Android自定义view实现滑动解锁效果

本文实例为大家分享了Android自定义view实现滑动解锁的具体代码,供大家参考,具体内容如下

1. 需求如下:

近期需要做一个类似屏幕滑动解锁的功能,右划开始,左划暂停。

2. 需求效果图如下

3. 实现效果展示

4. 自定义view如下

/**

* Desc 自定义滑动解锁View

* Author ZY

* Mail sunnyfor98@gmail.com

* Date 2021/5/17 11:52

*/

@SuppressLint("ClickableViewAccessibility")

class SlideSwitchButton : ViewGroup {

constructor(context: Context?) : this(context, null)

constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)

constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : this(

context,

attrs,

defStyleAttr, 0

)

constructor(

context: Context?,

attrs: AttributeSet?,

defStyleAttr: Int,

defStyleRes: Int

) : super(context, attrs, defStyleAttr, defStyleRes)

var duration = 300

var isOpen = false

var scrollView: ScrollView? = null

var onSwitchListener: ((isOpen: Boolean) -> Unit)? = null

private var itemHeight = 0

private var itemPadding = 0

private var parentWidth = 0

private val stopImgView: ImageView by lazy {

ImageView(context).apply {

setImageResource(R.drawable.f1_svg_btn_stop)

}

}

private val startImgView: ImageView by lazy {

ImageView(context).apply {

setImageResource(R.drawable.f1_svg_btn_start)

}

}

private val hintView: TextView by lazy {

TextView(context).apply {

setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.dp_14))

compoundDrawablePadding = resources.getDimension(R.dimen.dp_5).toInt()

setTextColor(Color.parseColor("#727b9f"))

}

}

init {

setBackgroundResource(R.drawable.f1_sel_bg_slide_btn)

addView(hintView)

updateHint()

addView(stopImgView)

addView(startImgView)

var x = 0

startImgView.setOnTouchListener { v, event ->

when (event.action) {

MotionEvent.ACTION_DOWN -> {

scrollView?.requestDisallowInterceptTouchEvent(true)

x = event.x.toInt()

}

MotionEvent.ACTION_UP -> {

if (startImgView.x < (parentWidth - startImgView.width) / 2) {

play(false)

} else {

play(true)

}

scrollView?.requestDisallowInterceptTouchEvent(false)

}

MotionEvent.ACTION_MOVE -> {

val lastX = event.x - x

if (startImgView.x + lastX > parentWidth - itemPadding - startImgView.width) {

return@setOnTouchListener true

}

if (startImgView.x + lastX < itemPadding) {

return@setOnTouchListener true

}

startImgView.x += lastX

}

}

return@setOnTouchListener true

}

}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec)

setMeasuredDimension(widthMeasureSpec, resources.getDimension(R.dimen.dp_90).toInt())

itemPadding = resources.getDimension(R.dimen.dp_5).toInt()

itemHeight = resources.getDimension(R.dimen.dp_80).toInt()

parentWidth = MeasureSpec.getSize(widthMeasureSpec)

}

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {

stopImgView.layout(

itemPadding,

itemPadding,

itemPadding + itemHeight,

itemPadding + itemHeight

)

startImgView.layout(

itemPadding,

itemPadding,

itemPadding + itemHeight,

itemPadding + itemHeight

)

val len =

hintView.paint.measureText(hintView.text.toString()) + resources.getDimension(R.dimen.dp_24)

val let = (r - len) / 2

hintView.layout(

let.toInt(),

resources.getDimension(R.dimen.dp_35).toInt(),

(let + len).toInt(),

resources.getDimension(R.dimen.dp_55).toInt()

)

}

/**

* flag tue为开始 false为停止

*/

private fun play(flag: Boolean) {

val mStart = startImgView.x

val mEnd = if (flag) {

parentWidth - itemPadding * 2 - startImgView.width.toFloat()

} else {

stopImgView.x - itemPadding

}

val animatorOBJ =

ObjectAnimator.ofFloat(startImgView, "translationX", mStart, mEnd)

animatorOBJ.duration = duration.toLong()

animatorOBJ.addListener(object : Animator.AnimatorListener {

override fun onAnimationRepeat(animation: Animator?) {

}

override fun onAnimationEnd(animation: Animator?) {

updateHint(flag)

if (flag != isOpen) {

isOpen = flag

onSwitchListener?.invoke(flag)

}

}

override fun onAnimationCancel(animation: Animator?) {

}

override fun onAnimationStart(animation: Animator?) {

}

})

animatorOBJ.start()

}

private fun updateHint(lock: Boolean = false) {

val icon = if (lock) {

hintView.text = "滑动停止"

ResourcesCompat.getDrawable(resources, R.drawable.f1_svg_left_arrow, null)

} else {

hintView.text = "滑动开始"

ResourcesCompat.getDrawable(resources, R.drawable.f1_svg_right_arrow, null)

}

icon?.setBounds(

0,

0,

resources.getDimension(R.dimen.dp_14).toInt(),

resources.getDimension(R.dimen.dp_12).toInt()

)

if (lock) {

hintView.setCompoundDrawables(icon, null, null, null)

} else {

hintView.setCompoundDrawables(null, null, icon, null)

}

}

fun stop() {

play(false)

}

fun start() {

play(true)

}

}

这里需要注意一点:页面过长时,ScrollView和SlideSwitchButton滑动事件会冲突,所以需要吧scrollView传进来

5. 调用方式如下

/**

* Desc 自定义滑动解锁View

* Author ZY

* Mail sunnyfor98@gmail.com

* Date 2021/5/28 17:48

*/

class SlideSwitchButtonActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.f1_act_main)

btn_start.scrollView = scrollView

btn_start.onSwitchListener = {

if (it) {

Toast.makeText(this,"开始操作",Toast.LENGTH_LONG).show()

btn_start.start()

} else {

Toast.makeText(this,"停止操作",Toast.LENGTH_LONG).show()

btn_start.stop()

}

}

}

}

之前封装了一版ZyFrame框架,集工具类、自定义组件、网络请求框架一体,感觉用起来有些厚重,接下来会抽时间做拆分,ZyFrame保留网络请求功能,ZyUI专做自定义组件,ZyTool专做工具类,大概就这样。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 Android自定义view实现滑动解锁效果 的全部内容, 来源链接: utcz.com/p/243614.html

回到顶部