【问题标题】:How to implement onClick, onLongClick and onTouch to one View如何对一个View实现onClick、onLongClick和onTouch
【发布时间】:2020-06-28 15:10:00
【问题描述】:

我有一个实现onClick()onLongClick()onTouch() 的视图(它是RecyclerView 中的ViewHolder,但我认为它不会有任何区别)。我面临的问题是 longClick 永远不会被执行。我在其他问题中读到了它,但我不知道该怎么做,什么时候应该在onTouch() 中返回true \ false。这是我的代码;

实现View.OnTouchListener的ViewHolder类中的函数bind()

binding.background.setOnClickListener {
    Log.d("Click")
}

binding.background.setOnLongClickListener {
    Log.d("Long Click")
}

binding.background.setOnTouchListener(this) // here I see warning "Custom view `ConstraintLayout` has setOnTouchListener called on it but does not override performClick"

覆盖 onTouch()

override fun onTouch(v: View?, event: MotionEvent?): Boolean
{
    return when (event!!.action)
    {
        MotionEvent.ACTION_DOWN ->
        {
            x1 = event.x
            true
        }
            MotionEvent.ACTION_UP ->
        {
            x2 = event.x
            return if (abs(x2 - x1) > MIN_DISTANCE)
            {
                Log.d("Was swiped")
                true
            }
            else
            {
                Log.d("Wasn't swiped")
                v?.performClick()
                false
            }
        }
        else -> false
    }
}

这个函数只检测视图上的滑动。我应该在onTouch() 中更改什么以使longClick 工作?另外,有没有更简单的方法来检测 RecyclerView 项目上的滑动?

【问题讨论】:

  • 如果你覆盖触摸,我认为这会拦截相同的事件,否则会去点击或长按。 ??????
  • @EpicPandaForce 我想是的,但有什么办法可以让longClickonTouch 在同一个视图上?

标签: android kotlin onclicklistener ontouchlistener onlongclicklistener


【解决方案1】:

尝试从下面的 onTouchEvent 视图中使用 GestureDetector

final GestureDetector longPressGestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
        Log.d(TAG, "onLongPress -> long press detected");
    }
});
public boolean onTouchEvent(MotionEvent event) {
    return longPressGestureDetector.onTouchEvent(event); //Will handle gesture API calls. The Gesture Detector can be used for Swipe actions as well.
};

