143
+                mOuterPageChangeListener.onPageScrollStateChanged(state);
144
+            }
145
+        }
146
+    };
147
+
148
+    public boolean isCanLoop() {
149
+        return canLoop;
150
+    }
151
+
152
+    public void setCanLoop(boolean canLoop) {
153
+        this.canLoop = canLoop;
154
+        if (canLoop == false) {
155
+            setCurrentItem(getRealItem(), false);
156
+        }
157
+        if (mAdapter == null) return;
158
+        mAdapter.setCanLoop(canLoop);
159
+        mAdapter.notifyDataSetChanged();
160
+    }
161
+
162
+    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
163
+        this.onItemClickListener = onItemClickListener;
164
+    }
165
+}

+ 104 - 0
views/src/main/java/com/android/views/banner/CBPageAdapter.java

@@ -0,0 +1,104 @@
1
+package com.android.views.banner;
2
+
3
+import android.support.v4.view.PagerAdapter;
4
+import android.view.View;
5
+import android.view.ViewGroup;
6
+
7
+
8
+import com.android.views.R;
9
+
10
+import java.util.List;
11
+
12
+/**
13
+ * Created by Sai on 15/7/29.
14
+ */
15
+public class CBPageAdapter<T> extends PagerAdapter {
16
+    protected List<T> mDatas;
17
+    protected CBViewHolderCreator holderCreator;
18
+//    private View.OnClickListener onItemClickListener;
19
+    private boolean canLoop = true;
20
+    private CBLoopViewPager viewPager;
21
+    private final int MULTIPLE_COUNT = 300;
22
+
23
+    public int toRealPosition(int position) {
24
+        int realCount = getRealCount();
25
+        if (realCount == 0)
26
+            return 0;
27
+        int realPosition = position % realCount;
28
+        return realPosition;
29
+    }
30
+
31
+    @Override
32
+    public int getCount() {
33
+        return canLoop ? getRealCount()*MULTIPLE_COUNT : getRealCount();
34
+    }
35
+
36
+    public int getRealCount() {
37
+        return mDatas == null ? 0 : mDatas.size();
38
+    }
39
+
40
+    @Override
41
+    public Object instantiateItem(ViewGroup container, int position) {
42
+        int realPosition = toRealPosition(position);
43
+
44
+        View view = getView(realPosition, null, container);
45
+//        if(onItemClickListener != null) view.setOnClickListener(onItemClickListener);
46
+        container.addView(view);
47
+        return view;
48
+    }
49
+
50
+    @Override
51
+    public void destroyItem(ViewGroup container, int position, Object object) {
52
+        View view = (View) object;
53
+        container.removeView(view);
54
+    }
55
+
56
+    @Override
57
+    public void finishUpdate(ViewGroup container) {
58
+        int position = viewPager.getCurrentItem();
59
+        if (position == 0) {
60
+            position = viewPager.getFristItem();
61
+        } else if (position == getCount() - 1) {
62
+            position = viewPager.getLastItem();
63
+        }
64
+        try {
65
+            viewPager.setCurrentItem(position, false);
66
+        }catch (IllegalStateException e){}
67
+    }
68
+
69
+    @Override
70
+    public boolean isViewFromObject(View view, Object object) {
71
+        return view == object;
72
+    }
73
+
74
+    public void setCanLoop(boolean canLoop) {
75
+        this.canLoop = canLoop;
76
+    }
77
+
78
+    public void setViewPager(CBLoopViewPager viewPager) {
79
+        this.viewPager = viewPager;
80
+    }
81
+
82
+    public CBPageAdapter(CBViewHolderCreator holderCreator, List<T> datas) {
83
+        this.holderCreator = holderCreator;
84
+        this.mDatas = datas;
85
+    }
86
+
87
+    public View getView(int position, View view, ViewGroup container) {
88
+        Holder holder = null;
89
+        if (view == null) {
90
+            holder = (Holder) holderCreator.createHolder();
91
+            view = holder.createView(container.getContext());
92
+            view.setTag(R.id.cb_item_tag, holder);
93
+        } else {
94
+            holder = (Holder<T>) view.getTag(R.id.cb_item_tag);
95
+        }
96
+        if (mDatas != null && !mDatas.isEmpty())
97
+            holder.UpdateUI(container.getContext(), position, mDatas.get(position));
98
+        return view;
99
+    }
100
+
101
+//    public void setOnItemClickListener(View.OnClickListener onItemClickListener) {
102
+//        this.onItemClickListener = onItemClickListener;
103
+//    }
104
+}

+ 45 - 0
views/src/main/java/com/android/views/banner/CBPageChangeListener.java

@@ -0,0 +1,45 @@
1
+package com.android.views.banner;
2
+
3
+import android.support.v4.view.ViewPager;
4
+import android.widget.ImageView;
5
+
6
+import java.util.ArrayList;
7
+
8
+/**
9
+ * Created by Sai on 15/7/29.
10
+ * 翻页指示器适配器
11
+ */
12
+public class CBPageChangeListener implements ViewPager.OnPageChangeListener {
13
+    private ArrayList<ImageView> pointViews;
14
+    private int[] page_indicatorId;
15
+    private ViewPager.OnPageChangeListener onPageChangeListener;
16
+    public CBPageChangeListener(ArrayList<ImageView> pointViews, int page_indicatorId[]){
17
+        this.pointViews=pointViews;
18
+        this.page_indicatorId = page_indicatorId;
19
+    }
20
+    @Override
21
+    public void onPageScrollStateChanged(int state) {
22
+        if(onPageChangeListener != null)onPageChangeListener.onPageScrollStateChanged(state);
23
+    }
24
+
25
+    @Override
26
+    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
27
+        if(onPageChangeListener != null)onPageChangeListener.onPageScrolled(position,positionOffset,positionOffsetPixels);
28
+    }
29
+
30
+    @Override
31
+    public void onPageSelected(int index) {
32
+        for (int i = 0; i < pointViews.size(); i++) {
33
+            pointViews.get(index).setImageResource(page_indicatorId[1]);
34
+            if (index != i) {
35
+                pointViews.get(i).setImageResource(page_indicatorId[0]);
36
+            }
37
+        }
38
+        if(onPageChangeListener != null)onPageChangeListener.onPageSelected(index);
39
+
40
+    }
41
+
42
+    public void setOnPageChangeListener(ViewPager.OnPageChangeListener onPageChangeListener) {
43
+        this.onPageChangeListener = onPageChangeListener;
44
+    }
45
+}

+ 10 - 0
views/src/main/java/com/android/views/banner/CBViewHolderCreator.java

@@ -0,0 +1,10 @@
1
+package com.android.views.banner;
2
+/**
3
+ * @ClassName :  ViewHolderCreator 
4
+ * @Description : 
5
+ * @Author Sai
6
+ * @Date 2014年11月30日 下午3:29:34
7
+ */
8
+public interface CBViewHolderCreator<Holder> {
9
+	public Holder createHolder();
10
+}

+ 344 - 0
views/src/main/java/com/android/views/banner/ConvenientBanner.java

