android开发之Android 自定义滑动解锁View
小职 2021-06-09 来源 :「左郁」 阅读 1687 评论 0

摘要:本篇主要介绍了android开发之Android 自定义滑动解锁View,通过具体的内容展现,希望对Android 开发的学习有所帮助。

本篇主要介绍了android开发之Android 自定义滑动解锁View,通过具体的内容展现,希望对Android 开发的学习有所帮助。

android开发之Android 自定义滑动解锁View

 自定义滑动解锁View

1. 需求如下:

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


2. 需求效果图如下

android开发之Android 自定义滑动解锁View


3. 实现效果展示

android开发之Android 自定义滑动解锁View


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开发之Android 自定义滑动解锁View

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程