簡體   English   中英

Android - 如何檢測屏幕上的觸摸是“滾動”觸摸?

[英]Android - how to detect a touch on screen is a "scroll" touch?

我正在用 Java 創建一個 android 應用程序,其中我在屏幕周圍有很多<TextView> ,所有這些都定義了 onTouchListeners 。 它們包含在<ScrollView>因為它們占用的空間比屏幕中可用的空間多。

我的問題是:當我向上/向下滾動應用程序時,通過觸摸屏幕並向上/向下移動手指,滾動按預期工作,但觸摸的<TextView>的 onTouchListener 也被觸發(這可能是預期的)好吧)-我不希望這種情況發生。 當我觸摸屏幕滾動它時,我希望 onTouchListener 被忽略。

我怎樣才能做到這一點? 我不希望我的函數在用戶滾動並“意外”觸發某個<TextView>上的 onTouchListener 時運行。

在搜索更多之后,我找到了 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;
    }

});

我和你有同樣的問題,我用ACTION_CANCEL解決了它。

當以前感知的動作(如您的情況下的ACTION_DOWN )現在被其他手勢(如滾動等)“取消”時, motionEvent.getActionMasked()等於ACTION_CANCEL 。您的代碼可能如下所示:

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.      
        }
    }

我希望這有幫助。

我遇到了類似的問題,但是使用一個 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) }
    }
}

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) })

您可以像這樣識別移動動作:

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

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

            }

            return false;
        }
    });

為我工作:

View.OnTouchListener() {

@Override

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

  return true
});

您不需要使用這種復雜的方法來捕獲“點擊”事件。 僅針對此方法:-

//當然是在觸摸監聽器里面:-

科特林:-

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

JAVA :- 只需將 event.action 替換為 event.getAction()

這對我有用😉

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM