package com.tiger.quicknews.wedget.viewimage.Indicators; import android.content.Context; import android.content.res.TypedArray; import android.database.DataSetObserver; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.ShapeDrawable; import android.support.v4.view.PagerAdapter; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import com.tiger.quicknews.R; import com.tiger.quicknews.wedget.viewimage.Tricks.InfinitePagerAdapter; import com.tiger.quicknews.wedget.viewimage.Tricks.ViewPagerEx; import java.util.ArrayList; /** * Pager Indicator. */ public class PagerIndicator extends LinearLayout implements ViewPagerEx.OnPageChangeListener { private final Context mContext; /** * bind this Indicator with * {@link com.example.androidimageslider.wedget.viewimage.Tricks.daimajia.slider.library.Tricks.ViewPagerEx} */ private ViewPagerEx mPager; /** * Variable to remember the previous selected indicator. */ private ImageView mPreviousSelectedIndicator; /** * Previous selected indicator position. */ private int mPreviousSelectedPosition; /** * Custom selected indicator style resource id. */ private int mUserSetUnSelectedIndicatorResId; /** * Custom unselected indicator style resource id. */ private int mUserSetSelectedIndicatorResId; private Drawable mSelectedDrawable; private Drawable mUnselectedDrawable; /** * This value is from {@link com.tiger.quicknews.wedget.viewimage.Animations.daimajia.slider.library.SliderAdapter} * getRealCount() represent the indicator count that we should draw. */ private int mItemCount = 0; private Shape mIndicatorShape = Shape.Oval; private IndicatorVisibility mVisibility = IndicatorVisibility.Visible; private final int mDefaultSelectedColor; private final int mDefaultUnSelectedColor; private final float mDefaultSelectedWidth; private final float mDefaultSelectedHeight; private final float mDefaultUnSelectedWidth; private final float mDefaultUnSelectedHeight; public enum IndicatorVisibility { Visible, Invisible; }; private final GradientDrawable mUnSelectedGradientDrawable; private final GradientDrawable mSelectedGradientDrawable; private final LayerDrawable mSelectedLayerDrawable; private final LayerDrawable mUnSelectedLayerDrawable; private float mPadding_left; private float mPadding_right; private float mPadding_top; private float mPadding_bottom; private final float mSelectedPadding_Left; private final float mSelectedPadding_Right; private final float mSelectedPadding_Top; private final float mSelectedPadding_Bottom; private final float mUnSelectedPadding_Left; private final float mUnSelectedPadding_Right; private final float mUnSelectedPadding_Top; private final float mUnSelectedPadding_Bottom; /** * Put all the indicators into a ArrayList, so we can remove them easily. */ private final ArrayList<ImageView> mIndicators = new ArrayList<ImageView>(); public PagerIndicator(Context context) { this(context, null); } public PagerIndicator(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.PagerIndicator, 0, 0); int visibility = attributes.getInt(R.styleable.PagerIndicator_visibility, IndicatorVisibility.Visible.ordinal()); for (IndicatorVisibility v : IndicatorVisibility.values()) { if (v.ordinal() == visibility) { mVisibility = v; break; } } int shape = attributes.getInt(R.styleable.PagerIndicator_shape, Shape.Oval.ordinal()); for (Shape s : Shape.values()) { if (s.ordinal() == shape) { mIndicatorShape = s; break; } } mUserSetSelectedIndicatorResId = attributes.getResourceId( R.styleable.PagerIndicator_selected_drawable, 0); mUserSetUnSelectedIndicatorResId = attributes.getResourceId( R.styleable.PagerIndicator_unselected_drawable, 0); mDefaultSelectedColor = attributes.getColor(R.styleable.PagerIndicator_selected_color, Color.rgb(255, 255, 255)); mDefaultUnSelectedColor = attributes.getColor(R.styleable.PagerIndicator_unselected_color, Color.argb(33, 255, 255, 255)); mDefaultSelectedWidth = attributes.getDimension(R.styleable.PagerIndicator_selected_width, (int) pxFromDp(6)); mDefaultSelectedHeight = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_selected_height, (int) pxFromDp(6)); mDefaultUnSelectedWidth = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_unselected_width, (int) pxFromDp(6)); mDefaultUnSelectedHeight = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_unselected_height, (int) pxFromDp(6)); mSelectedGradientDrawable = new GradientDrawable(); mUnSelectedGradientDrawable = new GradientDrawable(); mPadding_left = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_left, (int) pxFromDp(3)); mPadding_right = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_right, (int) pxFromDp(3)); mPadding_top = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_top, (int) pxFromDp(0)); mPadding_bottom = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_padding_bottom, (int) pxFromDp(0)); mPadding_left = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_left, (int) pxFromDp(3)); mPadding_right = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_right, (int) pxFromDp(3)); mPadding_top = attributes.getDimensionPixelSize(R.styleable.PagerIndicator_padding_top, (int) pxFromDp(0)); mPadding_bottom = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_padding_bottom, (int) pxFromDp(0)); mSelectedPadding_Left = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_selected_padding_left, (int) pxFromDp(3)); mSelectedPadding_Right = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_selected_padding_right, (int) pxFromDp(3)); mSelectedPadding_Top = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_selected_padding_top, (int) pxFromDp(0)); mSelectedPadding_Bottom = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_selected_padding_bottom, (int) pxFromDp(0)); mUnSelectedPadding_Left = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_unselected_padding_left, (int) pxFromDp(3)); mUnSelectedPadding_Right = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_unselected_padding_right, (int) pxFromDp(3)); mUnSelectedPadding_Top = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_unselected_padding_top, (int) pxFromDp(0)); mUnSelectedPadding_Bottom = attributes.getDimensionPixelSize( R.styleable.PagerIndicator_unselected_padding_bottom, (int) pxFromDp(0)); mSelectedLayerDrawable = new LayerDrawable(new Drawable[] { mSelectedGradientDrawable }); mUnSelectedLayerDrawable = new LayerDrawable(new Drawable[] { mUnSelectedGradientDrawable }); setIndicatorStyleResource(mUserSetSelectedIndicatorResId, mUserSetUnSelectedIndicatorResId); setDefaultIndicatorShape(mIndicatorShape); setDefaultSelectedIndicatorSize(mDefaultSelectedWidth, mDefaultSelectedHeight, Unit.Px); setDefaultUnselectedIndicatorSize(mDefaultUnSelectedWidth, mDefaultUnSelectedHeight, Unit.Px); setDefaultIndicatorColor(mDefaultSelectedColor, mDefaultUnSelectedColor); setIndicatorVisibility(mVisibility); setDefaultPadding(mPadding_left, mPadding_top, mPadding_right, mPadding_bottom, Unit.Px); setDefaultSelectedPadding(mSelectedPadding_Left, mSelectedPadding_Top, mSelectedPadding_Right, mSelectedPadding_Bottom, Unit.Px); setDefaultUnSelectedPadding(mUnSelectedPadding_Left, mUnSelectedPadding_Top, mUnSelectedPadding_Right, mUnSelectedPadding_Bottom, Unit.Px); attributes.recycle(); } public enum Shape { Oval, Rectangle } public void setDefaultPadding(float left, float top, float right, float bottom, Unit unit) { if (mUserSetSelectedIndicatorResId == 0) { if (unit == Unit.DP) { mSelectedLayerDrawable.setLayerInset(0, (int) pxFromDp(left), (int) pxFromDp(top), (int) pxFromDp(right), (int) pxFromDp(bottom)); mUnSelectedLayerDrawable.setLayerInset(0, (int) pxFromDp(left), (int) pxFromDp(top), (int) pxFromDp(right), (int) pxFromDp(bottom)); } else { mSelectedLayerDrawable.setLayerInset(0, (int) left, (int) top, (int) right, (int) bottom); mUnSelectedLayerDrawable.setLayerInset(0, (int) left, (int) top, (int) right, (int) bottom); } } } public void setDefaultSelectedPadding(float left, float top, float right, float bottom, Unit unit) { if (mUserSetSelectedIndicatorResId == 0) { if (unit == Unit.DP) { mSelectedLayerDrawable.setLayerInset(0, (int) pxFromDp(left), (int) pxFromDp(top), (int) pxFromDp(right), (int) pxFromDp(bottom)); } else { mSelectedLayerDrawable.setLayerInset(0, (int) left, (int) top, (int) right, (int) bottom); } } } public void setDefaultUnSelectedPadding(float left, float top, float right, float bottom, Unit unit) { if (mUserSetSelectedIndicatorResId == 0) { if (unit == Unit.DP) { mUnSelectedLayerDrawable.setLayerInset(0, (int) pxFromDp(left), (int) pxFromDp(top), (int) pxFromDp(right), (int) pxFromDp(bottom)); } else { mUnSelectedLayerDrawable.setLayerInset(0, (int) left, (int) top, (int) right, (int) bottom); } } } /** * if you are using the default indicator, this method will help you to set * the shape of indicator, there are two kind of shapes you can set, oval * and rect. * * @param shape */ public void setDefaultIndicatorShape(Shape shape) { if (mUserSetSelectedIndicatorResId == 0) { if (shape == Shape.Oval) { mSelectedGradientDrawable.setShape(GradientDrawable.OVAL); } else { mSelectedGradientDrawable.setShape(GradientDrawable.RECTANGLE); } } if (mUserSetUnSelectedIndicatorResId == 0) { if (shape == Shape.Oval) { mUnSelectedGradientDrawable.setShape(GradientDrawable.OVAL); } else { mUnSelectedGradientDrawable.setShape(GradientDrawable.RECTANGLE); } } resetDrawable(); } /** * Set Indicator style. * * @param selected page selected drawable * @param unselected page unselected drawable */ public void setIndicatorStyleResource(int selected, int unselected) { mUserSetSelectedIndicatorResId = selected; mUserSetUnSelectedIndicatorResId = unselected; if (selected == 0) { mSelectedDrawable = mSelectedLayerDrawable; } else { mSelectedDrawable = mContext.getResources().getDrawable(mUserSetSelectedIndicatorResId); } if (unselected == 0) { mUnselectedDrawable = mUnSelectedLayerDrawable; } else { mUnselectedDrawable = mContext.getResources().getDrawable( mUserSetUnSelectedIndicatorResId); } resetDrawable(); } /** * if you are using the default indicator , this method will help you to set * the selected status and the unselected status color. * * @param selectedColor * @param unselectedColor */ public void setDefaultIndicatorColor(int selectedColor, int unselectedColor) { if (mUserSetSelectedIndicatorResId == 0) { mSelectedGradientDrawable.setColor(selectedColor); } if (mUserSetUnSelectedIndicatorResId == 0) { mUnSelectedGradientDrawable.setColor(unselectedColor); } resetDrawable(); } public enum Unit { DP, Px } public void setDefaultSelectedIndicatorSize(float width, float height, Unit unit) { if (mUserSetSelectedIndicatorResId == 0) { float w = width; float h = height; if (unit == Unit.DP) { w = pxFromDp(width); h = pxFromDp(height); } mSelectedGradientDrawable.setSize((int) w, (int) h); resetDrawable(); } } public void setDefaultUnselectedIndicatorSize(float width, float height, Unit unit) { if (mUserSetUnSelectedIndicatorResId == 0) { float w = width; float h = height; if (unit == Unit.DP) { w = pxFromDp(width); h = pxFromDp(height); } mUnSelectedGradientDrawable.setSize((int) w, (int) h); resetDrawable(); } } public void setDefaultIndicatorSize(float width, float height, Unit unit) { setDefaultSelectedIndicatorSize(width, height, unit); setDefaultUnselectedIndicatorSize(width, height, unit); } private float dpFromPx(float px) { return px / this.getContext().getResources().getDisplayMetrics().density; } private float pxFromDp(float dp) { return dp * this.getContext().getResources().getDisplayMetrics().density; } /** * set the visibility of indicator. * * @param visibility */ public void setIndicatorVisibility(IndicatorVisibility visibility) { if (visibility == IndicatorVisibility.Visible) { setVisibility(View.VISIBLE); } else { setVisibility(View.INVISIBLE); } resetDrawable(); } /** * clear self means unregister the dataset observer and remove all the child * views(indicators). */ public void destroySelf() { if (mPager == null || mPager.getAdapter() == null) { return; } InfinitePagerAdapter wrapper = (InfinitePagerAdapter) mPager.getAdapter(); PagerAdapter adapter = wrapper.getRealAdapter(); if (adapter != null) { adapter.unregisterDataSetObserver(dataChangeObserver); } removeAllViews(); ShapeDrawable shapeDrawable; } /** * bind indicator with viewpagerEx. * * @param pager */ public void setViewPager(ViewPagerEx pager) { if (pager.getAdapter() == null) { throw new IllegalStateException("Viewpager does not have adapter instance"); } mPager = pager; mPager.setOnPageChangeListener(this); ((InfinitePagerAdapter) mPager.getAdapter()).getRealAdapter().registerDataSetObserver( dataChangeObserver); } private void resetDrawable() { for (View i : mIndicators) { if (mPreviousSelectedIndicator != null && mPreviousSelectedIndicator.equals(i)) { ((ImageView) i).setImageDrawable(mSelectedDrawable); } else { ((ImageView) i).setImageDrawable(mUnselectedDrawable); } } } /** * redraw the indicators. */ public void redraw() { mItemCount = getShouldDrawCount(); mPreviousSelectedIndicator = null; for (View i : mIndicators) { removeView(i); } for (int i = 0; i < mItemCount; i++) { ImageView indicator = new ImageView(mContext); indicator.setImageDrawable(mUnselectedDrawable); addView(indicator); mIndicators.add(indicator); } setItemAsSelected(mPreviousSelectedPosition); } /** * since we used a adapter wrapper, so we can't getCount directly from * wrapper. * * @return */ private int getShouldDrawCount() { if (mPager.getAdapter() instanceof InfinitePagerAdapter) { return ((InfinitePagerAdapter) mPager.getAdapter()).getRealCount(); } else { return mPager.getAdapter().getCount(); } } private final DataSetObserver dataChangeObserver = new DataSetObserver() { @Override public void onChanged() { PagerAdapter adapter = mPager.getAdapter(); int count = 0; if (adapter instanceof InfinitePagerAdapter) { count = ((InfinitePagerAdapter) adapter).getRealCount(); } else { count = adapter.getCount(); } if (count > mItemCount) { for (int i = 0; i < count - mItemCount; i++) { ImageView indicator = new ImageView(mContext); indicator.setImageDrawable(mUnselectedDrawable); addView(indicator); mIndicators.add(indicator); } } else if (count < mItemCount) { for (int i = 0; i < mItemCount - count; i++) { removeView(mIndicators.get(0)); mIndicators.remove(0); } } mItemCount = count; mPager.setCurrentItem(mItemCount * 20 + mPager.getCurrentItem()); } @Override public void onInvalidated() { super.onInvalidated(); redraw(); } }; private void setItemAsSelected(int position) { if (mPreviousSelectedIndicator != null) { mPreviousSelectedIndicator.setImageDrawable(mUnselectedDrawable); } ImageView currentSelected = (ImageView) getChildAt(position + 1); if (currentSelected != null) { currentSelected.setImageDrawable(mSelectedDrawable); mPreviousSelectedIndicator = currentSelected; } mPreviousSelectedPosition = position; } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { if (mItemCount == 0) { return; } int n = position % mItemCount; setItemAsSelected(n - 1); } public IndicatorVisibility getIndicatorVisibility() { return mVisibility; } @Override public void onPageSelected(int position) { } @Override public void onPageScrollStateChanged(int state) { } public int getSelectedIndicatorResId() { return mUserSetSelectedIndicatorResId; } public int getUnSelectedIndicatorResId() { return mUserSetUnSelectedIndicatorResId; } }