(infiniteIndicatorLayout);
268 | }
269 |
270 | @Override
271 | public void handleMessage(Message msg) {
272 | super.handleMessage(msg);
273 |
274 | InfiniteIndicator infiniteIndicatorLayout = mWeakReference.get();
275 | if (infiniteIndicatorLayout != null) {
276 | switch (msg.what) {
277 | case MSG_SCROLL:
278 | infiniteIndicatorLayout.scrollOnce();
279 | infiniteIndicatorLayout.sendScrollMessage();
280 | default:
281 | break;
282 | }
283 | }
284 | }
285 | }
286 |
287 | @Override
288 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
289 | if (mIndicator != null) {
290 | mIndicator.onPageScrolled(getRealPosition(position), positionOffset, positionOffsetPixels);
291 | }
292 |
293 | if (configuration.getOnPageChangeListener() != null) {
294 | configuration.getOnPageChangeListener().onPageScrolled(
295 | getRealPosition(position), positionOffset, positionOffsetPixels);
296 | }
297 | }
298 |
299 | @Override
300 | public void onPageSelected(int position) {
301 | if (mIndicator != null) {
302 | mIndicator.onPageSelected(getRealPosition(position));
303 | }
304 | if (configuration.getOnPageChangeListener() != null) {
305 | configuration.getOnPageChangeListener().onPageSelected(getRealPosition(position));
306 | }
307 | }
308 |
309 | @Override
310 | public void onPageScrollStateChanged(int state) {
311 | if (mIndicator != null) {
312 | mIndicator.onPageScrollStateChanged(state);
313 | }
314 | if (configuration.getOnPageChangeListener() != null) {
315 | configuration.getOnPageChangeListener().onPageScrollStateChanged(state);
316 | }
317 | }
318 |
319 | public void setCurrentItem(int index) {
320 | if (index > getRealCount() - 1) {
321 | throw new IndexOutOfBoundsException("index is " + index + "current " +
322 | "list size is " + getRealCount());
323 | }
324 | scrollToIndex(index);
325 | }
326 | }
327 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/OnPageClickListener.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator;
2 |
3 | import cn.lightsky.infiniteindicator.Page;
4 |
5 | /**
6 | * Created by lightsky on 16/1/31.
7 | */
8 | public interface OnPageClickListener {
9 |
10 | void onPageClick(int position, Page page);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/Page.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator;
2 |
3 | /**
4 | * Created by xushuai on 2014/12/25.
5 | */
6 | public class Page {
7 | public String data = "";
8 | public Object res;
9 |
10 | public Page(Object res) {
11 | this.res = res;
12 | }
13 |
14 | public Page(String data, Object res) {
15 | this.data = data;
16 | this.res = res;
17 | }
18 |
19 | public Page(String data, Object res, OnPageClickListener listener) {
20 | this.data = data;
21 | this.res = res;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/ViewUtils.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator;
2 |
3 | import android.content.Context;
4 |
5 | /**
6 | * Created by lightsky on 2016/11/1.
7 | */
8 |
9 | public class ViewUtils {
10 | /**
11 | * @param context
12 | * @param dipValue
13 | * @return
14 | */
15 | public static int dip2px(Context context, float dipValue) {
16 | if (context == null) {
17 | return (int) dipValue;
18 | }
19 | final float scale = context.getResources().getDisplayMetrics().density;
20 | return (int) (dipValue * scale + 0.5f);
21 | }
22 |
23 | public static int px2dip(Context context, float pxValue) {
24 | if (context == null) {
25 | return (int) pxValue;
26 | }
27 | final float scale = context.getResources().getDisplayMetrics().density;
28 | return (int) (pxValue / scale + 0.5f);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/indicator/AnimIndicator.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator.indicator;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.provider.Settings;
6 | import android.support.v4.view.ViewPager;
7 | import android.util.AttributeSet;
8 | import android.view.Gravity;
9 | import android.view.View;
10 | import android.view.animation.Interpolator;
11 | import android.view.animation.LinearInterpolator;
12 | import android.widget.LinearLayout;
13 |
14 | import com.nineoldandroids.animation.AnimatorInflater;
15 | import com.nineoldandroids.animation.AnimatorSet;
16 |
17 | import cn.lightsky.infiniteindicator.R;
18 | import cn.lightsky.infiniteindicator.recycle.RecyleAdapter;
19 |
20 | public class AnimIndicator extends LinearLayout implements PageIndicator {
21 |
22 | private final static int DEFAULT_INDICATOR_WIDTH = 5;
23 | private int mIndicatorMargin;
24 | private int mIndicatorWidth;
25 | private int mIndicatorHeight;
26 | private int mCurrentPage = 0;
27 | private RecyleAdapter mRecyleAdapter;
28 | private int mAnimatorResId = R.animator.scale_with_alpha;
29 | private int mIndicatorBackground = R.drawable.white_radius;
30 | private AnimatorSet mAnimationOut;
31 | private AnimatorSet mAnimationIn;
32 |
33 | public AnimIndicator(Context context) {
34 | super(context);
35 | init(context, null);
36 | }
37 |
38 | public AnimIndicator(Context context, AttributeSet attrs) {
39 | super(context, attrs);
40 | init(context, attrs);
41 | }
42 |
43 | private void init(Context context, AttributeSet attrs) {
44 | setOrientation(LinearLayout.HORIZONTAL);
45 | setGravity(Gravity.CENTER);
46 | handleTypedArray(context, attrs);
47 | mAnimationOut = (AnimatorSet) AnimatorInflater.loadAnimator(context, mAnimatorResId);
48 | mAnimationOut.setInterpolator(new LinearInterpolator());
49 | mAnimationIn = (AnimatorSet) AnimatorInflater.loadAnimator(context, mAnimatorResId);
50 | mAnimationIn.setInterpolator(new ReverseInterpolator());
51 | }
52 |
53 | private void handleTypedArray(Context context, AttributeSet attrs) {
54 | if (attrs != null) {
55 | TypedArray typedArray =
56 | context.obtainStyledAttributes(attrs, R.styleable.AnimIndicator);
57 |
58 | mIndicatorWidth =
59 | typedArray.getDimensionPixelSize(R.styleable.AnimIndicator_ci_width, -1);
60 |
61 | mIndicatorHeight =
62 | typedArray.getDimensionPixelSize(R.styleable.AnimIndicator_ci_height, -1);
63 |
64 | mIndicatorMargin =
65 | typedArray.getDimensionPixelSize(R.styleable.AnimIndicator_ci_margin, -1);
66 |
67 | mAnimatorResId = typedArray.getResourceId(R.styleable.AnimIndicator_ci_animator,
68 | R.animator.scale_with_alpha);
69 |
70 | mIndicatorBackground = typedArray.getResourceId(R.styleable.AnimIndicator_ci_drawable,
71 | R.drawable.white_radius);
72 |
73 | typedArray.recycle();
74 | }
75 |
76 | mIndicatorWidth =
77 | (mIndicatorWidth == -1) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorWidth;
78 |
79 | mIndicatorHeight =
80 | (mIndicatorHeight == -1) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorHeight;
81 |
82 | mIndicatorMargin =
83 | (mIndicatorMargin == -1) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorMargin;
84 | }
85 |
86 | public void setViewPager(ViewPager viewPager) {
87 | mRecyleAdapter = (RecyleAdapter) viewPager.getAdapter();
88 | invalidIndicators();
89 | }
90 |
91 | @Override
92 | public void setCurrentItem(int item) {
93 | mCurrentPage = item;
94 | invalidIndicators();
95 | }
96 |
97 | @Override
98 | public void notifyDataSetChanged() {
99 | mCurrentPage = 0;
100 | invalidIndicators();
101 | }
102 |
103 | @Override
104 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
105 |
106 | }
107 |
108 | @Override
109 | public void onPageSelected(int position) {
110 | if (getChildAt(mCurrentPage) == null)
111 | return;
112 |
113 | mAnimationIn.setTarget(getChildAt(mCurrentPage));
114 | mAnimationIn.start();
115 | mAnimationOut.setTarget(getChildAt(position));
116 | mAnimationOut.start();
117 |
118 | mCurrentPage = position;
119 | }
120 |
121 | @Override
122 | public void onPageScrollStateChanged(int state) {
123 |
124 | }
125 |
126 | private void invalidIndicators() {
127 | removeAllViews();
128 |
129 | if (mRecyleAdapter == null) {
130 | return;
131 | }
132 |
133 | int count = mRecyleAdapter.getRealCount();
134 | if (count < 2) {
135 | return;
136 | }
137 |
138 | for (int i = 0; i < count; i++) {
139 | View indicator = new View(getContext());
140 | indicator.setBackgroundResource(mIndicatorBackground);
141 | addView(indicator, mIndicatorWidth, mIndicatorHeight);
142 | LayoutParams lp = (LayoutParams) indicator.getLayoutParams();
143 | lp.leftMargin = mIndicatorMargin;
144 | lp.rightMargin = mIndicatorMargin;
145 | indicator.setLayoutParams(lp);
146 |
147 | mAnimationOut.setTarget(indicator);
148 | mAnimationOut.start();
149 | }
150 |
151 | mAnimationOut.setTarget(getChildAt(mCurrentPage));
152 | mAnimationOut.start();
153 | }
154 |
155 | private class ReverseInterpolator implements Interpolator {
156 | @Override
157 | public float getInterpolation(float value) {
158 | return Math.abs(1.0f - value);
159 | }
160 | }
161 |
162 | public int dip2px(float dpValue) {
163 | final float scale = getResources().getDisplayMetrics().density;
164 | return (int) (dpValue * scale + 0.5f);
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/indicator/CircleIndicator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Patrik Akerfeldt
3 | * Copyright (C) 2011 Jake Wharton
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package cn.lightsky.infiniteindicator.indicator;
18 |
19 | import android.content.Context;
20 | import android.content.res.Resources;
21 | import android.content.res.TypedArray;
22 | import android.graphics.Canvas;
23 | import android.graphics.Paint;
24 | import android.graphics.Paint.Style;
25 | import android.graphics.drawable.Drawable;
26 | import android.support.v4.view.MotionEventCompat;
27 | import android.support.v4.view.ViewConfigurationCompat;
28 | import android.support.v4.view.ViewPager;
29 | import android.util.AttributeSet;
30 | import android.view.MotionEvent;
31 | import android.view.View;
32 | import android.view.ViewConfiguration;
33 |
34 | import cn.lightsky.infiniteindicator.R;
35 | import cn.lightsky.infiniteindicator.recycle.RecyleAdapter;
36 |
37 | import static android.graphics.Paint.ANTI_ALIAS_FLAG;
38 | import static android.widget.LinearLayout.HORIZONTAL;
39 | import static android.widget.LinearLayout.VERTICAL;
40 |
41 | /**
42 | * Draws circles (one for each view). The current view position is filled and
43 | * others are only stroked.
44 | *
45 | * Thanks to : https://github.com/JakeWharton/Android-ViewPagerIndicator
46 | */
47 | public class CircleIndicator extends View implements PageIndicator {
48 | private static final int INVALID_POINTER = -1;
49 |
50 | private float mRadius;
51 | private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG);
52 | private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG);
53 | private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG);
54 | private ViewPager mViewPager;
55 | private int mCurrentPage;
56 | private int mSnapPage;
57 | private float mPageOffset;
58 | private int mScrollState;
59 | private int mOrientation;
60 | private boolean mCentered;
61 | private boolean mSnap = true;
62 |
63 | private int mTouchSlop;
64 | private float mLastMotionX = -1;
65 | private int mActivePointerId = INVALID_POINTER;
66 | private boolean mIsDragging;
67 | private int mRealCount;
68 | private RecyleAdapter mRecyleAdapter;
69 |
70 |
71 | public CircleIndicator(Context context) {
72 | this(context, null);
73 | }
74 |
75 | public CircleIndicator(Context context, AttributeSet attrs) {
76 | this(context, attrs, R.attr.vpiCirclePageIndicatorStyle);
77 | }
78 |
79 | public CircleIndicator(Context context, AttributeSet attrs, int defStyle) {
80 | super(context, attrs, defStyle);
81 | if (isInEditMode()) return;
82 |
83 | //Load defaults from resources
84 | final Resources res = getResources();
85 | final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color);
86 | final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color);
87 | final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation);
88 | final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color);
89 | final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width);
90 | final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius);
91 | final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered);
92 | final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap);
93 |
94 | //Retrieve styles attributes
95 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0);
96 |
97 | mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered);
98 | mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation);
99 | mPaintPageFill.setStyle(Style.FILL);
100 | mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor));
101 | mPaintStroke.setStyle(Style.STROKE);
102 | mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor));
103 | mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth));
104 | mPaintFill.setStyle(Style.FILL);
105 | mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor));
106 | mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius);
107 |
108 | Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background);
109 | if (background != null) {
110 | setBackgroundDrawable(background);
111 | }
112 |
113 | a.recycle();
114 |
115 | final ViewConfiguration configuration = ViewConfiguration.get(context);
116 | mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);
117 | }
118 |
119 | public void setRealViewCount(int viewCount) {
120 | mRealCount = viewCount;
121 | }
122 |
123 | public void setCentered(boolean centered) {
124 | mCentered = centered;
125 | invalidate();
126 | }
127 |
128 | public boolean isCentered() {
129 | return mCentered;
130 | }
131 |
132 | public void setPageColor(int pageColor) {
133 | mPaintPageFill.setColor(pageColor);
134 | invalidate();
135 | }
136 |
137 | public int getPageColor() {
138 | return mPaintPageFill.getColor();
139 | }
140 |
141 | public void setFillColor(int fillColor) {
142 | mPaintFill.setColor(fillColor);
143 | invalidate();
144 | }
145 |
146 | public int getFillColor() {
147 | return mPaintFill.getColor();
148 | }
149 |
150 | public void setOrientation(int orientation) {
151 | switch (orientation) {
152 | case HORIZONTAL:
153 | case VERTICAL:
154 | mOrientation = orientation;
155 | requestLayout();
156 | break;
157 |
158 | default:
159 | throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL.");
160 | }
161 | }
162 |
163 | public int getOrientation() {
164 | return mOrientation;
165 | }
166 |
167 | public void setStrokeColor(int strokeColor) {
168 | mPaintStroke.setColor(strokeColor);
169 | invalidate();
170 | }
171 |
172 | public int getStrokeColor() {
173 | return mPaintStroke.getColor();
174 | }
175 |
176 | public void setStrokeWidth(float strokeWidth) {
177 | mPaintStroke.setStrokeWidth(strokeWidth);
178 | invalidate();
179 | }
180 |
181 | public float getStrokeWidth() {
182 | return mPaintStroke.getStrokeWidth();
183 | }
184 |
185 | public void setRadius(float radius) {
186 | mRadius = radius;
187 | invalidate();
188 | }
189 |
190 | public float getRadius() {
191 | return mRadius;
192 | }
193 |
194 | public void setSnap(boolean snap) {
195 | mSnap = snap;
196 | invalidate();
197 | }
198 |
199 | public boolean isSnap() {
200 | return mSnap;
201 | }
202 |
203 | @Override
204 | protected void onDraw(Canvas canvas) {
205 | super.onDraw(canvas);
206 |
207 | if (mRecyleAdapter == null)
208 | return;
209 |
210 | final int count = mRecyleAdapter.getRealCount();
211 | if (count <= 1) {
212 | return;
213 | }
214 |
215 | int longSize;
216 | int longPaddingBefore;
217 | int longPaddingAfter;
218 | int shortPaddingBefore;
219 | if (mOrientation == HORIZONTAL) {
220 | longSize = getWidth();
221 | longPaddingBefore = getPaddingLeft();
222 | longPaddingAfter = getPaddingRight();
223 | shortPaddingBefore = getPaddingTop();
224 | } else {
225 | longSize = getHeight();
226 | longPaddingBefore = getPaddingTop();
227 | longPaddingAfter = getPaddingBottom();
228 | shortPaddingBefore = getPaddingLeft();
229 | }
230 |
231 | final float threeRadius = mRadius * 3;
232 | final float shortOffset = shortPaddingBefore + mRadius;
233 | float longOffset = longPaddingBefore + mRadius;
234 | if (mCentered) {
235 | longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f)
236 | - ((count * threeRadius) / 2.0f);
237 | }
238 |
239 | float dX;
240 | float dY;
241 |
242 | float pageFillRadius = mRadius;
243 | if (mPaintStroke.getStrokeWidth() > 0) {
244 | pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f;
245 | }
246 |
247 | //Draw stroked circles
248 | for (int iLoop = 0; iLoop < count; iLoop++) {
249 | float drawLong = longOffset + (iLoop * threeRadius);
250 | if (mOrientation == HORIZONTAL) {
251 | dX = drawLong;
252 | dY = shortOffset;
253 | } else {
254 | dX = shortOffset;
255 | dY = drawLong;
256 | }
257 | // Only paint fill if not completely transparent
258 | if (mPaintPageFill.getAlpha() > 0) {
259 | canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill);
260 | }
261 |
262 | // Only paint stroke if a stroke width was non-zero
263 | if (pageFillRadius != mRadius) {
264 | canvas.drawCircle(dX, dY, mRadius, mPaintStroke);
265 | }
266 | }
267 |
268 | //Draw the filled circle according to the current scroll
269 | float cx = mSnapPage % count * threeRadius;
270 | if (mOrientation == HORIZONTAL) {
271 | dX = longOffset + cx;
272 | dY = shortOffset;
273 | } else {
274 | dX = shortOffset;
275 | dY = longOffset + cx;
276 | }
277 | canvas.drawCircle(dX, dY, mRadius, mPaintFill);
278 | }
279 |
280 | public boolean onTouchEvent(MotionEvent ev) {
281 | if (mViewPager == null || mRecyleAdapter.getCount() == 0) {
282 | return false;
283 | }
284 |
285 | final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
286 | switch (action) {
287 | case MotionEvent.ACTION_DOWN:
288 | mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
289 | mLastMotionX = ev.getX();
290 | break;
291 |
292 | case MotionEvent.ACTION_MOVE: {
293 | final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
294 | final float x = MotionEventCompat.getX(ev, activePointerIndex);
295 | final float deltaX = x - mLastMotionX;
296 |
297 | if (!mIsDragging) {
298 | if (Math.abs(deltaX) > mTouchSlop) {
299 | mIsDragging = true;
300 | }
301 | }
302 |
303 | if (mIsDragging) {
304 | mLastMotionX = x;
305 | if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) {
306 | mViewPager.fakeDragBy(deltaX);
307 | }
308 | }
309 |
310 | break;
311 | }
312 |
313 | case MotionEvent.ACTION_CANCEL:
314 | case MotionEvent.ACTION_UP:
315 | if (!mIsDragging) {
316 | final int count = mViewPager.getAdapter().getCount();
317 | final int width = getWidth();
318 | final float halfWidth = width / 2f;
319 | final float sixthWidth = width / 6f;
320 |
321 | if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) {
322 | if (action != MotionEvent.ACTION_CANCEL) {
323 | mViewPager.setCurrentItem(mCurrentPage - 1);
324 | }
325 | return true;
326 | } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) {
327 | if (action != MotionEvent.ACTION_CANCEL) {
328 | mViewPager.setCurrentItem(mCurrentPage + 1);
329 | }
330 | return true;
331 | }
332 | }
333 |
334 | mIsDragging = false;
335 | mActivePointerId = INVALID_POINTER;
336 | if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
337 | break;
338 |
339 | case MotionEventCompat.ACTION_POINTER_DOWN: {
340 | final int index = MotionEventCompat.getActionIndex(ev);
341 | mLastMotionX = MotionEventCompat.getX(ev, index);
342 | mActivePointerId = MotionEventCompat.getPointerId(ev, index);
343 | break;
344 | }
345 |
346 | case MotionEventCompat.ACTION_POINTER_UP:
347 | final int pointerIndex = MotionEventCompat.getActionIndex(ev);
348 | final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
349 | if (pointerId == mActivePointerId) {
350 | final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
351 | mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
352 | }
353 | mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId));
354 | break;
355 | }
356 |
357 | return true;
358 | }
359 |
360 | @Override
361 | public void setViewPager(ViewPager view) {
362 | if (mViewPager == view) {
363 | return;
364 | }
365 | mViewPager = view;
366 | mRecyleAdapter = (RecyleAdapter) mViewPager.getAdapter();
367 | }
368 |
369 | @Override
370 | public void setCurrentItem(int item) {
371 | mCurrentPage = item;
372 | invalidate();
373 | }
374 |
375 | @Override
376 | public void notifyDataSetChanged() {
377 | mCurrentPage = 0;
378 | invalidate();
379 | }
380 |
381 | @Override
382 | public void onPageScrollStateChanged(int state) {
383 | mScrollState = state;
384 | }
385 |
386 | @Override
387 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
388 | mCurrentPage = position;
389 | mPageOffset = positionOffset;
390 | invalidate();
391 | }
392 |
393 | @Override
394 | public void onPageSelected(int position) {
395 | if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) {
396 | mCurrentPage = position;
397 | mSnapPage = position;
398 | invalidate();
399 | }
400 | }
401 |
402 |
403 | /*
404 | * (non-Javadoc)
405 | *
406 | * @see android.view.View#onMeasure(int, int)
407 | */
408 | @Override
409 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
410 | if (mOrientation == HORIZONTAL) {
411 | setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec));
412 | } else {
413 | setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec));
414 | }
415 | }
416 |
417 | /**
418 | * Determines the width of this view
419 | *
420 | * @param measureSpec
421 | * A measureSpec packed into an int
422 | * @return The width of the view, honoring constraints from measureSpec
423 | */
424 | private int measureLong(int measureSpec) {
425 | int result;
426 | int specMode = MeasureSpec.getMode(measureSpec);
427 | int specSize = MeasureSpec.getSize(measureSpec);
428 |
429 | if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) {
430 | //We were told how big to be
431 | result = specSize;
432 | } else {
433 | //Calculate the width according the views count
434 | final int count = mRecyleAdapter.getRealCount();
435 | result = (int)(getPaddingLeft() + getPaddingRight()
436 | + (count * 2 * mRadius) + (count - 1) * mRadius + 1);
437 | //Respect AT_MOST value if that was what is called for by measureSpec
438 | if (specMode == MeasureSpec.AT_MOST) {
439 | result = Math.min(result, specSize);
440 | }
441 | }
442 | return result;
443 | }
444 |
445 | /**
446 | * Determines the height of this view
447 | *
448 | * @param measureSpec
449 | * A measureSpec packed into an int
450 | * @return The height of the view, honoring constraints from measureSpec
451 | */
452 | private int measureShort(int measureSpec) {
453 | int result;
454 | int specMode = MeasureSpec.getMode(measureSpec);
455 | int specSize = MeasureSpec.getSize(measureSpec);
456 |
457 | if (specMode == MeasureSpec.EXACTLY) {
458 | //We were told how big to be
459 | result = specSize;
460 | } else {
461 | //Measure the height
462 | result = (int)(2 * mRadius + getPaddingTop() + getPaddingBottom() + 1);
463 | //Respect AT_MOST value if that was what is called for by measureSpec
464 | if (specMode == MeasureSpec.AT_MOST) {
465 | result = Math.min(result, specSize);
466 | }
467 | }
468 | return result;
469 | }
470 | }
471 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/indicator/PageIndicator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Patrik Akerfeldt
3 | * Copyright (C) 2011 Jake Wharton
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package cn.lightsky.infiniteindicator.indicator;
19 |
20 | import android.support.v4.view.ViewPager;
21 |
22 | /**
23 | * A PageIndicator is responsible to show an visual indicator on the total views
24 | * number and the current visible view.
25 | */
26 | public interface PageIndicator extends ViewPager.OnPageChangeListener {
27 |
28 | /**
29 | * Bind the indicator to a ViewPager.
30 | *
31 | * @param view
32 | */
33 | void setViewPager(ViewPager view);
34 |
35 | /**
36 | * Set the current page of indicator.
37 | *
38 | * This must be used if you need to set the page before
39 | * the views are drawn on screen (e.g., default start page).
40 | *
41 | * @param item
42 | */
43 | void setCurrentItem(int item);
44 |
45 | /**
46 | * Notify the indicator that the page list has changed.
47 | */
48 | void notifyDataSetChanged();
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/recycle/BaseViewBinder.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator.recycle;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 |
9 | import cn.lightsky.infiniteindicator.ImageLoader;
10 | import cn.lightsky.infiniteindicator.IndicatorConfiguration;
11 | import cn.lightsky.infiniteindicator.OnPageClickListener;
12 | import cn.lightsky.infiniteindicator.Page;
13 | import cn.lightsky.infiniteindicator.R;
14 |
15 | /**
16 | * Created by lightsky on 2016/11/18.
17 | */
18 |
19 | public class BaseViewBinder implements ViewBinder {
20 |
21 | @Override
22 | public View bindView(Context context,
23 | final int position,
24 | final Page page,
25 | ImageLoader imageLoader,
26 | final OnPageClickListener mOnPageClickListener,
27 | View convertView,
28 | ViewGroup container) {
29 |
30 | ViewHolder holder;
31 | if (convertView != null) {
32 | holder = (ViewHolder) convertView.getTag();
33 | } else {
34 | convertView = LayoutInflater.from(context).inflate(R.layout.simple_slider_view, null);
35 | holder = new ViewHolder(convertView);
36 | convertView.setTag(holder);
37 | }
38 |
39 | if (holder.target != null) {
40 | if (mOnPageClickListener != null) {
41 | holder.target.setOnClickListener(new View.OnClickListener() {
42 | @Override
43 | public void onClick(View v) {
44 | mOnPageClickListener.onPageClick(position, page);
45 | }
46 | });
47 | }
48 |
49 | if (imageLoader != null) {
50 | imageLoader.load(context, holder.target, page.res);
51 | }
52 | }
53 |
54 | return convertView;
55 | }
56 |
57 | private static class ViewHolder {
58 | final ImageView target;
59 |
60 | public ViewHolder(View view) {
61 | target = (ImageView) view.findViewById(R.id.slider_image);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/recycle/RecycleBin.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator.recycle;
2 |
3 | import android.os.Build;
4 | import android.util.SparseArray;
5 | import android.view.View;
6 |
7 | /**
8 | * The RecycleBin facilitates reuse of views across layouts. The RecycleBin has two levels of
9 | * storage: ActiveViews and ScrapViews. ActiveViews are those views which were onscreen at the
10 | * start of a layout. By construction, they are displaying current information. At the end of
11 | * layout, all views in ActiveViews are demoted to ScrapViews. ScrapViews are old views that
12 | * could potentially be used by the adapter to avoid allocating views unnecessarily.
13 | *
14 | * This class was taken from Android's implementation of {@link android.widget.AbsListView} which
15 | * is copyrighted 2006 The Android Open Source Project.
16 | */
17 | public class RecycleBin {
18 | /**
19 | * Views that were on screen at the start of layout. This array is populated at the start of
20 | * layout, and at the end of layout all view in activeViews are moved to scrapViews.
21 | * Views in activeViews represent a contiguous range of Views, with position of the first
22 | * view store in mFirstActivePosition.
23 | */
24 | private View[] activeViews = new View[0];
25 | private int[] activeViewTypes = new int[0];
26 |
27 | /** Unsorted views that can be used by the adapter as a convert view. */
28 | private SparseArray[] scrapViews;
29 |
30 | private int viewTypeCount;
31 |
32 | private SparseArray currentScrapViews;
33 |
34 | public void setViewTypeCount(int viewTypeCount) {
35 | if (viewTypeCount < 1) {
36 | throw new IllegalArgumentException("Can't have a viewTypeCount < 1");
37 | }
38 | //noinspection unchecked
39 | SparseArray[] scrapViews = new SparseArray[viewTypeCount];
40 | for (int i = 0; i < viewTypeCount; i++) {
41 | scrapViews[i] = new SparseArray();
42 | }
43 | this.viewTypeCount = viewTypeCount;
44 | currentScrapViews = scrapViews[0];
45 | this.scrapViews = scrapViews;
46 | }
47 |
48 | protected boolean shouldRecycleViewType(int viewType) {
49 | return viewType >= 0;
50 | }
51 |
52 | /** @return A view from the ScrapViews collection. These are unordered. */
53 | View getScrapView(int position, int viewType) {
54 | if (viewTypeCount == 1) {
55 | return retrieveFromScrap(currentScrapViews, position);
56 | } else if (viewType >= 0 && viewType < scrapViews.length) {
57 | return retrieveFromScrap(scrapViews[viewType], position);
58 | }
59 | return null;
60 | }
61 |
62 | /**
63 | * Put a view into the ScrapViews list. These views are unordered.
64 | *
65 | * @param scrap The view to add
66 | */
67 | void addScrapView(View scrap, int position, int viewType) {
68 | if (viewTypeCount == 1) {
69 | currentScrapViews.put(position, scrap);
70 | } else {
71 | scrapViews[viewType].put(position, scrap);
72 | }
73 |
74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
75 | scrap.setAccessibilityDelegate(null);
76 | }
77 | }
78 |
79 | /** Move all views remaining in activeViews to scrapViews. */
80 | void scrapActiveViews() {
81 | final View[] activeViews = this.activeViews;
82 | final int[] activeViewTypes = this.activeViewTypes;
83 | final boolean multipleScraps = viewTypeCount > 1;
84 |
85 | SparseArray scrapViews = currentScrapViews;
86 | final int count = activeViews.length;
87 | for (int i = count - 1; i >= 0; i--) {
88 | final View victim = activeViews[i];
89 | if (victim != null) {
90 | int whichScrap = activeViewTypes[i];
91 |
92 | activeViews[i] = null;
93 | activeViewTypes[i] = -1;
94 |
95 | if (!shouldRecycleViewType(whichScrap)) {
96 | continue;
97 | }
98 |
99 | if (multipleScraps) {
100 | scrapViews = this.scrapViews[whichScrap];
101 | }
102 | scrapViews.put(i, victim);
103 |
104 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
105 | victim.setAccessibilityDelegate(null);
106 | }
107 | }
108 | }
109 |
110 | pruneScrapViews();
111 | }
112 |
113 | /**
114 | * Makes sure that the size of scrapViews does not exceed the size of activeViews.
115 | * (This can happen if an adapter does not recycle its views).
116 | */
117 | private void pruneScrapViews() {
118 | final int maxViews = activeViews.length;
119 | final int viewTypeCount = this.viewTypeCount;
120 | final SparseArray[] scrapViews = this.scrapViews;
121 | for (int i = 0; i < viewTypeCount; ++i) {
122 | final SparseArray scrapPile = scrapViews[i];
123 | int size = scrapPile.size();
124 | final int extras = size - maxViews;
125 | size--;
126 | for (int j = 0; j < extras; j++) {
127 | scrapPile.remove(scrapPile.keyAt(size--));
128 | }
129 | }
130 | }
131 |
132 | static View retrieveFromScrap(SparseArray scrapViews, int position) {
133 | int size = scrapViews.size();
134 | if (size > 0) {
135 | // See if we still have a view for this position.
136 | for (int i = 0; i < size; i++) {
137 | int fromPosition = scrapViews.keyAt(i);
138 | View view = scrapViews.get(fromPosition);
139 | if (fromPosition == position) {
140 | scrapViews.remove(fromPosition);
141 | return view;
142 | }
143 | }
144 | int index = size - 1;
145 | View r = scrapViews.valueAt(index);
146 | scrapViews.remove(scrapViews.keyAt(index));
147 | return r;
148 | } else {
149 | return null;
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/recycle/RecyclingPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator.recycle;
2 |
3 | import android.support.v4.view.PagerAdapter;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.AdapterView;
7 |
8 | /**
9 | * A {@link android.support.v4.view.PagerAdapter} which behaves like an {@link android.widget.Adapter} with view types and
10 | * view recycling.
11 | */
12 | public abstract class RecyclingPagerAdapter extends PagerAdapter {
13 | static final int IGNORE_ITEM_VIEW_TYPE = AdapterView.ITEM_VIEW_TYPE_IGNORE;
14 |
15 | private final RecycleBin recycleBin;
16 | private DataChangeListener mDataChangeListener;
17 |
18 | public interface DataChangeListener {
19 | void notifyDataChange();
20 | }
21 |
22 | public DataChangeListener getDataChangeListener() {
23 | return mDataChangeListener;
24 | }
25 |
26 | public void setDataChangeListener(DataChangeListener dataChangeListener) {
27 | this.mDataChangeListener = dataChangeListener;
28 | }
29 |
30 | public RecyclingPagerAdapter() {
31 | this(new RecycleBin());
32 | }
33 |
34 | RecyclingPagerAdapter(RecycleBin recycleBin) {
35 | this.recycleBin = recycleBin;
36 | recycleBin.setViewTypeCount(getViewTypeCount());
37 | }
38 |
39 | @Override
40 | public void notifyDataSetChanged() {
41 | recycleBin.scrapActiveViews();
42 | if (mDataChangeListener != null) {
43 | mDataChangeListener.notifyDataChange();
44 | }
45 | super.notifyDataSetChanged();
46 | }
47 |
48 | @Override
49 | public final Object instantiateItem(ViewGroup container, int position) {
50 | int viewType = getItemViewType(position);
51 | View view = null;
52 | if (viewType != IGNORE_ITEM_VIEW_TYPE) {
53 | view = recycleBin.getScrapView(position, viewType);
54 | }
55 | view = getView(position, view, container);
56 | container.addView(view);
57 | return view;
58 | }
59 |
60 | @Override
61 | public final void destroyItem(ViewGroup container, int position, Object object) {
62 | View view = (View) object;
63 | container.removeView(view);
64 | int viewType = getItemViewType(position);
65 | if (viewType != IGNORE_ITEM_VIEW_TYPE) {
66 | recycleBin.addScrapView(view, position, viewType);
67 | }
68 | }
69 |
70 | @Override
71 | public final boolean isViewFromObject(View view, Object object) {
72 | return view == object;
73 | }
74 |
75 | /**
76 | *
77 | * Returns the number of types of Views that will be created by
78 | * {@link #getView}. Each type represents a set of views that can be
79 | * converted in {@link #getView}. If the adapter always returns the same
80 | * type of View for all items, this method should return 1.
81 | *
82 | *
83 | * This method will only be called when when the adapter is set on the
84 | * the {@link android.widget.AdapterView}.
85 | *
86 | *
87 | * @return The number of types of Views that will be created by this adapter
88 | */
89 | public int getViewTypeCount() {
90 | return 1;
91 | }
92 |
93 | /**
94 | * Get the type of View that will be created by {@link #getView} for the specified item.
95 | *
96 | * @param position The position of the item within the adapter's data set whose view type we
97 | * want.
98 | * @return An integer representing the type of View. Two views should share the same type if one
99 | * can be converted to the other in {@link #getView}. Note: Integers must be in the
100 | * range 0 to {@link #getViewTypeCount} - 1. {@link #IGNORE_ITEM_VIEW_TYPE} can
101 | * also be returned.
102 | * @see #IGNORE_ITEM_VIEW_TYPE
103 | */
104 | @SuppressWarnings("UnusedParameters") // Argument potentially used by subclasses.
105 | public int getItemViewType(int position) {
106 | return 0;
107 | }
108 |
109 | /**
110 | * Get a View that displays the data at the specified position in the data set. You can either
111 | * create a View manually or inflate it from an XML layout file. When the View is inflated, the
112 | * parent View (GridView, ListView...) will apply default layout parameters unless you use
113 | * {@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)}
114 | * to specify a root view and to prevent attachment to the root.
115 | *
116 | * @param position The position of the item within the adapter's data set of the item whose view
117 | * we want.
118 | * @param convertView The old view to reuse, if possible. Note: You should check that this view
119 | * is non-null and of an appropriate type before using. If it is not possible to convert
120 | * this view to display the correct data, this method can create a new view.
121 | * Heterogeneous lists can specify their number of view types, so that this View is
122 | * always of the right type (see {@link #getViewTypeCount()} and
123 | * {@link #getItemViewType(int)}).
124 | * @param container The parent that this view will eventually be attached to
125 | * @return A View corresponding to the data at the specified position.
126 | */
127 | public abstract View getView(int position, View convertView, ViewGroup container);
128 | }
129 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/recycle/RecyleAdapter.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator.recycle;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | import cn.lightsky.infiniteindicator.ImageLoader;
11 | import cn.lightsky.infiniteindicator.OnPageClickListener;
12 | import cn.lightsky.infiniteindicator.Page;
13 |
14 | import static cn.lightsky.infiniteindicator.InfiniteIndicator.PAGE_COUNT_FACTOR;
15 |
16 | public class RecyleAdapter extends RecyclingPagerAdapter {
17 |
18 | private ViewBinder mViewBinder;
19 | private Context mContext;
20 | private ImageLoader mImageLoader;
21 | private OnPageClickListener mOnPageClickListener;
22 | private List mPageList = new ArrayList<>();
23 | private boolean isLoop = true;
24 |
25 | public RecyleAdapter(Context context, ViewBinder viewBinder) {
26 | this(context, viewBinder,null);
27 | }
28 |
29 | public RecyleAdapter(Context context, ViewBinder viewBinder, OnPageClickListener onPageClickListener) {
30 | this.mContext = context;
31 | this.mOnPageClickListener = onPageClickListener;
32 | this.mViewBinder = viewBinder;
33 | }
34 |
35 | /**
36 | * get really position
37 | *
38 | * @param position
39 | * @return
40 | */
41 | public int getRealPosition(int position) {
42 | return isLoop ? position % getRealCount() : position;
43 | }
44 |
45 | @Override
46 | public int getCount() {
47 | return isLoop ? getRealCount() * PAGE_COUNT_FACTOR : getRealCount();
48 | }
49 |
50 | public int getRealCount() {
51 | return mPageList.size();
52 | }
53 |
54 | @Override
55 | public View getView(final int position, View convertView, ViewGroup container) {
56 |
57 | final Page page = mPageList.get(getRealPosition(position));
58 | convertView = mViewBinder.bindView(
59 | mContext,
60 | getRealPosition(position),
61 | page,
62 | mImageLoader,
63 | mOnPageClickListener,
64 | convertView,
65 | container);
66 |
67 | return convertView;
68 | }
69 |
70 | public void setImageLoader(ImageLoader imageLoader) {
71 | mImageLoader = imageLoader;
72 | }
73 |
74 | public void setPages(List pages) {
75 | this.mPageList = pages;
76 | notifyDataSetChanged();
77 | }
78 |
79 | /**
80 | * @return the is Loop
81 | */
82 | public boolean isLoop() {
83 | return isLoop;
84 | }
85 |
86 | /**
87 | * @param isLoop the is InfiniteLoop to set
88 | */
89 | public void setIsLoop(boolean isLoop) {
90 | this.isLoop = isLoop;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/library/src/main/java/cn/lightsky/infiniteindicator/recycle/ViewBinder.java:
--------------------------------------------------------------------------------
1 | package cn.lightsky.infiniteindicator.recycle;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 |
7 | import cn.lightsky.infiniteindicator.ImageLoader;
8 | import cn.lightsky.infiniteindicator.OnPageClickListener;
9 | import cn.lightsky.infiniteindicator.Page;
10 |
11 | /**
12 | * Created by lightsky on 2016/11/18.
13 | *
14 | * extract getView for customing view binding
15 | */
16 |
17 | public interface ViewBinder {
18 |
19 | View bindView(Context context,
20 | int position,
21 | Page page,
22 | ImageLoader imageLoader,
23 | OnPageClickListener onPageClickListener,
24 | View convertView,
25 | ViewGroup container);
26 | }
27 |
--------------------------------------------------------------------------------
/library/src/main/res/animator/scale_with_alpha.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
11 |
17 |
18 |
19 |
25 |
--------------------------------------------------------------------------------
/library/src/main/res/animator/translation_and_rotate.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
18 |
19 |
20 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/balck_radius_square.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable/white_radius.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_anim_circle_indicator.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
21 |
22 |
26 |
27 |
31 |
32 |
36 |
37 |
41 |
42 |
46 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_anim_line_indicator.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
22 |
23 |
28 |
29 |
34 |
35 |
40 |
41 |
46 |
47 |
52 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/layout_default_indicator.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
15 |
16 |
20 |
21 |
25 |
26 |
30 |
31 |
35 |
36 |
40 |
41 |
45 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/simple_slider_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #FF0000
5 | #3366CC
6 |
7 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 | 10dp
7 |
8 | 30dp
9 |
10 |
11 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/library/src/main/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
20 |
21 |
28 |
29 |
30 |
31 |
38 |
39 |
46 |
47 |
54 |
55 |
62 |
63 |
74 |
--------------------------------------------------------------------------------
/library/src/main/res/values/vpi__defaults.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 | true
19 | #FFFFFFFF
20 | #00000000
21 | 0
22 | 3dp
23 | false
24 | #FFDDDDDD
25 | 1dp
26 |
27 |
--------------------------------------------------------------------------------
/res/a.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightSky/InfiniteIndicator/95c4e98b60577a0844a0e402e627f43387c8aa3a/res/a.jpg
--------------------------------------------------------------------------------
/res/b.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightSky/InfiniteIndicator/95c4e98b60577a0844a0e402e627f43387c8aa3a/res/b.jpg
--------------------------------------------------------------------------------
/res/c.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightSky/InfiniteIndicator/95c4e98b60577a0844a0e402e627f43387c8aa3a/res/c.jpg
--------------------------------------------------------------------------------
/res/d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lightSky/InfiniteIndicator/95c4e98b60577a0844a0e402e627f43387c8aa3a/res/d.jpg
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo',':library'
2 |
--------------------------------------------------------------------------------