android 根据bounds坐标进行点击操作_炫酷的Android时钟UI控件,隔壁产品都馋哭了...

废话不多说,先上效果924b64629b9516e99af336b1fe3f00d9.gif效果酷炫,动画丰富,效果爆炸boom~1dc61420c3f592e9ec4081bc83705c35.png设计思路看腻了市面上各种丑陋难看的时钟控件,是时候整点新活!将现实生活中的摆钟圆形表盘设计、电子手表的数显表盘设计抽象出来,提取出“圆形”、“数显”、“时光流逝感”等词汇,融合这些词汇特征,把特征赋予最终的UI设计......就这样,一个炫酷的UI控件诞生了!拨动时钟圆盘可以调整时钟,伴随时间的流逝,拨动的圆盘还能自动回位,交互逻辑自然顺畅。7c39fc8a54ab4eeef6f5d1878c1c595f.gif设置不同的主题色即可体现更多的内涵,“静谧”、“夜晚”、“月夜”、“纯净”等等,控件设计本身的可扩展性非常好。3a6012f339b041c3389bf576aaa0c449.png实现方案设计思路清晰明确之后,就要考虑如何实现了。来人,上口号。?没有人?比我?更懂☝️实现类设计从UI图中可以观察到,时钟控件由四个大表盘组成,分别是上下午表盘、小时表盘、分钟表盘、秒钟表盘。在实现思路上首先考虑抽象出圆盘控件父类DiskView,其余表盘均继承自DiskView即可。有了各种各样的表盘,最后再用ViewGroup将其进行组装。8b7f8de1e79a81c3245e41f14b72e232.png而DiskView作为基类,需要承担动画、拖动、点击等交互的逻辑,同时还要具备表盘的公共属性,例如表盘半径radius、表盘旋转角度degree等。
public class DiskView extends View {    private static final String TAG = "DiskView";    Context mContext;    /**     * 圆盘半径     */    int mRadius = 0;    /**     * 手指第一次按下时的坐标     */    float startX, startY;    /**     * 当前手指按下点的坐标     */    float curX, curY;    /**     * 第一次手指按下的点与初始位置形成的夹角     */    int startDegree;    /**     * 手指按下的点与初始位置形成的夹角     */    int curDegree;    /**     * 圆盘当前位置相对初始位置的角度,初始位置角度为0度     */    int degree = 0;    /**     * 手指抬起后是否需要回归原来的状态     */    boolean isNeedReturn = true;    ValueAnimator animator;}
UI绘制有了坐标、角度、半径、颜色等属性定义,接下来考虑绘制。绘制采用canvas的图形绘制api,计算好各个图形的位置,赋予对应的颜色。调用rotate方法围绕圆心绘制具有一定角度的文字。需要注意的是,绘制文字时要确保文字中线经过圆盘圆心。
@Overrideprotected void onDraw(Canvas canvas) {    super.onDraw(canvas);    //画圆盘    mPaint.setColor(diskColor);    canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);    //画数字    mPaint.setColor(numColor);    Rect bounds = new Rect();    for (int i = 0; i < 60; i++) {        if (i == minute) {            mPaint.setColor(selectNumColor);        } else {            mPaint.setColor(numColor);        }        if (i % 10 != 0) {            if (i % 5 == 0) {                canvas.drawCircle(mRadius, 2 * mRadius - textHeight * 3 / 2, DisplayUtils.sp2px(mContext, 20) / 4, mPaint);            } else {                canvas.drawCircle(mRadius, 2 * mRadius - textHeight * 3 / 2, DisplayUtils.sp2px(mContext, 20) / 6, mPaint);            }        } else {            mPaint.getTextBounds(i + "", 0, (i + "").length(), bounds);            textHeight = bounds.height();            canvas.drawText(i + "", mRadius - bounds.width() / 2, mRadius * 2 - bounds.height(), mPaint);        }        canvas.rotate(-6, mRadius, mRadius);    }}
交互逻辑控件交互逻辑大部分都在onTouchEvent的回调中进行处理,分别对用户的点击、移动、抬起动作做针对性处理,核心关键在于计算好各个情况的圆盘角度,之后再通过animator计算好对应的数值,实时刷新界面即可。需要注意的是用户的起始落点不能超过圆盘的界限,在单独使用某一个圆盘控件时要考虑边界限制。
@Overridepublic boolean onTouchEvent(MotionEvent event) {    curX = event.getX();    curY = event.getY();    switch (event.getAction()) {        case MotionEvent.ACTION_DOWN:            startX = event.getX();            startY = event.getY();            startDegree = computeCurrentAngle(curX, curY);            //起始落点不能超过圆盘界限            if (Math.sqrt(                    (startX - mRadius) * (startX - mRadius) + (startY - mRadius) * (startY - mRadius)            ) > mRadius) {                startDegree = 0;            }            break;        case MotionEvent.ACTION_MOVE:            //起始落点不能超过圆盘界限            if (Math.sqrt(                    (startX - mRadius) * (startX - mRadius) + (startY - mRadius) * (startY - mRadius)            ) > mRadius) {                return false;            }            curDegree = computeCurrentAngle(curX, curY);            postInvalidate();            break;        case MotionEvent.ACTION_UP:            if (Math.sqrt(                    (startX - mRadius) * (startX - mRadius) + (startY - mRadius) * (startY - mRadius)            ) > mRadius) {                return false;            }            int tmpDegree = degree;//手指按下前的圆盘角度            degree = degree + curDegree - startDegree;            if (Math.abs(degree) > 360) {                degree %= 360;            }            startDegree = 0;            curDegree = 0;            startX = 0;            startY = 0;            //是否需要回位            if (isNeedReturn) {                animator = ValueAnimator.ofInt(degree, tmpDegree);                animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {                    @Override                    public void onAnimationUpdate(ValueAnimator animation) {                        degree = (int) animation.getAnimatedValue();                        postInvalidate();                    }                });                animator.setDuration(200);                animator.setInterpolator(new DecelerateInterpolator());                animator.start();            }            break;    }    return true;}
后记自定义控件开发作为Android开发中的重要一环,如何利用好各个api实现功能是一方面,如何自顶向下进行设计才是重点。在开发之前最关键的事情并不是构思如何实现、如何设计,而是去发掘用户的需求,从需求倒推功能,再从功能角度考虑如何进行设计,最终呈现给用户。

bed78c77ff92acd79a57b2e54442cdb6.png

技术交流,欢迎加我微信:ezglumes ,拉你入技术交流群。

84cc89488e316fce4bb27e65782cd05f.png

推荐阅读:

音视频面试基础题

OpenGL ES 学习资源分享

开通专辑 | 细数那些年写过的技术文章专辑

NDK 学习进阶免费视频来了

推荐几个堪称教科书级别的 Android 音视频入门项目

觉得不错,点个在看呗~

0232b97c75400f541afbc152338ec94e.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/528106.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

打了断点为直接运行完_BBC主持人多次打断,香港大律师忍不住发飙

来源:环球网7月7日&#xff0c;香港资深大律师汤家骅就香港《国安法》相关内容接受BBC栏目《唇枪舌剑》(HARDtalk)采访。节目主持人斯蒂芬•萨克在整个访问过程中频频打断汤家骅&#xff0c;根本不让汤家骅回答完问题。视频显示&#xff0c;汤家骅多次试图向萨克解释《国安法》…

指针 是否相同_算法一招鲜——双指针问题

什么是双指针&#xff08;对撞指针、快慢指针&#xff09;双指针&#xff0c;指的是在遍历对象的过程中&#xff0c;不是普通的使用单个指针进行访问&#xff0c;而是使用两个相同方向&#xff08;快慢指针&#xff09;或者相反方向&#xff08;对撞指针&#xff09;的指针进行…

作为神经网络的输入_MATLAB实战|基于神经网络河南省降水量预测

1 BP神经网络结构神经网络旨在通过模仿动物的神经系统利用神经元作为连接结点的新型智能算法&#xff0c;神经网络本身包含三层结构&#xff0c;输入层&#xff0c;隐含层&#xff0c;输出层&#xff0c;每一层都有自己的特殊功能&#xff0c;输入层进行因子的输入与处理。由于…

docker kafka互通有问题_Docker搭建kafka集群

拉取镜像docker pull wurstmeister/kafka docker pull wurstmeister/zookeeper启动镜像docker run --name zookeeper -p 12181:2181 -d wurstmeister/zookeeper:latestdocker run -p 19092:9092 --name kafka1 -d -e KAFKA_BROKER_ID0 -e KAFKA_ZOOKEEPER_CONNECT宿主机ip:1218…

elementui 上传七牛_element ui使用上传组件上传文件到七牛(qiniu-js)

博主正在重构博客中&#xff0c;刚开始时静态资源都是上传到本地服务器的&#xff0c;但这个项目博主最后打算真正上线运营的。索性就改进了下&#xff0c;把静态资源尽量放到云存储中&#xff0c;方便后续开发。这里把方法和遇到坑给记录下。1.使用前提注册七牛云并创建存储空…

bool类型0和1真假_MySQL整理5—数据类型和运算符

数据科学探路者&#xff1a;MySQL整理4—数据表的基本操作2​zhuanlan.zhihu.com一、数据类型数据科学探路者&#xff1a;MySQL知识整理1—数据库基础​zhuanlan.zhihu.com在上面链接的部分内容中&#xff0c;介绍了以下数据类型&#xff1a;整数类型&#xff1a;BIT、BOOL、TI…

linux启动mysql1820_linux 系统下MySQL5.7重置root密码(完整版,含ERROR 1820 (HY000)解决方案)...

mysql的root密码忘记了怎么重置&#xff1f;往下看&#xff1a;1.保证你的mysql服务处于关闭状态。(用ps -ef | grep mysql 查看进程&#xff0c;有则kill -9 进程号)2.在my.cnf所在目录中执行 vim my.cnf3.在[mysqld] 后边加入skip-grant-tables如图&#xff1a;并保存。4.启动…

mysql谓词演算_MySQL基础知识

一、了解MySQL1、什么是数据库&#xff1f;数据库是一种以某种有组织的方式存储的数据集合。2、模式(schema):关于数据库和表的布局及特性的信息。3、列&#xff1a;正确的将数据分解为多个列极为重要。通过把它分解开&#xff0c;才有可能利用特定的列对数据进行排序和过滤。4…

mysql+缓冲池脏块率高_什么是数据库的 “缓存池” ?(万字干货)

原标题&#xff1a;什么是数据库的 “缓存池” &#xff1f;(万字干货)1、Buffer Pool 概述Buffer Pool 是什么&#xff1f;从字面上看是 缓存池 的意思&#xff0c;没错&#xff0c;它其实也就是 缓存池 的意思。它是 MySQL 当中至关重要的一个组件&#xff0c;可以这么说&…

mysql多实例配置安装_MySQL多实例安装配置方案

一.基本概念MySQL多实例就是&#xff0c;在一台机器上开启多个不同的服务端口(如&#xff1a;3306,3307,3308...)&#xff0c;运行多个MySQL服务进程&#xff0c;这些服务进程通过不同的socket监听不同的端口提供服务。MySQL可以共用一套安全程序&#xff0c;使用不同的my.cnf配…

java趣味_Java趣味分享:try finally

考虑以下四个测试方法&#xff0c;它们会输出什么&#xff1f;public class Test {public static void main(String\[\] args) {System.out.println(test1());System.out.println(test2());System.out.println(test3());System.out.println(test4());}private static int test1…

java 纯面向对象_Java到底是不是一种纯面向对象语言?

原标题&#xff1a;Java到底是不是一种纯面向对象语言&#xff1f;Java——是否确实的 “纯面向对象”&#xff1f;让我们深入到Java的世界&#xff0c;试图来证实它。在我刚开始学习 Java 的前面几年&#xff0c;我从书本里知道了 Java 是遵循 “面向对象编程范式(Object Orie…

java爬虫post 404_POST 后台404错误

今天在开发一个用户信息更新模块的时候遇到了两个问题&#xff1a;1、在我提交form表单的时候我希望在提交表单之后页面不刷新&#xff0c;同时返回更新数据2、向后台POST表单信息的时候&#xff0c;后台显示POST url 404的错误解决第一个问题的使用使用jquery.form的插件进行异…

java防止重复启动bat_java调用exe,及调用bat不成功的解决办法

开门见山的说&#xff0c;文件目录如下想调用123.exe,但是尝试了几次调用不到&#xff0c;然后写了个bat。初始内容如下echo offD:cd test"123.exe"双击可以运行&#xff0c;但是java代码无法调用&#xff0c;怪事。于是&#xff0c;辗转反侧&#xff0c;苦思冥想&am…

java8.0 platform图_Java Platform SE binary语言-Java编程32位/64位版(jdk-jeb)下载V8.0.2510.8官方安装版-西西软件下载...

Java编程32位/64位版(jdk-jeb)是一款功能强大的计算机编程语言工具&#xff0c;Java技术让您可以在安全的计算环境下工作和游戏。使用 Java您可以畅玩网络游戏、与世界各地的朋友聊天、计算按揭利息&#xff0c;还可以在 3D 模式下浏览图像&#xff0c;诸多功能不一而足。软件特…

java 线程由浅入深_由浅入深,Java 并发编程中的 Synchronized(一)

synchronized 作用synchronized 关键字是 Java 并发编程中线程同步的常用手段之一。1.1 作用&#xff1a;确保线程互斥的访问同步代&#xff0c;锁自动释放&#xff0c;多个线程操作同个代码块或函数必须排队获得锁&#xff0c;保证共享变量的修改能够及时可见&#xff0c;获得…

php有哪些高级扩展,php扩展有哪些

什么是PHP扩展&#xff1f;为PHP提供一些扩展的功能常见的PHP扩展mysql-----提供给PHP操作MySQL数据库的功能gd2----动态创建图像xdebug-----跟踪、调试和分析PHP程序的运行状况查看PHP扩展1.使用phpinfo探针phpinfo()---输出关于PHP配置的信息输出PHP当前状态的大量信息&#…

php 图片系统,Linger

软件简介Linger 是 PHP 图片分享系统。一个精简的图片分享系统网站&#xff0c;采用Bootstrap前端框架&#xff0c;支持部分页面的移动端自适应。同时采用HTML5进行图片批量上传。使用了一个简单的时间线动态展示&#xff0c;可作为简易的图片社交社区。有一个完整的用户中心和…

php 传递类名,php 对象和数组序列化 serialize()返回字符串方便存储和传递 unserialize()反序列化 不丢失类型和结构...

现在开发中经常使用序列号和反序列化技术手段&#xff0c;php开发中也大量使用到。如下几个知名系统都使用了大量的序列化技术ecshop2. phpcms内容管理系统3.laravel框架一、序列号的目的&#xff1f;方便数组和对象的传输或存储&#xff0c;同时不丢失其类型和结构如下是ecsho…

python操作json字符串,超详细的Python文件操作知识

来自&#xff1a;CSDN&#xff0c;作者&#xff1a;南枝向暖北枝寒MA链接&#xff1a;https://blog.csdn.net/mall_lucy/article/details/104547365【导语】&#xff1a;python进行文件操作&#xff0c;在日常编程中是很常用的。为了方便大家&#xff0c;这里对各种文件操作的知…