@@ -0,0 +1,344 @@
1
+package com.android.views.banner;
2
+
3
+import android.annotation.TargetApi;
4
+import android.content.Context;
5
+import android.content.res.TypedArray;
6
+import android.os.Build;
7
+import android.support.v4.view.ViewPager;
8
+import android.support.v4.view.ViewPager.PageTransformer;
9
+import android.util.AttributeSet;
10
+import android.view.LayoutInflater;
11
+import android.view.MotionEvent;
12
+import android.view.View;
13
+import android.view.ViewGroup;
14
+import android.widget.ImageView;
15
+import android.widget.LinearLayout;
16
+import android.widget.RelativeLayout;
17
+
18
+
19
+import com.android.views.R;
20
+
21
+import java.lang.ref.WeakReference;
22
+import java.lang.reflect.Field;
23
+import java.util.ArrayList;
24
+import java.util.List;
25
+
26
+/**
27
+ * 页面翻转控件,极方便的广告栏
28
+ * 支持无限循环,自动翻页,翻页特效
29
+ * @author Sai 支持自动翻页
30
+ */
31
+public class ConvenientBanner<T> extends LinearLayout {
32
+    private List<T> mDatas;
33
+    private int[] page_indicatorId;
34
+    private ArrayList<ImageView> mPointViews = new ArrayList<ImageView>();
35
+    private CBPageChangeListener pageChangeListener;
36
+    private ViewPager.OnPageChangeListener onPageChangeListener;
37
+    private CBPageAdapter pageAdapter;
38
+    private CBLoopViewPager viewPager;
39
+    private ViewPagerScroller scroller;
40
+    private ViewGroup loPageTurningPoint;
41
+    private long autoTurningTime;
42
+    private boolean turning;
43
+    private boolean canTurn = false;
44
+    private boolean manualPageable = true;
45
+    private boolean canLoop = true;
46
+    public enum PageIndicatorAlign{
47
+        ALIGN_PARENT_LEFT,ALIGN_PARENT_RIGHT,CENTER_HORIZONTAL
48
+    }
49
+    private AdSwitchTask adSwitchTask ;
50
+
51
+    public ConvenientBanner(Context context) {
52
+        super(context);
53
+        init(context);
54
+    }
55
+
56
+    public ConvenientBanner(Context context, AttributeSet attrs) {
57
+        super(context, attrs);
58
+        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ConvenientBanner);
59
+        canLoop = a.getBoolean(R.styleable.ConvenientBanner_canLoop,true);
60
+        a.recycle();
61
+        init(context);
62
+    }
63
+
64
+    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
65
+    public ConvenientBanner(Context context, AttributeSet attrs, int defStyleAttr) {
66
+        super(context, attrs, defStyleAttr);
67
+        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ConvenientBanner);
68
+        canLoop = a.getBoolean(R.styleable.ConvenientBanner_canLoop,true);
69
+        a.recycle();
70
+        init(context);
71
+    }
72
+
73
+    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
74
+    public ConvenientBanner(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
75
+        super(context, attrs, defStyleAttr, defStyleRes);
76
+        TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ConvenientBanner);
77
+        canLoop = a.getBoolean(R.styleable.ConvenientBanner_canLoop,true);
78
+        a.recycle();
79
+        init(context);
80
+    }
81
+
82
+    private void init(Context context) {
83
+        View hView = LayoutInflater.from(context).inflate(
84
+                R.layout.include_viewpager, this, true);
85
+        viewPager = (CBLoopViewPager) hView.findViewById(R.id.cbLoopViewPager);
86
+        loPageTurningPoint = (ViewGroup) hView
87
+                .findViewById(R.id.loPageTurningPoint);
88
+        initViewPagerScroll();
89
+
90
+        adSwitchTask = new AdSwitchTask(this);
91
+    }
92
+
93
+    static class AdSwitchTask implements Runnable {
94
+
95
+        private final WeakReference<ConvenientBanner> reference;
96
+
97
+        AdSwitchTask(ConvenientBanner convenientBanner) {
98
+            this.reference = new WeakReference<ConvenientBanner>(convenientBanner);
99
+        }
100
+
101
+        @Override
102
+        public void run() {
103
+            ConvenientBanner convenientBanner = reference.get();
104
+
105
+            if(convenientBanner != null){
106
+                if (convenientBanner.viewPager != null && convenientBanner.turning) {
107
+                    int page = convenientBanner.viewPager.getCurrentItem() + 1;
108
+                    convenientBanner.viewPager.setCurrentItem(page);
109
+                    convenientBanner.postDelayed(convenientBanner.adSwitchTask, convenientBanner.autoTurningTime);
110
+                }
111
+            }
112
+        }
113
+    }
114
+
115
+    public ConvenientBanner setPages(CBViewHolderCreator holderCreator,List<T> datas){
116
+        this.mDatas = datas;
117
+        pageAdapter = new CBPageAdapter(holderCreator,mDatas);
118
+        viewPager.setAdapter(pageAdapter,canLoop);
119
+
120
+        if (page_indicatorId != null)
121
+            setPageIndicator(page_indicatorId);
122
+        return this;
123
+    }
124
+
125
+    /**
126
+     * 通知数据变化
127
+     * 如果只是增加数据建议使用 notifyDataSetAdd()
128
+     */
129
+    public void notifyDataSetChanged(){
130
+        viewPager.getAdapter().notifyDataSetChanged();
131
+        if (page_indicatorId != null)
132
+            setPageIndicator(page_indicatorId);
133
+    }
134
+
135
+    /**
136
+     * 设置底部指示器是否可见
137
+     *
138
+     * @param visible
139
+     */
140
+    public ConvenientBanner setPointViewVisible(boolean visible) {
141
+        loPageTurningPoint.setVisibility(visible ? View.VISIBLE : View.GONE);
142
+        return this;
143
+    }
144
+
145
+    /**
146
+     * 底部指示器资源图片
147
+     *
148
+     * @param page_indicatorId
149
+     */
150
+    public ConvenientBanner setPageIndicator(int[] page_indicatorId) {
151
+        loPageTurningPoint.removeAllViews();
152
+        mPointViews.clear();
153
+        this.page_indicatorId = page_indicatorId;
154
+        if(mDatas==null)return this;
155
+        for (int count = 0; count < mDatas.size(); count++) {
156
+            // 翻页指示的点
157
+            ImageView pointView = new ImageView(getContext());
158
+            pointView.setPadding(5, 0, 5, 0);
159
+            if (mPointViews.isEmpty())
160
+                pointView.setImageResource(page_indicatorId[1]);
161
+            else
162
+                pointView.setImageResource(page_indicatorId[0]);
163
+            mPointViews.add(pointView);
164
+            loPageTurningPoint.addView(pointView);
165
+        }
166
+        pageChangeListener = new CBPageChangeListener(mPointViews,
167
+                page_indicatorId);
168
+        viewPager.setOnPageChangeListener(pageChangeListener);
169
+        pageChangeListener.onPageSelected(viewPager.getRealItem());
170
+        if(onPageChangeListener != null)pageChangeListener.setOnPageChangeListener(onPageChangeListener);
171
+
172
+        return this;
173
+    }
174
+
175
+    /**
176
+     * 指示器的方向
177
+     * @param align  三个方向:居左 (RelativeLayout.ALIGN_PARENT_LEFT),居中 (RelativeLayout.CENTER_HORIZONTAL),居右 (RelativeLayout.ALIGN_PARENT_RIGHT)
178
+     * @return
179
+     */
180
+    public ConvenientBanner setPageIndicatorAlign(PageIndicatorAlign align) {
181
+        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) loPageTurningPoint.getLayoutParams();
182
+        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, align == PageIndicatorAlign.ALIGN_PARENT_LEFT ? RelativeLayout.TRUE : 0);
183
+        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, align == PageIndicatorAlign.ALIGN_PARENT_RIGHT ? RelativeLayout.TRUE : 0);
184
+        layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL, align == PageIndicatorAlign.CENTER_HORIZONTAL ? RelativeLayout.TRUE : 0);
185
+        loPageTurningPoint.setLayoutParams(layoutParams);
186
+        return this;
187
+    }
188
+
189
+    /***
190
+     * 是否开启了翻页
191
+     * @return
192
+     */
193
+    public boolean isTurning() {
194
+        return turning;
195
+    }
196
+
197
+    /***
198
+     * 开始翻页
199
+     * @param autoTurningTime 自动翻页时间
200
+     * @return
201
+     */
202
+    public ConvenientBanner startTurning(long autoTurningTime) {
203
+        //如果是正在翻页的话先停掉
204
+        if(turning){
205
+            stopTurning();
206
+        }
207
+        //设置可以翻页并开启翻页
208
+        canTurn = true;
209
+        this.autoTurningTime = autoTurningTime;
210
+        turning = true;
211
+        postDelayed(adSwitchTask, autoTurningTime);
212
+        return this;
213
+    }
214
+
215
+    public void stopTurning() {
216
+        turning = false;
217
+        removeCallbacks(adSwitchTask);
218
+    }
219
+
220
+    /**
221
+     * 自定义翻页动画效果
222
+     *
223
+     * @param transformer
224
+     * @return
225
+     */
226
+    public ConvenientBanner setPageTransformer(PageTransformer transformer) {
227
+        viewPager.setPageTransformer(true, transformer);
228
+        return this;
229
+    }
230
+
231
+
232
+    /**
233
+     * 设置ViewPager的滑动速度
234
+     * */
235
+    private void initViewPagerScroll() {
236
+        try {
237
+            Field mScroller = null;
238
+            mScroller = ViewPager.class.getDeclaredField("mScroller");
239
+            mScroller.setAccessible(true);
240
+            scroller = new ViewPagerScroller(
241
+                    viewPager.getContext());
242
+            mScroller.set(viewPager, scroller);
243
+
244
+        } catch (NoSuchFieldException e) {
245
+            e.printStackTrace();
246
+        } catch (IllegalArgumentException e) {
247
+            e.printStackTrace();
248
+        } catch (IllegalAccessException e) {
249
+            e.printStackTrace();
250
+        }
251
+    }
252
+
253
+    public boolean isManualPageable() {
254
+        return viewPager.isCanScroll();
255
+    }
256
+
257
+    public void setManualPageable(boolean manualPageable) {
258
+        viewPager.setCanScroll(manualPageable);
259
+    }
260
+
261
+    //触碰控件的时候,翻页应该停止,离开的时候如果之前是开启了翻页的话则重新启动翻页
262
+    @Override
263
+    public boolean dispatchTouchEvent(MotionEvent ev) {
264
+
265
+        int action = ev.getAction();
266
+        if (action == MotionEvent.ACTION_UP||action == MotionEvent.ACTION_CANCEL||action == MotionEvent.ACTION_OUTSIDE) {
267
+            // 开始翻页
268
+            if (canTurn)startTurning(autoTurningTime);
269
+        } else if (action == MotionEvent.ACTION_DOWN) {
270
+            // 停止翻页
271
+            if (canTurn)stopTurning();
272
+        }
273
+        return super.dispatchTouchEvent(ev);
274
+    }
275
+
276
+    //获取当前的页面index
277
+    public int getCurrentItem(){
278
+        if (viewPager!=null) {
279
+            return viewPager.getRealItem();
280
+        }
281
+        return -1;
282
+    }
283
+    //设置当前的页面index
284
+    public void setcurrentitem(int index){
285
+        if (viewPager!=null) {
286
+            viewPager.setCurrentItem(index);
287
+        }
288
+    }
289
+
290
+    public ViewPager.OnPageChangeListener getOnPageChangeListener() {
291
+        return onPageChangeListener;
292
+    }
293
+
294
+    /**
295
+     * 设置翻页监听器
296
+     * @param onPageChangeListener
297
+     * @return
298
+     */
299
+    public ConvenientBanner setOnPageChangeListener(ViewPager.OnPageChangeListener onPageChangeListener) {
300
+        this.onPageChangeListener = onPageChangeListener;
301
+        //如果有默认的监听器(即是使用了默认的翻页指示器)则把用户设置的依附到默认的上面,否则就直接设置
302
+        if(pageChangeListener != null)pageChangeListener.setOnPageChangeListener(onPageChangeListener);
303
+        else viewPager.setOnPageChangeListener(onPageChangeListener);
304
+        return this;
305
+    }
306
+
307
+    public boolean isCanLoop() {
308
+        return viewPager.isCanLoop();
309
+    }
310
+
311
+    /**
312
+     * 监听item点击
313
+     * @param onItemClickListener
314
+     */
315
+    public ConvenientBanner setOnItemClickListener(OnItemClickListener onItemClickListener) {
316
+        if (onItemClickListener == null) {
317
+            viewPager.setOnItemClickListener(null);
318
+            return this;
319
+        }
320
+        viewPager.setOnItemClickListener(onItemClickListener);
321
+        return this;
322
+    }
323
+
324
+    /**
325
+     * 设置ViewPager的滚动速度
326
+     * @param scrollDuration
327
+     */
328
+    public void setScrollDuration(int scrollDuration){
329
+        scroller.setScrollDuration(scrollDuration);
330
+    }
331
+
332
+    public int getScrollDuration() {
333
+        return scroller.getScrollDuration();
334
+    }
335
+
336
+    public CBLoopViewPager getViewPager() {
337
+        return viewPager;
338
+    }
339
+
340
+    public void setCanLoop(boolean canLoop) {
341
+        this.canLoop = canLoop;
342
+        viewPager.setCanLoop(canLoop);
343
+    }
344
+}

