首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何使用Kotlin构建Android旋转旋钮以帮助儿子练习钢琴

当我儿子的钢琴老师告诉他应该使用节拍器练习计时时,我借此机会使用了Kotlin。我决定使用编程语言和Android的生态系统,以便构建Metronome应用程序。

我最初的实现使用SeekBar来控制BPM(每分钟节拍数)-节拍器滴答声的速率。但是,随着项目的进行,我想使其像一个物理数字单元,就像现实世界中许多音乐家所使用的那样。物理单位没有“ SeekBar视图”,我想模拟实际单位可能具有的旋钮。旋钮是非常有用的UI控件。它们很像滑块或SeekBar,可在许多情况下使用。以下是它们的一些优点:他们在您的应用中消耗的很少,它们可用于控制值的连续或离散范围,用户可以立即从实际应用程序中识别它们,它们不是标准的Android控件,因此可为您的应用赋予独特的“自定义”感觉,尽管存在一些适用于Android的开放源代码旋钮库,但我在任何一个库中都找不到我想要的东西。,对于我的适度需求,许多工具都有些过分了,例如设置背景图像或处理两个或多个模式操作的水龙头等。有些工具没有我想适合我的项目的可定制性,而是带有自己的旋钮图像。还有一些假设值或位置的离散范围。而且其中许多似乎比需要的要复杂得多。因此,我决定自己设计一个,这就变成了一个有趣的小项目了。在本文中,我将讨论如何构建它。下面这个就是成品。

节拍器应用程序及其旋钮

因此,让我们看看如何创建一个旋钮。

设计旋钮

第一步是为旋钮本身创建图形。我不是一个设计师,但是我想到在旋钮控件中营造“深度”和运动感的关键是使用偏心的径向渐变。这将使我产生表面凹陷和光反射的错觉。我使用Sketch绘制了旋钮,然后将其导出到svg。然后,将其作为可绘制对象导入Android Studio。

在xml中创建视图

创建视图的第一步是在res / layout文件夹中创建一个xml布局文件。可以使用代码完全创建视图,但是应该使用xml创建Android中良好的可重用视图。

注意标记-我们将使用它,因为我们将扩展现有的Android Layout类,并且此布局将是该布局的内部结构。我们将对旋钮使用ImageView,并随着用户移动它进行旋转。

为了使该旋钮可通过xml配置,我们将为该旋钮将返回的值的范围以及用于可视化的drawable创建属性。我们将在res / values下创建一个attrs.xml文件。

接下来,创建一个新的Kotlin类文件RotaryKnobView,该文件扩展了RelativeLayout并实现了接口GestureDetector.OnGestureListener。

我们将使用RelativeLayout作为控件的父容器,并实现OnGestureListener来处理旋钮的移动手势。接下来,我们将初始化一些默认值并定义类成员。

关于分频器变量的注释-我希望旋钮具有开始和结束位置,而不是能够无限旋转,就像立体声系统上的音量旋钮一样。我将起点和终点分别设置为-150度和150度。因此,旋钮的有效运动仅为300度。

我们将使用除法器来分配希望旋钮在这些可用的300度上返回的值的范围-以便我们可以根据旋钮的位置角度来计算实际值。

接下来,我们初始化组件:

1、放大布局。

2、将属性读入变量。

3、更新除法器(以支持传入的最小值和最大值)

4、设置图像。

由于我们需要实现OnGestureListener的功能,因此该类尚未编译,让我们现在去处理吧。

检测用户手势

OnGestureListener接口要求我们实现六个功能:

onScroll,onTouchEvent,onDown,onSingleTapUp,onFling,onLongPress,onShowPress。其中,我们需要在onDown和onTouchEvent上使用(返回true),并在onScroll中实现移动登录。

这是onScroll的实现。我们将在以下段落中填写缺失的部分。

onScroll接收两个坐标集e1和e2,分别表示触发事件的滚动的开始和结束运动。我们只对e2(旋钮的新位置)感兴趣,因此我们可以对其进行动画处理以定位并计算值。我使用的功能将在下一部分中进行回顾,以计算旋转角度。如前所述,我们仅使用从旋钮的起点到终点的300度,因此在这里,我们还使用分频器计算旋钮的位置应代表什么值。

计算旋转角度

现在,让我们编写calculateAngle函数。

该功能需要一些解释和一些初一年级数学。(噢~还好我数学考试通常都是及格的不然还真不会,建议数学不好的朋友重新回去复习一下初一年级的数学)

此功能的目的是根据传递的坐标以角度计算旋钮的位置。我选择将旋钮的12点钟位置视为零,然后在顺时针旋转时将其位置增加到正数,在从12点逆时针旋转时减少到负数。

我们从onScroll函数获取x,y坐标,指示视图在该运动中结束的位置(针对该事件)。x和y代表笛卡尔坐标系上的一个点。我们可以将该点表示转换为极坐标系,以x轴上方或下方的角度以及该点与极点的距离来表示该点。

可以使用atan2函数在两个坐标系之间进行转换。对我们来说幸运的是,与大多数数学库一样,Kotlin数学库为我们提供了atan2的实现。但是,我们确实需要考虑旋钮模型和简单的数学实现之间的一些差异。(0,0)坐标表示视图的右上角,而不是中间。并且,当x坐标沿正确的方向前进时(随着向右移动而增长),y坐标向后移动。0是视图的顶部,而视图的高度值是该视图中的最低像素线。

为了适应这种情况,我们将x和y分别除以视图的宽度和高度,以使其归一化为0–1。然后我们从两者中减去0.5,将0,0点移到中间。最后,我们从1中减去y的值以反转其方向。

极坐标系与我们所需的方向相反。随着我们逆时针旋转,度数值会增加。因此,我们添加了一个负号来反转atan2函数的结果。我们希望0度的值指向北,否则经过9点,该值将从0跳到359。

因此我们将结果加90,注意,一旦角度大于180,将值减小360。因此我们得到-180

最后但并非最不重要的一点,我们为使用中的Activity或Fragment提供一个接口,以监听旋转事件:

使用旋钮

现在,让我们创建一个简单的实现来测试我们的旋钮。在主要活动中,我们创建一个TextView并将一个视图从容器列表中拖出。显示视图选择后,选择RotaryKnobView。

编辑活动的布局xml文件,并设置最小值,最大值和初始值以及要使用的可绘制对象。

最后,在我们的MainActivity类中,为布局充气并实现RotaryKnobListener接口以更新TextField的值。

到这里已经完成了,为儿子创建一个应用我把初一的数学拿出来了,钢琴考试再不过我绝对会好好“疼爱”你的。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200529A0851L00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券