背景
交互设计了一个导航栏左右交换的功能,左右各设置一个不同的功能区,然后左右可以切换
方案设计
- 使用startDragAndDrop方法,进行移动
- 通过修改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)
总结
- 使用startDragAndDrop方法,进行移动
- 通过修改ConstraintLayout.LayoutParams变更位置