+ 14 - 0
views/src/main/java/com/android/views/banner/Holder.java

@@ -0,0 +1,14 @@
1
+package com.android.views.banner;
2
+
3
+/**
4
+ * Created by Sai on 15/12/14.
5
+ * @param <T> 任何你指定的对象
6
+ */
7
+
8
+import android.content.Context;
9
+import android.view.View;
10
+
11
+public interface Holder<T>{
12
+    View createView(Context context);
13
+    void UpdateUI(Context context, int position, T data);
14
+}

+ 8 - 0
views/src/main/java/com/android/views/banner/OnItemClickListener.java

@@ -0,0 +1,8 @@
1
+package com.android.views.banner;
2
+
3
+/**
4
+ * Created by Sai on 15/11/13.
5
+ */
6
+public interface OnItemClickListener {
7
+    public void onItemClick(int position);
8
+}

+ 49 - 0
views/src/main/java/com/android/views/banner/ViewPagerScroller.java

@@ -0,0 +1,49 @@
1
+package com.android.views.banner;
2
+
3
+import android.content.Context;
4
+import android.view.animation.Interpolator;
5
+import android.widget.Scroller;
6
+
7
+public class ViewPagerScroller extends Scroller {
8
+	private int mScrollDuration = 800;// 滑动速度,值越大滑动越慢,滑动太快会使3d效果不明显
9
+	private boolean zero;
10
+
11
+	public ViewPagerScroller(Context context) {
12
+		super(context);
13
+	}
14
+
15
+	public ViewPagerScroller(Context context, Interpolator interpolator) {
16
+		super(context, interpolator);
17
+	}
18
+
19
+	public ViewPagerScroller(Context context, Interpolator interpolator,
20
+			boolean flywheel) {
21
+		super(context, interpolator, flywheel);
22
+	}
23
+
24
+	@Override
25
+	public void startScroll(int startX, int startY, int dx, int dy, int duration) {
26
+		super.startScroll(startX, startY, dx, dy, zero ? 0 : mScrollDuration);
27
+	}
28
+
29
+	@Override
30
+	public void startScroll(int startX, int startY, int dx, int dy) {
31
+		super.startScroll(startX, startY, dx, dy, zero ? 0 : mScrollDuration);
32
+	}
33
+
34
+	public int getScrollDuration() {
35
+		return mScrollDuration;
36
+	}
37
+
38
+	public void setScrollDuration(int scrollDuration) {
39
+		this.mScrollDuration = scrollDuration;
40
+	}
41
+
42
+	public boolean isZero() {
43
+		return zero;
44
+	}
45
+
46
+	public void setZero(boolean zero) {
47
+		this.zero = zero;
48
+	}
49
+}

