package moe.feng.bilinyan.view; import android.animation.Animator; import android.animation.AnimatorInflater; import android.content.Context; import android.content.res.TypedArray; import android.support.annotation.AnimatorRes; import android.support.annotation.DrawableRes; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.animation.Interpolator; import android.widget.LinearLayout; import moe.feng.bilinyan.R; import static android.support.v4.view.ViewPager.OnPageChangeListener; public class CircleIndicator extends LinearLayout implements OnPageChangeListener { private final static int DEFAULT_INDICATOR_WIDTH = 5; private ViewPager mViewpager; private int mIndicatorMargin = -1; private int mIndicatorWidth = -1; private int mIndicatorHeight = -1; private int mAnimatorResId = R.animator.scale_with_alpha; private int mAnimatorReverseResId = 0; private int mIndicatorBackgroundResId = R.drawable.white_radius; private int mIndicatorUnselectedBackgroundResId = R.drawable.white_radius; private int mCurrentPosition = 0; private Animator mAnimationOut; private Animator mAnimationIn; public CircleIndicator(Context context) { super(context); init(context, null); } public CircleIndicator(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } private void init(Context context, AttributeSet attrs) { setOrientation(LinearLayout.HORIZONTAL); setGravity(Gravity.CENTER); handleTypedArray(context, attrs); checkIndicatorConfig(context); } private void handleTypedArray(Context context, AttributeSet attrs) { if (attrs == null) { return; } TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicator); mIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_width, -1); mIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_height, -1); mIndicatorMargin = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_ci_margin, -1); mAnimatorResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_animator, R.animator.scale_with_alpha); mAnimatorReverseResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_animator_reverse, 0); mIndicatorBackgroundResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_drawable, R.drawable.white_radius); mIndicatorUnselectedBackgroundResId = typedArray.getResourceId(R.styleable.CircleIndicator_ci_drawable_unselected, mIndicatorBackgroundResId); typedArray.recycle(); } /** * Create and configure Indicator in Java code. */ public void configureIndicator(int indicatorWidth, int indicatorHeight, int indicatorMargin) { configureIndicator(indicatorWidth, indicatorHeight, indicatorMargin, R.animator.scale_with_alpha, 0, R.drawable.white_radius, R.drawable.white_radius); } public void configureIndicator(int indicatorWidth, int indicatorHeight, int indicatorMargin, @AnimatorRes int animatorId, @AnimatorRes int animatorReverseId, @DrawableRes int indicatorBackgroundId, @DrawableRes int indicatorUnselectedBackgroundId) { mIndicatorWidth = indicatorWidth; mIndicatorHeight = indicatorHeight; mIndicatorMargin = indicatorMargin; mAnimatorResId = animatorId; mAnimatorReverseResId = animatorReverseId; mIndicatorBackgroundResId = indicatorBackgroundId; mIndicatorUnselectedBackgroundResId = indicatorUnselectedBackgroundId; checkIndicatorConfig(getContext()); } private void checkIndicatorConfig(Context context) { mIndicatorWidth = (mIndicatorWidth < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorWidth; mIndicatorHeight = (mIndicatorHeight < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorHeight; mIndicatorMargin = (mIndicatorMargin < 0) ? dip2px(DEFAULT_INDICATOR_WIDTH) : mIndicatorMargin; mAnimatorResId = (mAnimatorResId == 0) ? R.animator.scale_with_alpha : mAnimatorResId; mAnimationOut = AnimatorInflater.loadAnimator(context, mAnimatorResId); if (mAnimatorReverseResId == 0) { mAnimationIn = AnimatorInflater.loadAnimator(context, mAnimatorResId); mAnimationIn.setInterpolator(new ReverseInterpolator()); } else { mAnimationIn = AnimatorInflater.loadAnimator(context, mAnimatorReverseResId); } mIndicatorBackgroundResId = (mIndicatorBackgroundResId == 0) ? R.drawable.white_radius : mIndicatorBackgroundResId; mIndicatorUnselectedBackgroundResId = (mIndicatorUnselectedBackgroundResId == 0) ? mIndicatorBackgroundResId : mIndicatorUnselectedBackgroundResId; } public void setViewPager(ViewPager viewPager) { mViewpager = viewPager; mCurrentPosition = mViewpager.getCurrentItem(); createIndicators(viewPager); mViewpager.removeOnPageChangeListener(this); mViewpager.addOnPageChangeListener(this); onPageSelected(mCurrentPosition); } /** * @deprecated User ViewPager addOnPageChangeListener */ @Deprecated public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener) { if (mViewpager == null) { throw new NullPointerException("can not find Viewpager , setViewPager first"); } mViewpager.removeOnPageChangeListener(onPageChangeListener); mViewpager.addOnPageChangeListener(onPageChangeListener); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (mViewpager.getAdapter() == null || mViewpager.getAdapter().getCount() <= 0) { return; } if (mAnimationIn.isRunning()) mAnimationIn.end(); if (mAnimationOut.isRunning()) mAnimationOut.end(); View currentIndicator = getChildAt(mCurrentPosition); currentIndicator.setBackgroundResource(mIndicatorUnselectedBackgroundResId); mAnimationIn.setTarget(currentIndicator); mAnimationIn.start(); View selectedIndicator = getChildAt(position); selectedIndicator.setBackgroundResource(mIndicatorBackgroundResId); mAnimationOut.setTarget(selectedIndicator); mAnimationOut.start(); mCurrentPosition = position; } @Override public void onPageScrollStateChanged(int state) { } private void createIndicators(ViewPager viewPager) { removeAllViews(); if (viewPager.getAdapter() == null) { return; } int count = viewPager.getAdapter().getCount(); if (count <= 0) { return; } addIndicator(mIndicatorBackgroundResId, mAnimationOut); for (int i = 1; i < count; i++) { addIndicator(mIndicatorUnselectedBackgroundResId, mAnimationIn); } } private void addIndicator(@DrawableRes int backgroundDrawableId, Animator animator) { if (animator.isRunning()) animator.end(); View Indicator = new View(getContext()); Indicator.setBackgroundResource(backgroundDrawableId); addView(Indicator, mIndicatorWidth, mIndicatorHeight); LayoutParams lp = (LayoutParams) Indicator.getLayoutParams(); lp.leftMargin = mIndicatorMargin; lp.rightMargin = mIndicatorMargin; Indicator.setLayoutParams(lp); animator.setTarget(Indicator); animator.start(); } private class ReverseInterpolator implements Interpolator { @Override public float getInterpolation(float value) { return Math.abs(1.0f - value); } } public int dip2px(float dpValue) { final float scale = getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }