android ViewPager 指示器 PageIndicator
来源:互联网 发布:华人医师数据库 编辑:程序博客网 时间:2024/05/16 16:20
一款 google写的 ViewPager 指示器 PageIndicator
下面是pagedindicator代码
package com.lmjssjj.pagedindicator;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.animation.ValueAnimator.AnimatorUpdateListener;import android.content.Context;import android.graphics.Canvas;import android.graphics.Outline;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.util.Property;import android.view.View;import android.view.ViewGroup;import android.view.ViewOutlineProvider;import android.view.animation.Interpolator;import android.view.animation.OvershootInterpolator;import android.widget.FrameLayout;/** * Base class for a page indicator. */public class PageIndicator extends FrameLayout { private static final float SHIFT_PER_ANIMATION = 0.5f; private static final float SHIFT_THRESHOLD = 0.1f; private static final long ANIMATION_DURATION = 150; private static final int ENTER_ANIMATION_START_DELAY = 300; private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150; private static final int ENTER_ANIMATION_DURATION = 400; // This value approximately overshoots to 1.5 times the original size. private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f; private static final RectF sTempRect = new RectF(); private static final Property<PageIndicator, Float> CURRENT_POSITION = new Property<PageIndicator, Float>( float.class, "current_position") { @Override public Float get(PageIndicator obj) { return obj.mCurrentPosition; } @Override public void set(PageIndicator obj, Float pos) { obj.mCurrentPosition = pos; obj.invalidate(); obj.invalidateOutline(); } }; /** * Listener for keep running the animation until the final state is reached. */ private final AnimatorListenerAdapter mAnimCycleListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mAnimator = null; animateToPostion(mFinalPosition); } }; private final Paint mCirclePaint; private final float mDotRadius; private final int mActiveColor; private final int mInActiveColor; private final boolean mIsRtl; private int mActivePage; /** * The current position of the active dot including the animation progress. * For ex: 0.0 => Active dot is at position 0 0.33 => Active dot is at * position 0 and is moving towards 1 0.50 => Active dot is at position [0, * 1] 0.77 => Active dot has left position 0 and is collapsing towards * position 1 1.0 => Active dot is at position 1 */ private float mCurrentPosition; private float mFinalPosition; private ObjectAnimator mAnimator; private float[] mEntryAnimationRadiusFactors; private ViewGroup parentView; protected int mNumPages = 1; public PageIndicator(Context context) { this(context, null); } public PageIndicator(Context context, AttributeSet attrs) { this(context, attrs, 0); } public PageIndicator(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCirclePaint.setStyle(Style.FILL); mDotRadius = getResources().getDimension(R.dimen.page_indicator_dot_size) / 2; setOutlineProvider(new MyOutlineProver()); mActiveColor = Utilities.getColorAccent(context); mInActiveColor = getResources().getColor(R.color.page_indicator_dot_color); mIsRtl = Utilities.isRtl(getResources()); setWillNotDraw(false); } public void addMarker() { mNumPages++; onPageCountChanged(); } public void removeMarker() { mNumPages--; onPageCountChanged(); } public void setMarkersCount(int numMarkers) { mNumPages = numMarkers; onPageCountChanged(); } public void setScroll(int currentScroll, int totalScroll) { Log.v("lmjssjj", "currentScroll:" + currentScroll); Log.v("lmjssjj", "totalScroll:" + totalScroll); if (mNumPages > 1) { if (mIsRtl) { currentScroll = totalScroll - currentScroll; } int scrollPerPage = totalScroll / (mNumPages - 1); int absScroll = mActivePage * scrollPerPage; float scrollThreshold = SHIFT_THRESHOLD * scrollPerPage; if ((absScroll - currentScroll) > scrollThreshold) { // current scroll is before absolute scroll animateToPostion(mActivePage - SHIFT_PER_ANIMATION); } else if ((currentScroll - absScroll) > scrollThreshold) { // current scroll is ahead of absolute scroll animateToPostion(mActivePage + SHIFT_PER_ANIMATION); } else { animateToPostion(mActivePage); } } } private void animateToPostion(float position) { Log.v("lmjssjj", "mFinalPosition:" + mFinalPosition); mFinalPosition = position; if (Math.abs(mCurrentPosition - mFinalPosition) < SHIFT_THRESHOLD) { mCurrentPosition = mFinalPosition; } if (mAnimator == null && Float.compare(mCurrentPosition, mFinalPosition) != 0) { float positionForThisAnim = mCurrentPosition > mFinalPosition ? mCurrentPosition - SHIFT_PER_ANIMATION : mCurrentPosition + SHIFT_PER_ANIMATION; mAnimator = ObjectAnimator.ofFloat(this, CURRENT_POSITION, positionForThisAnim); mAnimator.addListener(mAnimCycleListener); mAnimator.setDuration(ANIMATION_DURATION); mAnimator.start(); } } public void stopAllAnimations() { if (mAnimator != null) { mAnimator.removeAllListeners(); mAnimator.cancel(); mAnimator = null; } mFinalPosition = mActivePage; CURRENT_POSITION.set(this, mFinalPosition); } /** * Sets up up the page indicator to play the entry animation. * {@link #playEntryAnimation()} must be called after this. */ public void prepareEntryAnimation() { mEntryAnimationRadiusFactors = new float[mNumPages]; invalidate(); } public void playEntryAnimation() { int count = mEntryAnimationRadiusFactors.length; if (count == 0) { mEntryAnimationRadiusFactors = null; invalidate(); return; } Interpolator interpolator = new OvershootInterpolator(ENTER_ANIMATION_OVERSHOOT_TENSION); AnimatorSet animSet = new AnimatorSet(); for (int i = 0; i < count; i++) { ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(ENTER_ANIMATION_DURATION); final int index = i; anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mEntryAnimationRadiusFactors[index] = (Float) animation.getAnimatedValue(); invalidate(); } }); anim.setInterpolator(interpolator); anim.setStartDelay(ENTER_ANIMATION_START_DELAY + ENTER_ANIMATION_STAGGERED_DELAY * i); animSet.play(anim); } animSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mEntryAnimationRadiusFactors = null; invalidateOutline(); invalidate(); } }); animSet.start(); } public void setActiveMarker(int activePage) { if (mActivePage != activePage) { mActivePage = activePage; invalidate(); } } protected void onPageCountChanged() { requestLayout(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Add extra spacing of mDotRadius on all sides so than entry animation // could be run. int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ? MeasureSpec.getSize(widthMeasureSpec) : (int) ((mNumPages * 3 + 2) * mDotRadius); int height = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY ? MeasureSpec.getSize(heightMeasureSpec) : (int) (4 * mDotRadius); setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { // Draw all page indicators; float circleGap = 3 * mDotRadius; float startX = (getWidth() - mNumPages * circleGap + mDotRadius) / 2; float x = startX + mDotRadius; float y = canvas.getHeight() / 2; if (mEntryAnimationRadiusFactors != null) { // During entry animation, only draw the circles if (mIsRtl) { x = getWidth() - x; circleGap = -circleGap; } for (int i = 0; i < mEntryAnimationRadiusFactors.length; i++) { mCirclePaint.setColor(i == mActivePage ? mActiveColor : mInActiveColor); canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i], mCirclePaint); x += circleGap; } } else { mCirclePaint.setColor(mInActiveColor); for (int i = 0; i < mNumPages; i++) { canvas.drawCircle(x, y, mDotRadius, mCirclePaint); x += circleGap; } mCirclePaint.setColor(mActiveColor); canvas.drawRoundRect(getActiveRect(), mDotRadius, mDotRadius, mCirclePaint); } } private RectF getActiveRect() { float startCircle = (int) mCurrentPosition; float delta = mCurrentPosition - startCircle; float diameter = 2 * mDotRadius; float circleGap = 3 * mDotRadius; float startX = (getWidth() - mNumPages * circleGap + mDotRadius) / 2; sTempRect.top = getHeight() * 0.5f - mDotRadius; sTempRect.bottom = getHeight() * 0.5f + mDotRadius; sTempRect.left = startX + startCircle * circleGap; sTempRect.right = sTempRect.left + diameter; Log.v("lmjssjj", "delta:" + delta); if (delta < SHIFT_PER_ANIMATION) { // dot is capturing the right circle. sTempRect.right += delta * circleGap * 2; } else { // Dot is leaving the left circle. sTempRect.right += circleGap; delta -= SHIFT_PER_ANIMATION; sTempRect.left += delta * circleGap * 2; } if (mIsRtl) { float rectWidth = sTempRect.width(); sTempRect.right = getWidth() - sTempRect.left; sTempRect.left = sTempRect.right - rectWidth; } Log.v("lmjssjj", "sTempRect:" + sTempRect.toString()); return sTempRect; } private class MyOutlineProver extends ViewOutlineProvider { @Override public void getOutline(View view, Outline outline) { if (mEntryAnimationRadiusFactors == null) { RectF activeRect = getActiveRect(); outline.setRoundRect((int) activeRect.left, (int) activeRect.top, (int) activeRect.right, (int) activeRect.bottom, mDotRadius); } } }}
通过监听setOnScrollChangeListener 来改变状态
@Override public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) { pi.setScroll(scrollX, vp.getMeasuredWidth() *( mImgIds.length-1)); //Log.v("lmjssjj", "scrollX" + scrollX); }
阅读全文
0 0
- android ViewPager 指示器 PageIndicator
- Android ViewPager指示器 IndicatorBar
- Android自定义ViewPager指示器
- Android ViewPager指示器 IndicatorBar
- Android-自定义ViewPager指示器
- Android自定义ViewPager指示器
- Android 实现Viewpager指示器
- Android Viewpager界面指示器案例
- Android ViewPager 小圆点指示器
- Android简单的ViewPager指示器
- Android简单的ViewPager指示器
- 指示器+viewpager Android Design Support Library使用详解指示器
- ViewPager 指示器
- ViewPager指示器
- ViewPager指示器
- ViewPager 指示器
- ViewPager指示器
- ViewPager指示器
- opengl绘制四边形
- HashMap,LinkedHashMap,TreeMap的区别
- Android应用实现微信登录和分享
- ASP.NET MVC中的Global.asax文件
- ettercap 入门学习
- android ViewPager 指示器 PageIndicator
- 合唱队形
- 给HTML页面设置背景音乐
- Java运算符总结
- MySQL的navicat断网无法访问问题
- js实现无缝滚动
- java se遗漏知识点
- 分区丢失数据恢复技巧
- 《Using OpenRefine》翻译~18