6

我正在用 Java 创建一个 android 应用程序,其中我<TextView>在屏幕上有很多,所有这些都定义了 onTouchListeners。它们被包裹在 a 中,<ScrollView>因为它们占用的空间比屏幕中可用的空间多。

我的问题是:当我通过触摸屏幕并向上/向下移动手指来向上/向下滚动应用程序时,滚动按预期工作,但触摸的 onTouchListener<TextView>也会被触发(这可能也是预期的) -我不希望这种情况发生。当我触摸屏幕滚动它时,我希望忽略 onTouchListener。

我怎样才能做到这一点?我不希望我的函数在用户滚动并且“意外”在某个 .onTouchListener 上触发时运行<TextView>

4

7 回答 7

20

经过更多搜索,我找到了 Stimsoni 的这个解决方案。这个想法是检查ACTION_DOWNACTION_UP事件之间的时间是否低于或高于 给出的值ViewConfiguration.getTapTimeout()

从文档中:

[返回] 我们将等待查看触摸事件是点击还是滚动的持续时间(以毫秒为单位)。如果用户在此间隔内没有移动,则认为是轻击。

代码:

view.setOnTouchListener(new OnTouchListener() {

    private long startClickTime;

    @Override
    public boolean onTouch(View view, MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {

            startClickTime = System.currentTimeMillis();

        } else if (event.getAction() == MotionEvent.ACTION_UP) {

            if (System.currentTimeMillis() - startClickTime < ViewConfiguration.getTapTimeout()) {

                // Touch was a simple tap. Do whatever.

            } else {

                // Touch was a not a simple tap.

            }

        }

        return true;
    }

});
于 2016-02-11T03:01:14.417 回答
2

我和你有同样的问题,我用ACTION_CANCEL.

motionEvent.getActionMasked()等于ACTION_CANCEL以前感知的动作(如ACTION_DOWN您的情况)现在被其他手势(如滚动等)“取消”时。您的代码可能是这样的:

view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View view, MotionEvent e) {
        if (e.getActionMasked() == MotionEvent.ACTION_DOWN) {
            // perceive a touch action.
        } else if(e.getActionMasked() == MotionEvent.ACTION_UP ||
                e.getActionMasked() == MotionEvent.ACTION_CANCEL) {
            // ignore the perceived action.      
        }
    }

我希望这有帮助。

于 2016-11-19T20:35:34.410 回答
1

我遇到了类似的问题,但是使用一个 TextView,搜索将我带到了这里。文本内容可能会占用比屏幕上可用的空间更多的空间。简单的工作示例:bpmcounter-android (Kotlin)

class MainActivity : AppCompatActivity() {

    inner class GestureTap : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapUp(e: MotionEvent?): Boolean {
            // Do your buttonClick stuff here. Any scrolling action will be ignored
            return true
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val textView = findViewById<TextView>(R.id.textView)
        textView.movementMethod = ScrollingMovementMethod()
        val gestureDetector = GestureDetector(this, GestureTap())
        textView.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) }
    }
}
于 2019-10-19T13:02:53.873 回答
1

1 方法:

我发现最好的方法是检测第一次触摸保存点 x 和 y,然后用第二次触摸来面对它。如果第一次点击和第二次点击之间的距离很近(我把 10% 作为一个近似值),那么触摸一个简单的点击,否则就是一个滚动运动。

 /**
 * determine whether two numbers are "approximately equal" by seeing if they
 * are within a certain "tolerance percentage," with `tolerancePercentage` given
 * as a percentage (such as 10.0 meaning "10%").
 *
 * @param tolerancePercentage 1 = 1%, 2.5 = 2.5%, etc.
 */
fun approximatelyEqual(desiredValue: Float, actualValue: Float, tolerancePercentage: Float): Boolean {
    val diff = Math.abs(desiredValue - actualValue) //  1000 - 950  = 50
    val tolerance = tolerancePercentage / 100 * desiredValue //  20/100*1000 = 200
    return diff < tolerance //  50<200      = true
}

var xPoint = 0f
var yPoint = 0f
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
    when(event.action) {

        MotionEvent.ACTION_DOWN -> {
            xPoint = event.x
            yPoint = event.y
            return true
        }

        MotionEvent.ACTION_UP -> {
            if (!approximatelyEqual(xPoint, event.x, 10f) || !approximatelyEqual(yPoint, event.y, 10f)) {
                //scrolling
            } else {
                //simple click
            }
        }
    }
    return false
}

2 方法:

做同样事情的另一种方法是使用 GestureDetector 类:

   interface GestureInterface {
    fun setOnScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float)
    fun onClick(e: MotionEvent)
}

class MyGestureDetector(val gestureInterfacePar: GestureInterface) : SimpleOnGestureListener() {

    override fun onSingleTapUp(e: MotionEvent): Boolean { 
        gestureInterfacePar.onClick(e)
        return false
    }

    override fun onLongPress(e: MotionEvent) {}
    override fun onDoubleTap(e: MotionEvent): Boolean {
        return false
    }

    override fun onDoubleTapEvent(e: MotionEvent): Boolean {
        return false
    }

    override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
        return false
    }

    override fun onShowPress(e: MotionEvent) {
    }

    override fun onDown(e: MotionEvent): Boolean { 
        return true
    }

    override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
        gestureInterfacePar.setOnScroll(e1, e2, distanceX, distanceY)
        return false
    }

    override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { 
        return super.onFling(e1, e2, velocityX, velocityY)
    }
}

最后,将它与您的视图绑定:

val mGestureDetector = GestureDetector(context, MyGestureDetector(object : GestureInterface {
                override fun setOnScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float) {
                    //handle the scroll
                }

                override fun onClick(e: MotionEvent) {
                    //handle the single click
                }

            }))


            view.setOnTouchListener(OnTouchListener { v, event -> mGestureDetector.onTouchEvent(event) })
于 2020-01-08T11:09:10.150 回答
0

您可以像这样识别移动动作:

view.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            if(event.getAction() == MotionEvent.ACTION_MOVE)
            {

            }

            return false;
        }
    });
于 2016-02-09T13:31:36.900 回答
0

为我工作:

View.OnTouchListener() {

@Override

public boolean onTouch(View v,MotionEvent event)
{
        if(event.getAction()!=MotionEvent.ACTION_DOWN)
        {
                     // Before touch
        }
        else {
                      // When touched
             }

  return true
});
于 2020-04-10T19:12:42.413 回答
0

您不需要采用这种复杂的方法来捕获“点击”事件。仅针对此方法:-

//当然是在触摸监听器内部:-

科特林:-

if(event.action == MotionEvent.ACTION_UP && event.action != MotionEvent.ACTION_MOVE) {
// Click has been made...
// Some code
}

JAVA :- 只需将 event.action 替换为 event.getAction()

这对我有用

于 2021-08-18T09:45:06.410 回答