本篇文章讲的是Kotlin 自定义view之实现标尺控件Ruler,以选择身高、体重等。开发中,当我们需要获取用户的身高和体重等信息时,如果直接让他们输入,显然体验不够好。像类似于唯品会、好轻等APP都是使用了类似于刻度尺的控件让用户滑动选择身高体重,觉得很棒。网上已有人使用Java语言实现这样的功能,但不影响我对其的学习。和往常一样,主要还是想总结一下自定义view之实现标尺控件的开发过程以及一些需要注意的地方。
按照惯例,我们先来看看效果图
一、先总结下自定义View的步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
3、重写onMesure
4、重写onDraw
其中onMesure方法不一定要重写,但大部分情况下还是需要重写的
二、View 的几个构造函数
1、constructor(mContext: Context)
—>java代码直接new一个RulerView实例的时候,会调用这个只有一个参数的构造函数;
2、constructor(mContext: Context, attrs: AttributeSet)
—>在默认的XML布局文件中创建的时候调用这个有两个参数的构造函数。AttributeSet类型的参数负责把XML布局文件中所自定义的属性通过AttributeSet带入到View内;
3、constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int)
—>构造函数中第三个参数是默认的Style,这里的默认的Style是指它在当前Application或者Activity所用的Theme中的默认Style,且只有在明确调用的时候才会调用
4、constructor(mContext: Context, attrs: AttributeSet,defStyleAttr:Int,defStyleRes:Int)
—>该构造函数是在API21的时候才添加上的
三、下面我们就开始来看看代码啦
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的需要用到的属性以及声明相对应属性的取值类型
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_weight_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="体重"
android:textColor="@android:color/black"
android:textSize="14dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.132" />
<RelativeLayout
android:id="@+id/rl_weight_ruler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/tv_weight_tip"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<per.lijuan.rulerdome.RulerView
android:id="@+id/ruler_weight"
android:layout_width="match_parent"
android:layout_height="58dp"
android:layout_marginTop="24dp"
app:alphaEnable="true"
app:lineColor="@android:color/darker_gray"
app:lineMaxHeight="40dp"
app:lineMidHeight="30dp"
app:lineMinHeight="20dp"
app:lineSpaceWidth="10dp"
app:lineWidth="2.5dp"
app:textColor="@android:color/black"
app:minValue="20"
app:maxValue="200"
app:perValue="0.1"
app:selectorValue="55"/>
<ImageView
android:layout_width="14dp"
android:layout_height="46dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="6dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_arrow"/>
</RelativeLayout>
<TextView
android:id="@+id/tv_weight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="11dp"
android:maxHeight="30sp"
android:textColor="@color/colorPrimary"
android:textSize="24sp"
app:layout_constraintTop_toBottomOf="@+id/rl_weight_ruler"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</android.support.constraint.ConstraintLayout>
一定要引入xmlns:app=”http://schemas.android.com/apk/res-auto”,Android Studio中我们可以使用res-atuo命名空间,就不用在添加自定义View全类名。
3、在View的构造方法中,获得我们的自定义的样式
private var mMinVelocity:Int = 0
private var mScroller: Scroller? = null//Scroller是一个专门用于处理滚动效果的工具类 用mScroller记录/计算View滚动的位置,再重写View的computeScroll(),完成实际的滚动
private var mVelocityTracker: VelocityTracker?=null//主要用跟踪触摸屏事件(flinging事件和其他gestures手势事件)的速率。
private var mWidth:Int = 0
private var mHeight:Int = 0
private var mSelectorValue=50f // 未选择时 默认的值 滑动后表示当前中间指针正在指着的值
private var mMaxValue=200f // 最大数值
private var mMinValue=100f //最小的数值
private var mPerValue=1f //最小单位(如 1:表示每2条刻度差为1;0.1:表示每2条刻度差为