Android自定义view实现滑动解锁效果
- 作者: 我读书少你别忽悠我呀
- 来源: 51数据库
- 2021-06-28
本文实例为大家分享了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中Bitmap用法(显示,保存,缩放,旋转)实例分析
12
android 仿微信聊天气泡效果实现思路
1
Android的尺度,drawable-xxxxxxx
2
Codeforces Round #656 (Div. 3) (C、D题)
1
Android之handler异步消息处理机制解析
6
GridView中图片显示出现上下间距过大,左右图片显示类似瀑布流的问题
0
AsyncTask的简单使用
5
两个简单Fragment之间的通信(三种方式)
18
uboot修改设置boot参数命令
41
android中实现从相册中一次性获取多张图片与拍照,并将选中的图片显示出来
2
