[英]Android - how to detect a touch on screen is a "scroll" touch?
我正在用 Java 創建一個 android 應用程序,其中我在屏幕周圍有很多<TextView>
,所有這些都定義了 onTouchListeners 。 它們包含在<ScrollView>
因為它們占用的空間比屏幕中可用的空間多。
我的問題是:當我向上/向下滾動應用程序時,通過觸摸屏幕並向上/向下移動手指,滾動按預期工作,但觸摸的<TextView>
的 onTouchListener 也被觸發(這可能是預期的)好吧)-我不希望這種情況發生。 當我觸摸屏幕滾動它時,我希望 onTouchListener 被忽略。
我怎樣才能做到這一點? 我不希望我的函數在用戶滾動並“意外”觸發某個<TextView>
上的 onTouchListener 時運行。
在搜索更多之后,我找到了 Stimsoni 的這個解決方案。 這個想法是檢查ACTION_DOWN
和ACTION_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.