简易打造一个引导页的指示器

简易打造一个引导页的指示器

来尝试打造一个简单的指示器

这是一个用作引导页的指示器,具有粘连效果,由于只花了一天的功夫写,一些细节尚未考虑周全

预览图
要写出一个这样一个指示器,需要你知道下面两个知识点:

  1. ViewPager.OnPageChangeListener
  2. Path类中quadTo的使用

1. ViewPager.OnPageChangeListener

废话不多,先了解OnPageChangeListener的作用,下面贴代码

public interface OnPageChangeListener {
		/**
         * @param position 计算位移偏移量的对象的位置
         * @param positionOffset 计算位移偏移量 (变化值从0f~1f)
         * @param positionOffsetPixels 位置偏移像素 这个在本例子中并未用到,所以我也没有去过多了解,可以去自己试试
         */
        void onPageScrolled(int position, float positionOffset,@Px int positionOffsetPixels);
		/**
         * @param position viewpager当前选中的页面
         */
        void onPageSelected(int position);
		//下面这个是滚动状态改变时才会去调用的方法,个人觉得可以在改变页面时,加上一个段动画,算是个坑吧,我还没填
        void onPageScrollStateChanged(int var1);
    }

值得注意的是有一点,第一个方法的positionOffset的值只从0~1的,我当时在困惑那该如何判断这个positionOffset是向左偏移还是向右呢?在我写完一半去测试的时候发现,第一个方法的position并不是逻辑上当前选中的那个而是,相对参考的position,什么意思呢,比如:我当前逻辑上currentPosition=2,那么当你拖动viewpager手指向左滑动时,那么第一个方法的position =2;但是,如果你向右滑,那么第一个方法的position =1;
这样就很好解释了positionOffset的值为什么没有方向了。因为他给的position永远是你当前选中的position和将要滑向的position中的左值。
当然了,第二个方法的position传值确实是当前选中的position,而且只在改变position时调用。

2. Path类中quadTo的使用

首先要说path类中有很多的方法,还有填充法则PorterDuffXfermode 和 FillType(什么奇偶法则等等)由于我被这个卡住了,所以在作图的时候画了三个path(逃)
切回主题,quadTo是Path类中,用来画二阶贝塞尔曲线的方法

 /**
     * Add a quadratic bezier from the last point, approaching control point
     * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
     * this contour, the first point is automatically set to (0,0).
     *
     * @param x1 The x-coordinate of the control point on a quadratic curve
     * @param y1 The y-coordinate of the control point on a quadratic curve
     * @param x2 The x-coordinate of the end point on a quadratic curve
     * @param y2 The y-coordinate of the end point on a quadratic curve
     */
    public void quadTo(float x1, float y1, float x2, float y2) {
        isSimplePath = false;
        nQuadTo(mNativePath, x1, y1, x2, y2);
    }

具体的贝塞尔曲线原理不多讲,但是要知道,quadTo的前两个参数是控制点的坐标,后者是结束点坐标。起点坐标就是path当前位置。
在这里插入图片描述
这里要找到点有三个,一个圆的上顶点,还有两条斜线的和x轴交点,以及另一个圆的上顶点,什么你看不见,我忘记画了,就在右边那里,自行脑补一下啦。
这样画出的贝塞尔曲线就像红色的那样,当然可能有点不标准,我用ps画的,有点丑见谅。
先说到这吧,贴关键代码

/**
     * 这个是拖动的形式
     * @param canvas
     * @param selectedPosition
     * @param selectionOffset
     */
    private void drawDragging(Canvas canvas,int selectedPosition, float selectionOffset) {
        //TODO 贝塞尔曲线
        float absOffset =selectedPosition==currentPosition?selectionOffset:selectionOffset-1;

        int[] firstPoint = selectedPosition==currentPosition?getStartCoordinate(selectedPosition):getStartCoordinate(selectedPosition+1);
        int[] secondPoint = selectedPosition==currentPosition?getStartCoordinate(selectedPosition):getStartCoordinate(selectedPosition+1);
        secondPoint[0]+=(absOffset)*getItemWidth();
        int spacing =Math.abs(firstPoint[0]-secondPoint[0]);
//        int[] movePoint = selectedPosition==currentPosition?getStartCoordinate(selectedPosition):getStartCoordinate(selectedPosition+1);
        float centerPointX = (float) (secondPoint[0]+firstPoint[0])/2+ (getItemWidth())*(1-selectionOffset);
        mDragPath.reset();
        if(selectionOffset<0.9){
            mDragPath.addCircle(
                    firstPoint[0]+getItemWidth()/2,
                    firstPoint[1]+getItemHeight()/2,
                    getRadius(),
                    selectionOffset>0 ? Path.Direction.CCW : Path.Direction.CW);
        }
        if(selectionOffset>0.1){
            mDragPath.addCircle(
                    secondPoint[0]+getItemWidth()/2,
                    secondPoint[1]+getItemHeight()/2,
                    getRadius(),
                    selectionOffset>0 ? Path.Direction.CCW : Path.Direction.CW);
        }
        mDragPath.close();
        canvas.drawPath(mDragPath, offsetPaint);
        if(selectionOffset>0.9||selectionOffset<0.1){

            return;
        }
        mDragPath.reset();
        mDragPath.moveTo(firstPoint[0]+getItemWidth()/2,getItemHeight()/2-getRadius());
        mDragPath.quadTo(centerPointX,getHeight()/2, secondPoint[0]+getItemWidth()/2, getItemHeight()/2-getRadius());
        mDragPath.lineTo(secondPoint[0]+getItemWidth()/2, getItemHeight()/2+getRadius());
        mDragPath.quadTo(centerPointX,getHeight()/2, firstPoint[0]+getItemWidth()/2, getItemHeight()/2+getRadius());
        mDragPath.lineTo(firstPoint[0]+getItemWidth()/2,getItemHeight()/2-getRadius());
        mDragPath.close();
        canvas.drawPath(mDragPath, offsetPaint);
    }

不考虑我的代码优雅性的话,关键点在于:根据我这个方法的传参,你需要提前知道当前position是哪一个。然后才能判断圆点是向左滑动还是向右。

PS:2019.1.5 00:51 具体完整的代码,我改天再传,好困。溜了溜了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值