找回密码
 立即注册
搜索
查看: 7|回复: 0

抖音超火时钟罗盘壁纸实现:自定义控件的方法及代码解析

[复制链接]

2万

主题

0

回帖

8万

积分

管理员

积分
86983
发表于 15 小时前 | 显示全部楼层 |阅读模式
近期抖音平台上流行的时钟罗盘壁纸异常受欢迎,今天我们便来尝试通过自定义控件来打造这一功能。

效果图:

软件详情:

时钟罗盘充当动态壁纸,其上的时钟随时间流逝而不断变换,去掉了月份和星期的标注,取而代之的是充满活力的彩色文字,整体视觉效果因而不再显得单调乏味。

代码实现:

创建一个继承自 View 的类,并为其设计一个接受一个参数的构造函数以及一个接受两个参数的构造函数,分别用于代码编写和布局设计。

<p><pre class="has">    <code>public DateTimeView创建于特定上下文环境中,以接收该上下文作为参数。
        this(context, null);
}
public DateTimeView 被设计为接受一个上下文对象和可空属性集,以构建日期时间视图。
        super(context, attributeSet);
在初始化过程中,我创建了用于绘制时分秒的画笔对象,赋值给变量this.paint。
        mContext = context;
        initData();
        init();
}
</code></pre></p>
接下来,我们将探讨()方法,该方法负责初始化数据,具体对应数字罗盘上的时分秒数值;同时,我们还将关注init()方法,该方法旨在创建画笔Paint并对其进行参数设置,并负责初始化定时器。

<p><pre class="has">    <code>  private void initData() {
        this.mScale = 0.5f;
        this.secondDelta = 0.0f;
        this.dayIndex = 0;
此处定义了一个字符串数组,其元素包括:"一"、"二"、"三"、"四"、"五"、"六"、"七"、"八"、"九"、"十"、"十一"、"十二"、"十三"、"十四"、"十五"、"十六"、"十七"、"十八"、"十九"、"二十"、"二十一"、"二十二"、"二十三"、"二十四"、"二十五"、"二十六"、"二十七"、"二十八"、"二十九"、"三十"、"三十一"。
        this.hourIndex = 0;
此变量hours被赋予了一个新的字符串数组,其中包含了以下十二个汉字:一、二、三、四、五、六、七、八、九、十、十一、十二。
        this.minusIndex = 0;
this.minutes = new String[]{"第一分钟", "第二分钟", "第三分钟", "第四分钟", "第五分钟", "第六分钟", "第七分钟", "第八分钟", "第九分钟", "第十分钟", "第十一分钟", "第十二分钟", "第十三分钟", "第十四分钟", "第十五分钟", "第十六分钟", "第十七分钟", "第十八分钟", "第十九分钟", "第二十分钟", "第二十一年级", "第二十二分钟", "第二十三分钟", "第二十四分钟", "第二十五分钟", "第二十六分钟", "第二十七分钟", "第二十八分钟", "第二十九分钟", "第三十分钟", "第三十一年级", "第三十二分钟", "第三十三分钟", "第三十四分钟", "第三十五分钟", "第三十六分钟", "第三十七分钟", "第三十八分钟", "第三十九分钟", "第四十分", "第四十一年级", "第四十二分钟", "第四十三分钟", "第四十四分钟", "第四十五分钟", "第四十六分钟", "第四十七分钟", "第四十八分钟", "第四十九分钟", "第五十分钟", "第五十一年级", "第五十二分钟", "第五十三分钟", "第五十四分钟", "第五十五分钟", "第五十六分钟", "第五十七分钟", "第五十八分钟", "第五十九分钟", "空字符串"};
        this.secondIndex = 0;
this.seconds = new String[]{"第一秒", "第二秒", "第三秒", "第四秒", "第五秒", "第六秒", "第七秒", "第八秒", "第九秒", "第十秒", "第十一秒", "第十二秒", "第十三秒", "第十四秒", "第十五秒", "第十六秒", "第十七秒", "第十八秒", "第十九秒", "第二十秒", "第二十一秒", "第二十二秒", "第二十三秒", "第二十四秒", "第二十五秒", "第二十六秒", "第二十七秒", "第二十八秒", "第二十九秒", "第三十秒", "第三十一秒", "第三十二秒", "第三十三秒", "第三十四秒", "第三十五秒", "第三十六秒", "第三十七秒", "第三十八秒", "第三十九秒", "第四十秒", "第四十一秒", "第四十二秒", "第四十三秒", "第四十四秒", "第四十五秒", "第四十六秒", "第四十七秒", "第四十八秒", "第四十九秒", "第五十秒", "第五十一秒", "第五十二秒", "第五十三秒", "第五十四秒", "第五十五秒", "第五十六秒", "第五十七秒", "第五十八秒", "第五十九秒", "空字符串"};
    }</code></pre></p>
