博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
界面无小事(四):来写个滚动选择器吧!
阅读量:5751 次
发布时间:2019-06-18

本文共 3823 字,大约阅读时间需要 12 分钟。


目录

  • 效果图
  • 前言
  • Paint类
  • 计时器
  • 基线baseline
  • 滚动选择器实现
  • 最后

效果图

不废话, 先上效果图. 觉得有趣再往下看吧.

效果图
效果图

前言

在pc时代, 输入一般都依靠键盘. 对于像选时间这种操作, win一般会列出全部日期, 然后让你点击选择. 说句实话, 土爆了. 当然了, 滚动选时间也土爆了(手动尴尬), 但是比win的操作方式已经有趣不少了. 而且滚动选择器我觉得还是有很多不错的应用场景的, 所以这次就写一个分享给大家.


Paint类

Paint还是很值得熟悉的一个类, 大部分函数都是set方法, 去文档看就好了. 本文有两个Paint实例, 一个是绘制文本用, 一个是绘线.

mPaint = new Paint();// 设置抗锯齿mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);// 设置文本对齐方式mPaint.setTextAlign(Paint.Align.CENTER);// 设置画笔颜色mPaint.setColor(UIUtil.getColor(R.color.colorText));mLinePaint = new Paint();mLinePaint.setColor(UIUtil.getColor(R.color.colorPrimaryTrans));

后续代码中, Paint实例会依据曲线设置文本字号以及透明度. 所以, 我们需要自己设置最小最大字号, 最小最大透明度, 这样就可以在范围内依据函数曲线变化. 差不多就是下图, 但是y是大于0的.

变化曲线
变化曲线
// 依据曲线设置字号float scale = gradient(mMax, mMoveLen);float size = (mMax - mMin) * scale + mMin;mPaint.setTextSize(size);// 依据曲线设置透明度mPaint.setAlpha((int) ((mMaxAlpha - mMinAlpha) * scale + mMinAlpha));

计时器

计时器是经常用到的, Android里面会用Timer, TimerTask, Handler三个组合使用. 思路就是Timer实例使用schedule函数, 传入TimerTask实例以及时间参数. 然后在TimerTask实例的run方法中让Handler实例调用sendMessage方法发送消息. 最后在handleMessage方法中处理. 代码如下:

mTask = new MyTimerTask(mHandler);mTimer.schedule(mTask, 0, 10);
private class MyTimerTask extends TimerTask {    Handler handler;    public MyTimerTask(Handler handler) {        this.handler = handler;    }    @Override    public void run() {        handler.sendMessage(handler.obtainMessage());    }}
Handler mHandler = new Handler() {    @Override    public void handleMessage(Message msg) {        // 逐步回滚, 直到小于指定值, 选中目标        if (Math.abs(mMoveLen) < BACK_SPEED) {            // 选中            mMoveLen = 0;            if (mTask != null) {                mTask.cancel();                mTask = null;                select();            }        } else {            // 滚动            mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * BACK_SPEED;        }        invalidate();    }};

基线baseline

最后来谈谈玄学, 基线. Android的绘制是基于基线的. 那什么是基线, 来看两张图片:

玄学图1
玄学图1
玄学图2
玄学图2

也就是说, 想要把某个文本垂直居中, 除了要获取View的高度, 还要获取文本的高度. 这里就需要Paint.FontMetrics类了, 里面有我们要的参数.

这里有两种思路, 依靠top和bottom算出文本高度, 或者依靠ascent和descent. 你对上面哪张图更理解, 就用哪个. 还有一点要说的就是, 所有参数都是相对于baseline的, 比方说top就可能是-100, bottom就会是30.

float baseline = y - (fmi.top + fmi.bottom) / 2.0f;float baseline = y - (fmi.ascent + fmi.descent) / 2.0f;

滚动选择器实现

要想实现滚动选择器, 肯定还是要处理触摸操作的. 如果对自定义视图不熟悉的, 可以看看我之前的文章. 或者google一下. 要点就是抬手时候开启计时器, 点下记录位置, 移动重绘. 然后为了头尾衔接, 需要在到顶和到底的时候处理下List中的内容.

@Overridepublic boolean onTouchEvent(MotionEvent event) {    switch (event.getActionMasked()) {        case MotionEvent.ACTION_DOWN: {            if (mTask != null) {                mTask.cancel();                mTask = null;            }            mLastDownY = event.getY();        }        break;        case MotionEvent.ACTION_MOVE: {            mMoveLen += (event.getY() - mLastDownY);            if (mMoveLen > DIS * mMin / 2) {                tailToHead();                mMoveLen = mMoveLen - DIS * mMin;            } else if (mMoveLen < -DIS * mMin / 2) {                headToTail();                mMoveLen = mMoveLen + DIS * mMin;            }            mLastDownY = event.getY();            invalidate();        }        break;        case MotionEvent.ACTION_UP: {            // 移动过小就不移动            if (Math.abs(mMoveLen) < 0.001) {                mMoveLen = 0;                break;            }            if (mTask != null) {                mTask.cancel();                mTask = null;            }            mTask = new MyTimerTask(mHandler);            mTimer.schedule(mTask, 0, 10);        }        break;    }    return true;}
private void headToTail() {    String head = mData.get(0);    mData.remove(0);    mData.add(head);}private void tailToHead() {    String tail = mData.get(mData.size() - 1);    mData.remove(mData.size() - 1);    mData.add(0, tail);}

最后

有段时间没写文章了, 也是忙一些乱七八糟的事情去了. 写得有点找不到感觉, 之后会努力写出有趣的分享文章来的. 喜欢可以点赞或者关注我哦~


转载地址:http://diukx.baihongyu.com/

你可能感兴趣的文章
我最常用的几个Xcode快键键
查看>>
Educational Codeforces Round 8 A. Tennis Tournament 暴力
查看>>
Node.js模块
查看>>
玩转iOS开发 - JSON 和 Xml 数据解析
查看>>
Undefined symbols for architecture i386: "_deflate", referenced from:
查看>>
String的split()方法探索和大揭秘
查看>>
mysql中变量character_set_connection的具体作用
查看>>
小酌重构系列[12]——去除上帝类
查看>>
FPGA学习手记(四)ModelSim入门及Testbench编写——合理利用仿真才是王道
查看>>
android 面试
查看>>
jQuery 遍历函数
查看>>
《寄生兽》观后感
查看>>
IntelliJ IDEA 的 Jetty部署插件
查看>>
x-forwarded-for的深度挖掘
查看>>
正则表达式元字符表
查看>>
secure_file_priv 配置项对数据导入导出的影响
查看>>
Linux 下编译升级 Python
查看>>
Winform开发框架之字段权限控制
查看>>
【Swift 2.2】iOS开发笔记(三)
查看>>
(MySQL里的数据)通过Sqoop Import Hive 里 和 通过Sqoop Export Hive 里的数据到(MySQL)...
查看>>