请你先在我的回答里看到标题及类别,以便更好地组织答案。
标题:Android自定义超级炫酷的ViewPage指示器的完整攻略
类别:Android开发 / ViewPage指示器
1. 基本思路
要自定义一个炫酷的ViewPage指示器,我们需要完成以下几个步骤:
- 创建一个自定义View,用于渲染指示器;
- 实现ViewPager.OnPageChangeListener接口,监听ViewPager页面变化,实时更新指示器;
- 对指示器进行渐变、弹簧效果等美化处理。
2. 创建自定义View
创建自定义View的过程如下:
- 继承View类;
- 重写onMeasure方法用于测量View的大小;
- 重写onDraw方法用于绘制View。
以下是代码示例:
public class DotIndicatorView extends View {
private int mDotNum = 0;
private int mSelectedIndex = 0;
private Paint mPaint;
private int mRadius;
private int mGap;
private int mPaddingLeft;
private int mPaddingRight;
private int mPaddingTop;
private int mPaddingBottom;
public DotIndicatorView(Context context) {
this(context, null);
}
public DotIndicatorView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DotIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.FILL);
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
mRadius = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, displayMetrics);
mGap = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, displayMetrics);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = mDotNum * mRadius * 2 + (mDotNum - 1) * mGap + mPaddingLeft + mPaddingRight;
int height = mRadius * 2 + mPaddingTop + mPaddingBottom;
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDotNum <= 1) {
return;
}
for (int i = 0; i < mDotNum; i++) {
int cx = mPaddingLeft + mRadius + i * (mGap + mRadius * 2);
int cy = getHeight() / 2;
canvas.drawCircle(cx, cy, mRadius, mPaint);
}
}
public void setDotNum(int dotNum) {
mDotNum = dotNum;
requestLayout();
}
public void setSelectedIndex(int selectedIndex) {
mSelectedIndex = selectedIndex;
invalidate();
}
}
3. 监听ViewPager页面变化
监听ViewPager页面变化的过程如下:
- 实现ViewPager.OnPageChangeListener接口;
- 在onPageSelected方法中更新指示器。
以下是代码示例:
public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
private ViewPager mViewPager;
private DotIndicatorView mDotIndicatorView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mDotIndicatorView = (DotIndicatorView) findViewById(R.id.dot_indicator);
mViewPager.setAdapter(new MyPagerAdapter());
mViewPager.addOnPageChangeListener(this);
mDotIndicatorView.setDotNum(3);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
mDotIndicatorView.setSelectedIndex(position);
}
@Override
public void onPageScrollStateChanged(int state) {
}
private class MyPagerAdapter extends PagerAdapter {
private List<View> mViewList;
public MyPagerAdapter() {
mViewList = new ArrayList<>();
mViewList.add(getLayoutInflater().inflate(R.layout.pager_item_1, null));
mViewList.add(getLayoutInflater().inflate(R.layout.pager_item_2, null));
mViewList.add(getLayoutInflater().inflate(R.layout.pager_item_3, null));
}
@Override
public int getCount() {
return mViewList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = mViewList.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mViewList.get(position));
}
}
}
4. 美化指示器
我们可以使用属性动画,对指示器进行渐变、弹簧效果等美化处理。以下是代码示例:
public class DotIndicatorView extends View {
// ...
private int mTickness;
private float mHollowRatio;
private int mHollowColor;
private int mSelectedColor;
private int mDuration;
private ValueAnimator mAnimator;
private int mToIndex;
private int mFromIndex;
private float mSelectedRatio;
public DotIndicatorView(Context context) {
// ...
mTickness = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, displayMetrics);
mHollowRatio = 0.4f;
mHollowColor = Color.TRANSPARENT;
mSelectedColor = Color.WHITE;
mDuration = 300;
mAnimator = ValueAnimator.ofFloat(0f, 1f);
mAnimator.setInterpolator(new OverShootInterpolator());
mAnimator.setDuration(mDuration);
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mSelectedRatio = (float) animation.getAnimatedValue();
invalidate();
}
});
}
private void drawDot(Canvas canvas, int cx, int cy, int radius, Paint paint) {
canvas.drawCircle(cx, cy, radius - mTickness / 2, paint);
canvas.drawCircle(cx, cy, radius * (1 - mHollowRatio) + mTickness / 2, mPaint);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDotNum <= 1) {
return;
}
for (int i = 0; i < mDotNum; i++) {
int cx = mPaddingLeft + mRadius + i * (mGap + mRadius * 2);
int cy = getHeight() / 2;
if (i == mSelectedIndex) {
int fromRadius = mRadius;
int toRadius = (int) (mRadius * (1 + mHollowRatio));
int radius = (int) (fromRadius + (toRadius - fromRadius) * mSelectedRatio);
mPaint.setColor(mSelectedColor);
drawDot(canvas, cx, cy, radius, mPaint);
} else {
mPaint.setColor(mHollowColor);
drawDot(canvas, cx, cy, mRadius, mPaint);
}
}
}
public void setSelectedIndex(int selectedIndex, boolean isAnimate) {
if (isAnimate) {
if (mAnimator.isRunning()) {
mAnimator.cancel();
}
mFromIndex = mSelectedIndex;
mToIndex = selectedIndex;
mAnimator.start();
} else {
mSelectedRatio = 1f;
mSelectedIndex = selectedIndex;
invalidate();
}
}
}
以上就是自定义炫酷的ViewPage指示器的完整攻略,希望可以帮助到你。如果有需要,也可以将以上代码片段按需整合到项目中,让自己的指示器更炫酷。
至于示例可以关注这个链接:https://github.com/max299792458/indicator 里面展示了两个指示器的示例代码
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Android自定义超级炫酷的ViewPage指示器 - Python技术站