+ 29 - 0
views/src/main/res/layout/include_viewpager.xml

@@ -0,0 +1,29 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+    android:layout_width="match_parent"
4
+    android:layout_height="match_parent"
5
+    android:orientation="vertical" >
6
+
7
+    <RelativeLayout
8
+        android:layout_width="match_parent"
9
+        android:layout_height="match_parent" >
10
+
11
+        <com.android.views.banner.CBLoopViewPager
12
+            android:id="@+id/cbLoopViewPager"
13
+            android:layout_width="match_parent"
14
+            android:layout_height="match_parent" />
15
+
16
+        <!-- 翻页指示点的viewgroup -->
17
+
18
+        <LinearLayout
19
+            android:id="@+id/loPageTurningPoint"
20
+            android:layout_width="wrap_content"
21
+            android:layout_height="wrap_content"
22
+            android:layout_alignParentBottom="true"
23
+            android:layout_margin="10dp"
24
+            android:layout_centerHorizontal="true"
25
+            android:orientation="horizontal" >
26
+        </LinearLayout>
27
+    </RelativeLayout>
28
+
29
+</LinearLayout>

+ 3 - 0
views/src/main/res/values/attrs.xml

@@ -73,4 +73,7 @@
73 73
         </attr>
74 74
     </declare-styleable>
