导航栏左右拖动切换

背景

交互设计了一个导航栏左右交换的功能,左右各设置一个不同的功能区,然后左右可以切换

方案设计

  1. 使用startDragAndDrop方法,进行移动
  2. 通过修改ConstraintLayout.LayoutParams变更位置

实现

布局代码

左侧代码

java 复制代码
            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/cl_left"
                android:layout_width="1360dp"
                android:layout_height="match_parent"
                android:background="@color/transparent"
                android:focusable="false"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintTop_toTopOf="parent">
          </androidx.constraintlayout.widget.ConstraintLayout>

右侧代码

java 复制代码
            <androidx.constraintlayout.widget.ConstraintLayout
                android:id="@+id/cl_right"
                android:layout_width="1360dp"
                android:layout_height="match_parent"
                android:background="@color/transparent"
                android:focusable="false"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toTopOf="parent">
                   </androidx.constraintlayout.widget.ConstraintLayout>

移动代码

左侧设置长按点击效果,设计移动效果

kotlin 复制代码
        binding.clLeft.setOnLongClickListener {

            val data = ClipData.newPlainText("clLeft", "clLeft move item")
            val shadowBuilder = View.DragShadowBuilder(binding.clLeft)
					//这里可以携带参数,也可以修改移动的效果
            val dragState = Bundle().apply {
                putBoolean("allow_return", false)
                putInt("original_visibility", binding.clLeft.visibility)
            }
            binding.clLeft.startDragAndDrop(data, shadowBuilder, dragState, 0)



            binding.clLeft.visibility = View.INVISIBLE


            return@setOnLongClickListener false
        }

右侧设置长按点击效果,设计移动效果

kotlin 复制代码
        binding.clRight.setOnLongClickListener {
            val data = ClipData.newPlainText("clRight", "clRight move item")
            val shadowBuilder = View.DragShadowBuilder(binding.clRight)

            val dragState = Bundle().apply {
                putBoolean("allow_return", false)
                putInt("original_visibility", binding.clRight.visibility)
            }
            binding.clRight.startDragAndDrop(data, shadowBuilder, dragState, 0)

            binding.clRight.visibility = View.INVISIBLE
            return@setOnLongClickListener true
        }

设置全局移动监听

kotlin 复制代码
    private val dragListener = View.OnDragListener { _, event ->
        Log.d(TAG, "dragListener:   x = ${event.x}   y = ${event.y} ")
        when (event.action) {
            DragEvent.ACTION_DROP -> {
                // 获取拖动的View
                val draggedView = event.localState as? View

                draggedView?.let { view ->
                    // 在新位置显示(不返回原位置)
                    view.visibility = View.INVISIBLE

                }

							//完成切换
                moveChangeSide()
                true
            }

            DragEvent.ACTION_DRAG_ENDED -> {

                binding.clLeft.visibility = View.VISIBLE
                binding.clRight.visibility = View.VISIBLE

                true
            }

            else -> true
        }
    }


    binding.root.setOnDragListener(dragListener)

完成移动的代码

kotlin 复制代码
    fun setLefBar(isLeft: Boolean) {


        val params = binding.clLeft.layoutParams as ConstraintLayout.LayoutParams
        if (isLeft) {
            params.startToStart = ConstraintLayout.LayoutParams.PARENT_ID
            params.endToEnd = ConstraintLayout.LayoutParams.UNSET
        } else {
            params.startToStart = ConstraintLayout.LayoutParams.UNSET
            params.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID
        }


        binding.clLeft.layoutParams = params
        binding.clLeft.requestLayout()

        binding.clLeft.visibility = View.VISIBLE
    }

遇到的问题

设置参数的时候,网上很多资料都是指向使用ConstraintSet来更新参数,但是这个方法不生效。所以这里记录一下

kotlin 复制代码
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout = binding.clleft) // parentLayeout是ConstraintLayout的实例
constraintSet.connect( startlD = binding.clleft.id,
startSide = ConstraintSet.END, endlD = ConstraintSet.PARENTT_ID, endSide = ConstraintSet.END, margin = 0
constraintSet.connect( startID= binding.clleft.id, startSide = ConstraintSt.START, endlD = -1, endSide = ConstraintSet.START, margin =
constraintSet.constrainWidth( viewld = binding.clleft.id, vvidth=1360)//设置宽高
constraintSet.constrainHeight( viewld = binding.clleft.id,height = Constraintset.MATCH_CONSTRAINT)
constraintSet.applyTo( constraintLayout = bindiing.clleft)

总结

  1. 使用startDragAndDrop方法,进行移动
  2. 通过修改ConstraintLayout.LayoutParams变更位置
相关推荐
脚踏实地,坚持不懈!10 分钟前
Android 系统工程师(性能/功耗/稳定性)岗位问题深度解析:从内核源码到实战排查(完善版)
android·linux·运维·服务器
Kapaseker15 分钟前
适配小米“中”折屏,非得买一台吗
android·kotlin
恋猫de小郭20 分钟前
Flutter 状态管理基准测评,一个很有趣的观点
android·前端·flutter
可乐鸡翅yeah_22 分钟前
App WebView 加载 M3U8 流媒体踩坑,安卓 iOS 混合开发播放异常定位
android·ios·harmonyos·m3u8·m3u8在线播放
木卫四科技1 小时前
从函数劫持到智能体控制平面:Hook 如何从 Linux-Android 演化到 Agent Runtime
android·linux·人工智能·安全
菠萝加点糖1 小时前
Android applicationIdSuffix 详解
android·gitee·kotlin
AIGC小尼1 小时前
穿山甲 + 腾讯短剧短视频聚合广告平台|Android+SpringBoot+Vue+Docker 完整部署指南
android·vue.js·spring boot·聚合广告·广告平台·穿山甲广告·腾讯广告
JMchen1233 小时前
【Android 性能优化实战 60 讲】06 GPU 呈现模式与卡顿视觉验证:拆解柱状图分层,秒辨渲染慢与等待慢
android·性能优化·实战·源码分析·渲染优化·gpu呈现模式·卡顿优化
91刘仁德10 小时前
MYSQL 事务原理及使用
android·mysql·adb
一笑的小酒馆12 小时前
AndroidKMP之瀑布流实现
android