首页 > 解决方案 > 像在 RecyclerView 中一样为 LinearLayout 拖动选择

问题描述

我想在 LinearLayout 中实现 DragSelect 功能。对于 RecyclerView 它已经存在,例如:here

LinearLayout它变得更加复杂。因为 onTouch 事件。用例将用于日期选择。这是具有此的自定义类视图组XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/containerSelectDays"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tvCurrentDaysOverall"
        style="@style/TextAppearance.SemiBold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:text="@string/repeat"
        android:textSize="@dimen/subtitle" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/layoutList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="16dp">

        <views.custom.SelectDayItemView
            android:id="@+id/day1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:layout_marginBottom="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/day2"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <primoz.com.alarmcontinue.views.custom.SelectDayItemView
            android:id="@+id/day2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/day1"
            app:layout_constraintEnd_toStartOf="@+id/day3"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/day1"
            app:layout_constraintTop_toTopOf="@+id/day1" />

        <views.custom.SelectDayItemView
            android:id="@+id/day3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/day1"
            app:layout_constraintEnd_toStartOf="@+id/day4"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/day2"
            app:layout_constraintTop_toTopOf="@+id/day1"
            tools:layout_editor_absoluteY="0dp" />

        <views.custom.SelectDayItemView
            android:id="@+id/day4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/day1"
            app:layout_constraintEnd_toStartOf="@+id/day5"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/day3"
            app:layout_constraintTop_toTopOf="@+id/day1"
            tools:layout_editor_absoluteY="0dp" />

        <views.custom.SelectDayItemView
            android:id="@+id/day5"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/day1"
            app:layout_constraintEnd_toStartOf="@+id/day6"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/day4"
            app:layout_constraintTop_toTopOf="@+id/day1"
            tools:layout_editor_absoluteY="0dp" />

        <views.custom.SelectDayItemView
            android:id="@+id/day6"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/day1"
            app:layout_constraintEnd_toStartOf="@+id/day7"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/day5"
            app:layout_constraintTop_toTopOf="@+id/day1"
            tools:layout_editor_absoluteY="0dp" />

        <views.custom.SelectDayItemView
            android:id="@+id/day7"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/day1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toEndOf="@+id/day6"
            app:layout_constraintTop_toTopOf="@+id/day1"
            tools:layout_editor_absoluteY="0dp" />


    </androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>

我在自定义类中尝试了:

override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
    val x = ev.x.roundToInt()
    val y = ev.y.roundToInt()
    handleTouch(x, y, ev, day1)
    handleTouch(x, y, ev, day2)
    handleTouch(x, y, ev, day3)
    handleTouch(x, y, ev, day4)
    handleTouch(x, y, ev, day5)
    handleTouch(x, y, ev, day6)
    handleTouch(x, y, ev, day7)
    return true
}

private fun handleTouch(
    x: Int,
    y: Int,
    ev: MotionEvent,
    day: SelectDayItemView
) {
    Log.d("Touched: $x,$y","touch")
    if (x > day.left && x < day.right && y > day.top && y < day.bottom) {
        if (ev.action == MotionEvent.ACTION_MOVE) {
            day.changeCheckedState()
        }
    }
}

但没有成功。它有时会认识到这一天被触及,有时它不会,所以它不是很可靠。我试图在孩子们内部放置触摸事件,但它只识别第一个并且不会触发其他事件。所以TouchListener需要在ViewGroup.

标签: androidandroid-selectorandroid-viewgroupandroid-touch-event

解决方案


推荐阅读