效果

素材准备

先准备钩子的一系列帧图,放在drawable目录下。也可以是png格式,xml格式可以通过svg格式转换(右击drawable文件夹 - New - Vector Assert - Local file - Path选择)。
以及checkbox的背景,ic_checkbox.xml文件。
所有素材都在源码中
最后在res - values - colors.xml中添加透明:
<!-- 添加透明-->
<color name="transparent">#00FFFFFF</color>
动画文件
在drawable目录下新建anim_tick.xml文件,编写以下内容:
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 第一帧为透明-->
<item
android:drawable="@color/transparent"
android:maxLevel="0" />
<item
android:drawable="@drawable/ic_tick_0"
android:maxLevel="1" />
<item
android:drawable="@drawable/ic_tick_1"
android:maxLevel="2" />
<item
android:drawable="@drawable/ic_tick_2"
android:maxLevel="3" />
<item
android:drawable="@drawable/ic_tick_3"
android:maxLevel="4" />
<item
android:drawable="@drawable/ic_tick_4"
android:maxLevel="5" />
<item
android:drawable="@drawable/ic_tick_5"
android:maxLevel="6" />
<item
android:drawable="@drawable/ic_tick_6"
android:maxLevel="7" />
<item
android:drawable="@drawable/ic_tick_7"
android:maxLevel="8" />
<item
android:drawable="@drawable/ic_tick_8"
android:maxLevel="9" />
<item
android:drawable="@drawable/ic_tick_9"
android:maxLevel="10" />
<item
android:drawable="@drawable/ic_tick_10"
android:maxLevel="11" />
</level-list>
即把钩子的帧图添加进去,第一帧为透明,即checkbox没有被选中时的状态。
封装CustomCheckbox类
新建CustomCheckbox类,和ImageCheckbox类:
class CustomCheckbox(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
private lateinit var checkbox: ImageCheckbox
init {
// 加载布局
LayoutInflater.from(context).inflate(R.layout.custom_checkbox, this)
// 获取控件
checkbox = findViewById(R.id.checkbox1357945214)
// 注册默认点击事件
this.setOnClickListener {
isChecked = !isChecked
}
}
/**
* 只有一个isChecked属性
*/
var isChecked: Boolean = false
set(value) {
field = value
checkbox.setChecked(value)
}
/**
* 设置checkbox点击事件
* @param listener lambda表达式
*/
override fun setOnClickListener(listener: OnClickListener?) {
checkbox.setOnClickListener(listener)
}
}
/**
* 不要直接使用ImageCheckbox类,没有封装完整
* 实现动画效果必须继承ImageView,所以分开写
*/
@SuppressLint("AppCompatCustomView")
class ImageCheckbox(context: Context, attrs: AttributeSet) :
ImageView(context, attrs) {
fun setChecked(value: Boolean) {
// 选中时开始动画
if (value) {
// 从0到11帧
val headerAnimator = ObjectAnimator.ofInt(this, "imageLevel", 0, 11)
headerAnimator.interpolator = LinearInterpolator()
// 持续时长200ms
headerAnimator.duration = 200
headerAnimator.start()
} else {
// 取消选中时设置显示第一帧,即透明
super.setImageLevel(0);
}
}
init {
super.setImageResource(R.drawable.anim_tick)
setChecked(false)
}
}
布局文件
在layout文件夹中新建custom_checkbox.xml,编写:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<!-- 防止id冲突-->
<!-- 注意这里引入的是ImageCheckbox-->
<com.example.customcheckbox.ImageCheckbox
android:id="@+id/checkbox1357945214"
android:layout_width="29dp"
android:layout_height="29dp"
android:background="@drawable/ic_checkbox"
android:padding="3dp" />
</LinearLayout>
注意这里引入的是ImageCheckbox。
引入控件
在activity_main.xml中添加代码:
<!-- 引入自定义CustomCheckbox-->
<com.example.customcheckbox.CustomCheckbox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
这里引入的才是CustomCheckbox。
到这里就可以运行了。
相关资源
动画实现参考android 帧动画的替代方案。