Custom slide to unlock View
- The requirements are as follows:
In the near future, we need to make a function similar to sliding to unlock the screen. Swipe right to start and swipe left to pause.
- The demand effect diagram is as follows
- Realize the effect display
- The custom view is as follows
/**
-
Desc custom slide to unlock View
-
Author ZY
-
Mail [email protected]
-
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)
}
}
One thing to note here: when the page is too long, the ScrollView and SlideSwitchButton sliding events will conflict, so you need to pass the scrollView in
- The calling method is as follows
/**
-
Desc custom slide to unlock View
-
Author ZY
-
Mail [email protected]
-
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()
}
}
}
}
Previously, a version of the ZyFrame framework was packaged, which integrates tools, custom components, and network request framework. It feels a bit heavy to use. Next, I will take time to split it. ZyFrame retains the network request function, ZyUI specializes in custom components, and ZyTool Specializing in tools, that's about it.
Article source: The network copyright belongs to the original author
The above content is not for commercial purposes, if it involves intellectual property issues, please contact the editor, we will deal with it immediately