Android自定义超级炫酷的ViewPage指示器

请你先在我的回答里看到标题及类别,以便更好地组织答案。

标题:Android自定义超级炫酷的ViewPage指示器的完整攻略

类别:Android开发 / ViewPage指示器

1. 基本思路

要自定义一个炫酷的ViewPage指示器,我们需要完成以下几个步骤:

  1. 创建一个自定义View,用于渲染指示器;
  2. 实现ViewPager.OnPageChangeListener接口,监听ViewPager页面变化,实时更新指示器;
  3. 对指示器进行渐变、弹簧效果等美化处理。

2. 创建自定义View

创建自定义View的过程如下:

  1. 继承View类;
  2. 重写onMeasure方法用于测量View的大小;
  3. 重写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页面变化的过程如下:

  1. 实现ViewPager.OnPageChangeListener接口;
  2. 在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技术站

(0)
上一篇 2023年6月25日
下一篇 2023年6月25日

相关文章

  • html5指南-3.如何实现html元素拖拽功能

    HTML5指南 – 如何实现HTML元素拖拽功能 HTML5提供了拖拽API,可以轻松实现HTML元素的拖拽功能。以下是实现HTML元素拖拽功能的详细攻略: 添加拖拽事件监听器 首先,我们需要为要拖拽的HTML元素添加拖拽事件监听器。可以使用以下代码: “`html “` 在上述示例中,我们给div元素添加了draggable=\”true\”属性,表示…

    other 2023年10月15日
    00
  • java 嵌套类的详解及实例代码

    ” + outerData); } } public static void main(String[] args) { OuterClass outerObj = new OuterClass(); OuterClass.InnerClass innerObj = outerObj.new InnerClass(); innerObj.printOuter…

    other 2023年7月27日
    00
  • CAD怎么自定义设置shx字?

    下面是关于CAD如何自定义设置shx字的攻略。具体操作步骤如下: 步骤一:准备shx字体文件 在CAD中,默认提供了一些shx字体文件供用户选择使用,但是如果你需要使用自己的shx字体文件,就需要先将字体文件准备好。 安装字体文件 如果你已经有了自己的shx字体文件,就需要将它安装到系统中。在Windows系统中,只需要双击字体文件即可安装。具体操作步骤如下…

    other 2023年6月25日
    00
  • stompjs使用文档总结

    以下是详细讲解“stompjs使用文档总结的完整攻略”的标准Markdown格式文本,包含两个示例说明: stompjs使用文档总结的完整攻略 stompjs是一个用于WebSocket通信的JavaScript库,它提供了一种简单的方式来实现基于STOMP协议的WebSocket通信。本攻略将介绍stompjs的使用方法。 步骤一:引入stompjs库 在…

    other 2023年5月10日
    00
  • 魅族16T和红米K20 Pro哪款好 魅族16T和红米K20 Pro区别对比

    魅族16T和红米K20 Pro哪款好?魅族16T和红米K20 Pro区别对比攻略 如果你正考虑购买一款高性能的智能手机,那么你可能会面临着购买魅族16T和红米K20 Pro这两款手机的选择。这两款手机都拥有出色的性能和功能。在本攻略中,我们将对这两款手机进行详细的比较和对比,帮助您更好地选择一款最适合自己的手机。 性能方面 魅族16T和红米K20 Pro都拥…

    other 2023年6月26日
    00
  • android侧边栏(使用supportlibrary4提供的扩展组件)

    以下是关于使用supportlibrary4提供的扩展组件实现Android侧边栏的完整攻略,包括基本介绍、实现步骤、示例说明等内容。 1. 基本介绍 Android侧边栏是一种常见的UI设计模式,可以让用户快速访问应用程序的不同部分。使用supportlibrary4提供的扩展组件,我们可以轻松地实现Android侧边栏。在使用侧边栏时,我们需要注意布局和…

    other 2023年5月10日
    00
  • VS2010:error MSB4018提示CL任务意外失败怎么解决?

    当我们在使用VS2010编译程序时,有时候会出现”error MSB4018: The “CL” task failed unexpectedly”的错误提示。这个错误表示编译器在执行编译任务时遇到了一些问题,导致编译失败。 要解决这个错误,我们可以尝试以下几个步骤: 步骤一:清理项目和重新生成 首先,我们可以尝试清理项目并重新生成代码。在Visual St…

    other 2023年6月27日
    00
  • Word里的英文字母大小写怎么转换?

    在Word中,你可以使用以下方法来转换英文字母的大小写: 使用快捷键: 转换为大写字母:选中你想要转换的文本,然后按下\”Ctrl\”和\”Shift\”键,并同时按下\”A\”键。 转换为小写字母:选中你想要转换的文本,然后按下\”Ctrl\”和\”Shift\”键,并同时按下\”A\”键。 使用菜单选项: 转换为大写字母:选中你想要转换的文本,然后在Wo…

    other 2023年8月16日
    00
合作推广
合作推广
分享本页
返回顶部