У меня есть следующий код, который создает кнопку во время выполнения:
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()
не вызывается. Почему?