滑轮选择器

452 查看


原来做项目时用到了滑轮选择器,也是借鉴了别人的,但当时时间紧也就没自己怎么优化与巩固,最近时间充足就重新巩固了一下,在这里记下自己的心得与实现方法以免以后生疏,有不足的地方欢迎指教。


实现原理

  • 首先自定义了一个PickerView继承android原生的View

  • 实现滑动点击监听事件,通过一系列触摸判断实现滑动效果

  • 其次TextPicker继承PopupWindow装载这个PickerView实现展示

原理还是很简单的,主要的就是自定义的PickerView

PickerView的实现

其中主要的实现方法是onDrawView()drawOtherView绘制滑轮选择器的文本显示,然后就是触摸事件onTouchEvent()的事件处理。

onDrawView的想法

滑轮的文本效果是要中间的文本显示正常而上面与下面的文本要相应的缩小字体大小达到远离的感觉,所用首先绘制好中间的文本,再以中间的文本为中心绘制上下的文本,下面是部分源码

    private void onDrawView(Canvas canvas) {
        float scal = getParabola((screenHeight / 4.0f), moveLength);
        //字体居中显示
        float x = screenWidth / 2.0f;
        float y = screenHeight / 2.0f + moveLength;
        float size = (maxTextSize - minTextSize) * scal + minTextSize;
        //获得Paint的属性参数
        Paint.FontMetricsInt pfm = mPaint.getFontMetricsInt();
        //得到居中y
        float baseLine = y - (pfm.top + pfm.bottom) / 2;
        mPaint.setTextSize(size);
        mPaint.setAlpha((int) ((maxAlpha - minAlpha) * scal + minAlpha));
        //画中间位置
        canvas.drawText(dataList.get(position), x, baseLine, mPaint);
        //画上面位置
        for (int i = 1; position - i >= 0; i++) {
            drawOtherView(canvas, i, -1);
        }
        //画下面的位置
        for (int i = 1; position + i < dataList.size(); i++) {
            drawOtherView(canvas, i, 1);
        }
    }  
    
    
    private void drawOtherView(Canvas canvas, int i, int direction) {
        float offsetY = (MARGIN * minTextSize * i + moveLength * direction);
        float scal = getParabola(screenHeight / 4.0f, offsetY);
        float x = screenWidth / 2.0f;
        float y = screenHeight / 2.0f + direction * offsetY;
        float size = (maxTextSize - minTextSize) * scal + minTextSize;
        float alpha = (maxAlpha - minAlpha) * scal + minAlpha;
        Paint.FontMetricsInt pfm = mPaint.getFontMetricsInt();
        float baseLine = (float) (y - (pfm.top + pfm.bottom) / 2.0);
        mPaint.setTextSize(size);
        mPaint.setAlpha((int) alpha);
        canvas.drawText(dataList.get(position + direction * i), x, baseLine, mPaint);
    }

然后就是触摸滑动效果,通过doDown(),doMove()doUp()来操作

private void doMove(MotionEvent event) {
        moveLength += event.getY() - eventY;
        if (moveLength > MARGIN * minTextSize / 2) {
            //手指向下滑动滑出边界
            moveFootTOHead();
            moveLength = moveLength - MARGIN * minTextSize;
        } else if (moveLength < -MARGIN * minTextSize / 2) {
            //手指向上滑动滑出边界
            moveHeadToFoot();
            moveLength = moveLength + MARGIN * minTextSize;
        }
        eventY = event.getY();
        invalidate();
    }

PickerView的主意方法就这些了,是不是很简单

实现了PickerView就可以在单独的一个xml中布局,xml的代码就不贴了

TextPicker

对于xml中PickerView进行了封装,因为可以项目中要用到多次,所用写个封装类还是必须的

对外方法

  • setPickerTitle(String text) 设置标题

  • setData(List<String> dataList, int i) 填充数据

  • setMiddleText(int position, int i) 设置居中文本

  • getText(int i) 获取文本

  • getOK() 获取确定控件

  • setPrepare() 开启

实现

最后就是实例化中TextPicker调用其方法实现

tp = new TextPicker(this);
        //初始化数据
        initData();
        //加载数据
        tp.setData(leftList, 1);
        tp.setData(middleList, 2);
        tp.setData(rightList, 3);
        //设置标题
        tp.setPickerTitle("标题");
        //设置默认居中文本
        tp.setMiddleText(5, 1);
        tp.setMiddleText(2, 2);
        tp.setMiddleText(25, 3);
        //准备完毕
        tp.setPrepare();
        ok = tp.getOK();
        ok.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                leftText = tp.getText(1);
                middleText = tp.getText(2);
                rightText = tp.getText(3);
                tv.setText(leftText+"-"+middleText+"-"+rightText);
                tp.dismiss();
            }
        });
        //展示
        tp.showAtLocation(this.findViewById(R.id.main), Gravity.CENTER, 0, 0);

效果图

更多源代码:https://github.com/idisfkj/idisfkj.picker

个人博客:https://idisfkj.github.io/