75 75
 
76
+    <declare-styleable name="ConvenientBanner">
77
+        <attr name="canLoop" format="boolean" />
78
+    </declare-styleable>
76 79
 </resources>

+ 4 - 0
views/src/main/res/values/ids.xml

@@ -0,0 +1,4 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<resources>
3
+    <item name="cb_item_tag" type="id"></item>
4
+</resources>

adminSystem - Gogs: Go Git Service

Nenhuma Descrição

index.js 9.5KB

    /* Copyright 2012-2015, Yahoo Inc. Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. */ /*jshint maxlen: 300 */ var fs = require('fs'), path = require('path'), handlebars = require('handlebars').create(), annotator = require('./annotator'), helpers = require('./helpers'), templateFor = function (name) { return handlebars.compile(fs.readFileSync(path.resolve(__dirname, 'templates', name + '.txt'), 'utf8')); }, headerTemplate = templateFor('head'), footerTemplate = templateFor('foot'), detailTemplate = handlebars.compile([ '<tr>', '<td class="line-count quiet">{{#show_lines}}{{maxLines}}{{/show_lines}}</td>', '<td class="line-coverage quiet">{{#show_line_execution_counts lineCoverage}}{{maxLines}}{{/show_line_execution_counts}}</td>', '<td class="text"><pre class="prettyprint lang-js">{{#show_code annotatedCode}}{{/show_code}}</pre></td>', '</tr>\n' ].join('')), summaryTableHeader = [ '<div class="pad1">', '<table class="coverage-summary">', '<thead>', '<tr>', ' <th data-col="file" data-fmt="html" data-html="true" class="file">File</th>', ' <th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>', ' <th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>', ' <th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>', ' <th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>', ' <th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>', ' <th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>', ' <th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>', ' <th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>', ' <th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>', '</tr>', '</thead>', '<tbody>' ].join('\n'), summaryLineTemplate = handlebars.compile([ '<tr>', '<td class="file {{reportClasses.statements}}" data-value="{{file}}"><a href="{{output}}">{{file}}</a></td>', '<td data-value="{{metrics.statements.pct}}" class="pic {{reportClasses.statements}}"><div class="chart">{{#show_picture}}{{metrics.statements.pct}}{{/show_picture}}</div></td>', '<td data-value="{{metrics.statements.pct}}" class="pct {{reportClasses.statements}}">{{metrics.statements.pct}}%</td>', '<td data-value="{{metrics.statements.total}}" class="abs {{reportClasses.statements}}">{{metrics.statements.covered}}/{{metrics.statements.total}}</td>', '<td data-value="{{metrics.branches.pct}}" class="pct {{reportClasses.branches}}">{{metrics.branches.pct}}%</td>', '<td data-value="{{metrics.branches.total}}" class="abs {{reportClasses.branches}}">{{metrics.branches.covered}}/{{metrics.branches.total}}</td>', '<td data-value="{{metrics.functions.pct}}" class="pct {{reportClasses.functions}}">{{metrics.functions.pct}}%</td>', '<td data-value="{{metrics.functions.total}}" class="abs {{reportClasses.functions}}">{{metrics.functions.covered}}/{{metrics.functions.total}}</td>', '<td data-value="{{metrics.lines.pct}}" class="pct {{reportClasses.lines}}">{{metrics.lines.pct}}%</td>', '<td data-value="{{metrics.lines.total}}" class="abs {{reportClasses.lines}}">{{metrics.lines.covered}}/{{metrics.lines.total}}</td>', '</tr>\n' ].join('\n\t')), summaryTableFooter = [ '</tbody>', '</table>', '</div>' ].join('\n'), emptyClasses = { statements: 'empty', lines: 'empty', functions: 'empty', branches: 'empty' }; helpers.registerHelpers(handlebars); var standardLinkMapper = { getPath: function (node) { if (typeof node === 'string') { return node; } var filePath = node.getQualifiedName(); if (node.isSummary()) { if (filePath !== '') { filePath += "/index.html"; } else { filePath = "index.html"; } } else { filePath += ".html"; } return filePath; }, relativePath: function (source, target) { var targetPath = this.getPath(target), sourcePath = path.dirname(this.getPath(source)); return path.relative(sourcePath, targetPath); }, assetPath: function (node, name) { return this.relativePath(this.getPath(node), name); } }; function getBreadcrumbHtml(node, linkMapper) { var parent = node.getParent(), nodePath = [], linkPath; while (parent) { nodePath.push(parent); parent = parent.getParent(); } linkPath = nodePath.map(function (ancestor) { var target = linkMapper.relativePath(node, ancestor), name = ancestor.getRelativeName() || 'All files'; return '<a href="' + target + '">' + name + '</a>'; }); linkPath.reverse(); return linkPath.length > 0 ? linkPath.join(' / ') + ' ' + node.getRelativeName() : 'All files'; } function fillTemplate(node, templateData, linkMapper, context) { var summary = node.getCoverageSummary(); templateData.entity = node.getQualifiedName() || 'All files'; templateData.metrics = summary; templateData.reportClass = context.classForPercent('statements', summary.statements.pct); templateData.pathHtml = getBreadcrumbHtml(node, linkMapper); templateData.base = { css: linkMapper.assetPath(node, 'base.css') }; templateData.sorter = { js: linkMapper.assetPath(node, 'sorter.js'), image: linkMapper.assetPath(node, 'sort-arrow-sprite.png') }; templateData.blockNavigation = { js: linkMapper.assetPath(node, 'block-navigation.js'), }; templateData.prettify = { js: linkMapper.assetPath(node, 'prettify.js'), css: linkMapper.assetPath(node, 'prettify.css') }; } function HtmlReport(opts) { this.verbose = opts.verbose; this.linkMapper = opts.linkMapper || standardLinkMapper; this.subdir = opts.subdir || ''; this.date = Date(); this.skipEmpty = opts.skipEmpty; } HtmlReport.prototype.getTemplateData = function () { return { datetime: this.date }; }; HtmlReport.prototype.getWriter = function (context) { if (!this.subdir) { return context.writer; } return context.writer.writerForDir(this.subdir); }; HtmlReport.prototype.onStart = function (root, context) { var that = this, copyAssets = function (subdir, writer) { var srcDir = path.resolve(__dirname, 'assets', subdir); fs.readdirSync(srcDir).forEach(function (f) { var resolvedSource = path.resolve(srcDir, f), resolvedDestination = '.', stat = fs.statSync(resolvedSource), dest; if (stat.isFile()) { dest = resolvedDestination + '/' + f; if (this.verbose) { console.log('Write asset: ' + dest); } writer.copyFile(resolvedSource, dest); } }); }; ['.', 'vendor'].forEach(function (subdir) { copyAssets(subdir, that.getWriter(context)); }); }; function fixPct(metrics) { Object.keys(emptyClasses).forEach(function(key) { metrics[key].pct = 0; }); return metrics; } HtmlReport.prototype.onSummary = function (node, context) { var linkMapper = this.linkMapper, templateData = this.getTemplateData(), children = node.getChildren(), skipEmpty = this.skipEmpty, cw; fillTemplate(node, templateData, linkMapper, context); cw = this.getWriter(context).writeFile(linkMapper.getPath(node)); cw.write(headerTemplate(templateData)); cw.write(summaryTableHeader); children.forEach(function (child) { var metrics = child.getCoverageSummary(), isEmpty = metrics.isEmpty(); if (skipEmpty && isEmpty) { return; } var reportClasses = isEmpty ? emptyClasses : { statements: context.classForPercent('statements', metrics.statements.pct), lines: context.classForPercent('lines', metrics.lines.pct), functions: context.classForPercent('functions', metrics.functions.pct), branches: context.classForPercent('branches', metrics.branches.pct) }, data = { metrics: isEmpty ? fixPct(metrics) : metrics, reportClasses: reportClasses, file: child.getRelativeName(), output: linkMapper.relativePath(node, child) }; cw.write(summaryLineTemplate(data) + '\n'); }); cw.write(summaryTableFooter); cw.write(footerTemplate(templateData)); cw.close(); }; HtmlReport.prototype.onDetail = function (node, context) { var linkMapper = this.linkMapper, templateData = this.getTemplateData(), cw; fillTemplate(node, templateData, linkMapper, context); cw = this.getWriter(context).writeFile(linkMapper.getPath(node)); cw.write(headerTemplate(templateData)); cw.write('<pre><table class="coverage">\n'); cw.write(detailTemplate(annotator.annotateSourceCode(node.getFileCoverage(), context))); cw.write('</table></pre>\n'); cw.write(footerTemplate(templateData)); cw.close(); }; module.exports = HtmlReport;