<p><pre class="has">    <code> private void init() {
此画笔用于时分秒的描绘,已将其抗锯齿功能设置为开启状态。
此画笔的颜色设置为纯白色。
此代码行将绘制文本的字体大小设置为50.0点;同时,对paint对象进行了调整。
创建一个单线程的定时任务执行器,并安排执行一个周期性定时任务,任务由以下代码块定义:Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
获取当前日期的日历实例:Calendar instance = Calendar.getInstance();
DateTimeView对象的本日索引值被设置为实例中的日历日期减去一。
DateTimeView实例的hourIndex属性被设置为从instance获取的当前小时数减去1。
DateTimeView对象中的minusIndex属性被设置为instance获取的当前分钟数减去1。
DateTimeView对象中的secondIndex属性被设置为instance获取的当前秒数减去一。
DateTimeView对象中的secondDelta值被设置为:通过取当前系统时间戳与1000的余数,将其转换为浮点数后乘以1.0f,再除以1000.0f,最后乘以3.0f。
若DateTimeView类的secondDelta属性值超过0.6浮点数,则{
DateTimeView对象中的secondDelta属性被设置为1.0浮点数。
                }
DateTimeView对象调用其postInvalidate方法执行。
            }
设置延迟时间为0毫秒,持续16毫秒,单位为毫秒。
创建一个新的Paint对象,用于绘制中间的文字内容。


设置画笔颜色为白色,mTextPaint的颜色属性被调整为Color.WHITE。
设置文本绘制样式为填充与描边相结合。
设置画笔宽度为3像素,mTextPaint的属性得以调整。
mTextPaint的抗锯齿功能被激活;当此选项设为“true”时,虽然可能会降低性能,但需根据实际使用情况来决定是否启用。
设置文本绘制的笔触为圆形,这指的是画笔画出的线条两端呈现的样式,类似于笔帽的形状。
设置文本绘制画笔的线条连接方式为圆角样式,使得两条线段在交汇处呈现平滑过渡效果。
mTextPaint.调整字符间的间隔值为12。
mTextPaint.setTextSize(dpToPx(70)); // 对文本画笔的字符大小进行设定,数值为通过dp转px计算得出的70
设置文本画笔的文本对齐为居中,确保文本内容在画布上水平居中显示。
在当前上下文中,我们通过以下方式创建了一个自定义字体:从资源文件中提取,具体操作是使用`createFromAsset`方法,该方法接收两个参数:一个是上下文对象`mContext`的`getAssets()`方法返回的资源管理器,另一个是字体文件的名称`"yzqs.ttf"`。
设置文本绘制器的字体为自定义字体,具体为通过创建字体对象来加载指定家族和样式的字体,即使用Typeface.create(familyName, style)方法。
视图宽度被设置为通过DimensionUtil工具将70dp转换成像素值得到的结果。
        //实现中间文字炫彩效果
其终止点位于屏幕宽度的两倍处,同样垂直方向上坐标为零。
创建了一个包含白色、绿色、青色、蓝色、红色和绿色以及白色的整数数组,指定了null值,并应用了Shader的平铺模式为CLAMP。
mTextPaint应用了mLinearGradient所设定的着色器。
创建一个新的Matrix对象,命名为mGradientMatrix。
创建一个用于绘制顶部提示信息的Paint对象,命名为mTextPaint2。
对mTextPaint2进行设置,开启抗锯齿功能。
设置画笔颜色为白色,mTextPaint2的颜色属性被调整为Color.WHITE。
设置mTextPaint2的绘画样式为填充与描边相结合。
为mTextPaint2指定了customFont字体样式。
mTextPaint2设置文本对齐方式为居中对齐。
    }</code></pre></p>
数据与画笔均已准备就绪,现在,我们将着手绘制所需的效果,这涉及到了()方法,即启动绘画过程的函数。

