Android - onDrag () не вызывается для представления, созданного во время выполнения - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть следующий код, который создает кнопку во время выполнения:

class MainActivity : AppCompatActivity(), View.OnTouchListener, GestureDetector.OnGestureListener, View.OnDragListener {

    private lateinit var binding : ActivityMainBinding
    private lateinit var gestureDetector: GestureDetector

    private lateinit var button: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        /** create the [Button] object*/
        button = Button(this)

        /** set some of its attributes */
        button.text = getString(R.string.hello)
        button.id = R.id.myButtonViewID

        /** set a [view.OnTouchListener] on it*/
        button.setOnTouchListener(this)

        /** add the [Button] object to the [ConstraintLayout] */
        binding.constraintLayout.addView(button)


        /** use [ConstraintSet] to specify how [Button] should be laid out */
        val set = ConstraintSet()
        set.constrainHeight(button.id, ConstraintSet.WRAP_CONTENT)
        set.constrainWidth(button.id, ConstraintSet.WRAP_CONTENT)

        set.connect(
            button.id,
            ConstraintSet.LEFT,
            ConstraintSet.PARENT_ID,
            ConstraintSet.LEFT, 0)

        set.connect(
            button.id,
            ConstraintSet.RIGHT,
            ConstraintSet.PARENT_ID,
            ConstraintSet.RIGHT, 0)

        set.connect(
            button.id,
            ConstraintSet.TOP,
            ConstraintSet.PARENT_ID,
            ConstraintSet.TOP, 0)

        set.connect(
            button.id,
            ConstraintSet.BOTTOM,
            ConstraintSet.PARENT_ID,
            ConstraintSet.BOTTOM, 0)

        /** apply the constraints */
        set.applyTo(binding.constraintLayout)

        /** create a [GestureDetector] object */
        gestureDetector = GestureDetector(this, this)

    }
    // rest of code which consists of the listeners you will see below
    // ...
}

Создание кнопки динамически, как это работает отлично. Теперь я хотел перетащить его динамически, реагируя на события касания пользователя. Поэтому я добавил onTouchListener к кнопке (button.setOnTouchListener(this)) и объект GestureDetector, который можно увидеть в конце метода onCreate().

Теперь для слушателей. Вот метод OnTouchListener onTouch():

/** [View.OnTouchListener] interface */
    override fun onTouch(view: View?, motionEvent: MotionEvent?): Boolean {
        gestureDetector.onTouchEvent(motionEvent)
        return true
    }

Что я делаю в onTouch(): я просто передаю motionEvent методу onTouchEvent() gestureDetector так что методы GestureDetector.OnGestureListener могут обрабатывать motionEvent.

Вот соответствующие методы интерфейса, которые я переопределил (я не буду добавлять все, только один, который использовал):

/** [GestureDetector.OnGestureListener] interface */
    ...
    ...

    override fun onDown(p0: MotionEvent?): Boolean {
        Log.d("GestureDetector", "onDown() is called.")
        return true
    }

    override fun onLongPress(p0: MotionEvent?) {
        Log.d("GestureDetector", "onLongPress() is called.")

        val builder : View.DragShadowBuilder = View.DragShadowBuilder(button)
        builder.view.setOnDragListener(this)
    }

В onLongPress() я просто строю объект View.DragShadowBuilder и устанавливаю View.OnDragListener на своей кнопке. Я поместил этот код здесь, потому что я хотел начать операцию перетаскивания, только когда пользователь делает «длинное нажатие».

Вот мой метод View.OnDragListener onDrag():

/** [View.OnDragListener] interface */
    override fun onDrag(view: View?, dragEvent: DragEvent?): Boolean {
        // just like in the onTouchListener we have a bunch of events for dragging
        Log.d("GestureDetector", "onDrag() is called.")
        when (dragEvent?.action) {
            DragEvent.ACTION_DRAG_STARTED -> {
                Log.d("GestureDetector", "onDrag: drag started.")
                return true
            }
            DragEvent.ACTION_DRAG_ENTERED -> {
                Log.d("GestureDetector", "onDrag: drag entered.")
                return true
            }
            DragEvent.ACTION_DRAG_LOCATION -> {
                Log.d(
                    "GestureDetector",
                    "onDrag: current point: ( " + dragEvent.x.toString() + " , " + dragEvent.y.toString() + " )"
                )
                return true
            }
            DragEvent.ACTION_DRAG_EXITED -> {
                Log.d("GestureDetector", "onDrag: exited.")
                return true
            }
            DragEvent.ACTION_DROP -> {
                Log.d("GestureDetector", "onDrag: dropped.")
                return true
            }
            DragEvent.ACTION_DRAG_ENDED -> {
                Log.d("GestureDetector", "onDrag: ended.")
                return true
            }
            else -> Log.e(
                "GestureDetector",
                "Unknown action type received by OnStartDragListener."
            )
        }
        return false
    }

Я мало что делаю в методе onDrag (). Просто печатать координаты во время движения к бревну. Но моя проблема в том, что onDrag () никогда не вызывается. В моем журнале я вижу только следующее:

D/GestureDetector: onDown() is called.
2020-04-02 15:28:27.444 22293-22293/com.celik.abdullah.learningTouchEvents D/GestureDetector: onShowPress() is called.
2020-04-02 15:28:27.945 22293-22293/com.celik.abdullah.learningTouchEvents D/GestureDetector: onLongPress() is called.

Итак, событие передается onLongPress(), как и ожидалось, но затем метод onDrag() не вызывается. Почему?

...