当前位置: 首页 > news >正文

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

自定义滑动解锁View

  1. 需求如下:

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

  1. 需求效果图如下
    IMG_256
  2. 实现效果展示
    IMG_257
  3. 自定义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 = 300var isOpen = falsevar scrollView: ScrollView? = nullvar onSwitchListener: ((isOpen: Boolean) -> Unit)? = nullprivate var itemHeight = 0private var itemPadding = 0private var parentWidth = 0private 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 = 0startImgView.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 - xif (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) / 2hintView.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.xval 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 = flagonSwitchListener?.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传进来

  1. 调用方式如下

/**

  • 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 = scrollViewbtn_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专做工具类,大概就这样。

文章来源:网络 版权归原作者所有

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系小编,我们将立即处理

http://www.lryc.cn/news/116530.html

相关文章:

  • CAD绘制法兰、添加光源、材质并渲染
  • ChatGPT访问流量下降的原因分析
  • 干货 | 详述 Elasticsearch 向量检索发展史
  • mysql常见面试题,高频题目放送
  • 使用 PowerShell 将 Excel 中的每个工作表单独另存为独立的文件
  • python提取pdf图片
  • Vue3 表单输入绑定简单应用
  • 如何解决 Elasticsearch 查询缓慢的问题以获得更好的用户体验
  • 近期学习练习
  • 平台安全之中间件安全
  • 芒果 TV 基于 Flink 的实时数仓建设实践
  • 尚硅谷大数据项目《在线教育之采集系统》笔记004
  • R语言4_安装BayesSpace
  • TSINGSEE青犀视频安防监控视频平台EasyCVR设备在线,视频无法播放的原因排查
  • 【算法篇C++实现】算法的时间、空间复杂度
  • On Evaluation of Embodied Navigation Agents 论文阅读
  • 【CSS 布局】水平垂直方向居中
  • Java实现轻量型Web服务器接收http协议提交的RFID读卡信息
  • 模拟实现消息队列项目(完结) -- 基于MQ的生产者消费者模型
  • 专业商城财务一体化-线上商城+进销存管理软件,批发零售全行业免费更新
  • 深度思考mysql面经
  • 2023-08-09力扣每日一题
  • [23] Instruct 3D-to-3D: Text Instruction Guided 3D-to-3D conversion
  • 设计模式行为型——访问者模式
  • vue3官网文档学习、复习笔记(快速上手)
  • 0基础学习VR全景平台篇 第81篇:全景相机-临云镜如何直播推流
  • 分数线划定
  • 考研C语言进阶题库——更新26-30题
  • 用C语言实现定积分计算(包括无穷积分/可自定义精度)
  • 使用Presto、Trino数据库时提示“The datetime zone id ‘GMT+08:00‘ is not recognised”