【讨论】:

    【解决方案2】:

    如果有人遇到这样的问题,我会这样解决:
    (它是可左右移动或滚动的回收站视图项目)

    ViewHolder 字段:

    private var xStart = 0F
    private var lastY = 0F
    private var yStart = 0F
    private val handler: Handler = Handler()
    private var isLongClickCanceled = false
    private var wasLongClicked = false
    private var startScrolling = false
    private var status = 0
    ...
    private const val LONG_CLICK_TIME = 700L
    private const val CLICK_DISTANCE = 75
    private const val PANEL_SIZE = 125
    
    

    触控功能

    override fun onTouch(v: View?, event: MotionEvent?): Boolean
    {
        if (v != null && event != null)
        {
            v.parent.requestDisallowInterceptTouchEvent(true)
            when (event.action)
            {
                MotionEvent.ACTION_DOWN ->
                {
                    Log.d("Down")
                    xStart = event.x
                    yStart = event.y
                    isLongClickCanceled = false
                    wasLongClicked = false
                    startScrolling = false
                    handler.postDelayed({ //long click
                        wasLongClicked = true
                        val leftPanel = (v as ViewGroup).getChildAt(0)
                        val rightPanel = v.getChildAt(1)
                        val paramsLP = leftPanel.layoutParams
                        val paramsRP = rightPanel.layoutParams
                        paramsLP.width = 1
                        paramsRP.width = 1
                        leftPanel.layoutParams = paramsLP
                        rightPanel.layoutParams = paramsRP
                        v.performLongClick()
                    }, LONG_CLICK_TIME)
                    xStart = event.x
                }
                MotionEvent.ACTION_UP ->
                {
                    Log.d("Up")
                    handler.removeCallbacksAndMessages(null)
                    if (!startScrolling && !isLongClickCanceled && !wasLongClicked)
                    {
                        if ((event.eventTime - event.downTime) < LONG_CLICK_TIME) //click
                        {
                            Log.d("Status $status")
                            if (status == 0)
                            {
                                v.performClick()
                            }
                            else
                            {
                                val leftPanel = (v as ViewGroup).getChildAt(0)
                                val rightPanel = v.getChildAt(1)
                                val paramsLP = leftPanel.layoutParams
                                val paramsRP = rightPanel.layoutParams
                                paramsLP.width = 1
                                paramsRP.width = 1
                                leftPanel.layoutParams = paramsLP
                                rightPanel.layoutParams = paramsRP
                                status = 0
                                selectCar(binding.car!!.carID, false)
                            }
                        }
                    }
                    else
                    {
                        val leftPanel = (v as ViewGroup).getChildAt(0)
                        val rightPanel = v.getChildAt(1)
                        val paramsLP = leftPanel.layoutParams
                        val paramsRP = rightPanel.layoutParams
                        when
                        {
                            status > (PANEL_SIZE / 2) ->
                            {
                                paramsLP.width = PANEL_SIZE
                                paramsRP.width = 1
                                selectCar(binding.car!!.carID, false)
                            }
                            status < -(PANEL_SIZE / 2) ->
                            {
                                paramsRP.width = PANEL_SIZE
                                paramsLP.width = 1
                                selectCar(binding.car!!.carID, true)
                            }
                            else ->
                            {
                                paramsLP.width = 1
                                paramsRP.width = 1
                                status = 0
                                selectCar(binding.car!!.carID, false)
                            }
                        }
                        leftPanel.layoutParams = paramsLP
                        rightPanel.layoutParams = paramsRP
                    }
                }
                MotionEvent.ACTION_MOVE ->
                {
                    if (startScrolling)
                    {
                        scroll((lastY - event.rawY).toInt())
                        lastY = event.rawY
                    }
                    else
                    {
                        if (!wasLongClicked)
                        {
                            if (isLongClickCanceled)
                            {
                                val deltaX = (event.x - xStart).toInt()
                                if (abs(deltaX) > 75)
                                {
                                    val leftPanel = (v as ViewGroup).getChildAt(0)
                                    val rightPanel = v.getChildAt(1)
                                    val paramsLP = leftPanel.layoutParams
                                    val paramsRP = rightPanel.layoutParams
                                    if (deltaX > 0)
                                    {
                                        status = (deltaX - CLICK_DISTANCE)
                                        paramsLP.width = min(status, PANEL_SIZE)
                                        paramsRP.width = 1
                                    }
                                    else if (deltaX < 0)
                                    {
                                        status = (deltaX + CLICK_DISTANCE)
                                        paramsRP.width = min(-status, PANEL_SIZE)
                                        paramsLP.width = 1
                                    }
                                    leftPanel.layoutParams = paramsLP
                                    rightPanel.layoutParams = paramsRP
                                }
                            }
                            else if (abs(yStart - event.y) > CLICK_DISTANCE)
                            {
                                lastY = event.rawY
                                startScrolling = true
                                handler.removeCallbacksAndMessages(null)
                            }
                            else if (!isLongClickCanceled && abs(xStart - event.x) >= CLICK_DISTANCE)
                            {
                                isLongClickCanceled = true
                                handler.removeCallbacksAndMessages(null)
                            }
                        }
                    }
                }
            }
        }
        return true
    }
    

    传递给 ViewHolder 的滚动函数

    { dy -> binding.recViewCar.scrollBy(0, dy) }
    

    此代码可以执行 Click、LongClick 和 Touching 视图。当用户进行 LongClick 时,不会执行移动操作。将手指放在屏幕上并将其移动超过CLICK_DISTANCE Click 和 LongClick 将不会执行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 2012-06-12
      相关资源
      最近更新 更多