<p><pre class="has">    <code>//绘画顶部的提示语
创建了一个SimpleDateFormat对象,命名为formatter,并设置了其格式为“HH:mm”。
当前日期为curDate,该变量通过调用System.currentTimeMillis()方法获取系统当前时间戳,进而构造出一个Date对象。
mTextPaint2.setTextSize(dpToPx(25)); // 对字符大小进行设定
canvas在canvas2的宽度中心位置,使用mTextPaint2绘制文字提示,内容为“明明什么都没做”,并调用dpToPx函数将40dp转换为像素值。
mTextPaint2.setFontSize(dp转换为像素值(45)); // 对文本绘制对象设置字体大小
在画布上,我使用了drawText方法,将"就已经 "与格式化后的当前日期字符串连接,并居中绘制在画布2的宽度一半的位置,同时考虑到dp转像素后的40倍数加上40像素,最后用mTextPaint2画笔完成提示语的绘制。
//画姓氏
canvas在画布上绘制文字,姓氏为mName,位置位于canvas2宽度的一半,高度的一半向上偏移26像素,所使用的画笔为mTextPaint。
//画时分秒
String[] strArr = this.hours;
此处的mScale值计算如下:首先,将画布的宽度转换为浮点数,然后除以1080.0,最后乘以0.5。
float f3等于0.0f减去((float) this.hourIndex乘以length)的结果。
        int i4 = 0;
        f = f3;
遍历字符串数组中的每一个元素,对每个字符串进行操作。
            matrix.reset();
matrix执行了翻译操作,其参数分别为300.0f和0.0f;postTranslate方法被调用。


matrix执行了围绕原点旋转的操作,旋转角度为f度;同时,旋转的中心坐标保持在(0.0f, 0.0f)。
            f += length;
matrix执行了postTranslate方法,其参数分别为:宽度的一半转换为浮点数,以及高度的一半也转换为浮点数。
            f2 = this.mScale;
matrix执行了缩放操作,缩放比例分别为f2和f2,缩放中心点位于窗口的中心位置,具体坐标为窗口宽度的一半和高度的一半。
            canvas2.setMatrix(matrix);
此画笔的颜色设置为:若当前小时索引与i4相等,则设为白色;否则,设为-7829368色。
创建一个新的StringBuilder对象,并将其赋值给变量stringBuilder。
            stringBuilder.append(str222);
            stringBuilder.append("点");
canvas2在画布上绘制文本,文本内容为stringBuilder转换得到的字符串,起始位置为(0.0f, 0.0f),使用的是this.paint进行绘制。
            i4++;
        }
        strArr = this.minutes;
长度值等于360.0f除以字符串数组长度的浮点数表示;
f3的值等于0.0f减去((float) this.minusIndex)乘以length的结果。
        f = f3;
        i4 = 0;
遍历字符串数组strArr中的每一个元素,针对每个元素进行操作:。
            matrix.reset();
matrix执行了postTranslate方法,其中第一个参数为500.0f,第二个参数为0.0f。
            matrix.postRotate(f, 0.0f, 0.0f);
            f += length;
            matrix.postTranslate((float) (getWidth() / 2), (float) (getHeight() / 2));
            f2 = this.mScale;
            matrix.postScale(f2, f2, (float) (getWidth() / 2), (float) (getHeight() / 2));
            canvas2.setMatrix(matrix);
此画笔的颜色设置为:若索引i4等于减去索引,则变为白色;否则,设定为-7829368色值。
canvas2上绘制文本,内容为str2222,起始位置在坐标(0.0f, 0.0f),使用的是this.paint进行绘制。
            i4++;
        }
        strArr = this.seconds;
float length3 = 360.0f 除以 (strArr的长度转换成float类型);
长度值计算如下:首先,将当前索引的浮点数形式乘以长度三,然后从零点零浮点数中减去这个结果;接着,再将第二差值乘以长度三;最后,将这两个计算结果相减,得到最终的长度值。
        float f5 = length;
        int i5 = 0;
        for (String str3 : strArr) {
            matrix.reset();
matrix执行了postTranslate方法,参数分别为760.0f和0.0f。
matrix执行了围绕原点旋转的操作,旋转角度为f5度;同时,旋转的中心坐标保持在(0.0f, 0.0f)。
            f5 += length3;
            matrix.postTranslate((float) (getWidth() / 2), (float) (getHeight() / 2));
            float f6 = this.mScale;
matrix执行了缩放操作,缩放比例分别为f6和f6,缩放中心位于窗口宽度的二分之一处,以及窗口高度的二分之一处。
            canvas2.setMatrix(matrix);
若此处的secondDelta值恰好等于1.0浮点数。
此画笔的颜色设置为:若索引i5等于第二个索引加一,则变为白色;否则,变为-7829368色。
            } else {
此画笔的颜色设置为:若当前索引等于第二个索引,则变为白色;否则,变为-7829368色。
            }
canvas2在坐标(0.0f, 0.0f)处绘制文本,所绘文本内容为str3,绘制时使用的画笔为this.paint。
            i5++;
        }</code></pre></p>
此处仅展示了关键代码片段,详细代码内容尚未提供,如遇疑问,请于下方评论区留言沟通。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|【宏智网络】 ( 京ICP备20013102号 )

GMT+8, 2025-6-18 22:15 , Processed in 0.125805 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表