Я хочу, щоб моя програма розпізнавала, коли користувач провела пальцем справа наліво на екрані телефону.
Як це зробити?
Я хочу, щоб моя програма розпізнавала, коли користувач провела пальцем справа наліво на екрані телефону.
Як це зробити?
Відповіді:
OnSwipeTouchListener.java :
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener (Context ctx){
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
result = true;
}
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}
Використання:
imageView.setOnTouchListener(new OnSwipeTouchListener(MyActivity.this) {
public void onSwipeTop() {
Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
}
});
OnSwipeTouchListener
цього, який отримує контекст, оскільки цей конструктор GestureDetector
застарілий з рівня API 3, і інстанціювати його GestureDetector
в цьому конструкторі.
onTouch
до OnSwipeTouchListener
визначення, інакше мій IDE з'явиться помилка "доступ до приватного члена"
Цей код виявляє пальці ліворуч і праворуч, уникає застарілих викликів API та має інші різні вдосконалення щодо попередніх відповідей.
/**
* Detects left and right swipes across a view.
*/
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context context) {
gestureDetector = new GestureDetector(context, new GestureListener());
}
public void onSwipeLeft() {
}
public void onSwipeRight() {
}
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_DISTANCE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeRight();
else
onSwipeLeft();
return true;
}
return false;
}
}
}
Використовуйте його так:
view.setOnTouchListener(new OnSwipeTouchListener(context) {
@Override
public void onSwipeLeft() {
// Whatever
}
});
setOnTouchListener
(як правило onCreate
). context
- це this
покажчик (якщо ви не створюєте фрагмент).
Fragment.getActivity()
.
Якщо вам також потрібно обробити події клацання, тут можна внести деякі зміни
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());
public boolean onTouch(final View v, final MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
result = onSwipeRight();
} else {
result = onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
result = onSwipeBottom();
} else {
result = onSwipeTop();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public boolean onSwipeRight() {
return false;
}
public boolean onSwipeLeft() {
return false;
}
public boolean onSwipeTop() {
return false;
}
public boolean onSwipeBottom() {
return false;
}
}
І використання вибірки:
background.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
toggleSomething();
}
});
background.setOnTouchListener(new OnSwipeTouchListener() {
public boolean onSwipeTop() {
Toast.makeText(MainActivity.this, "top", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeRight() {
Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeLeft() {
Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeBottom() {
Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT).show();
return true;
}
});
Розширюючи відповідь Мірека, на випадок, коли ви хочете використовувати пальці жестами всередині подання прокрутки. За замовчуванням сенсорний слухач для перегляду прокрутки відключається, тому дія прокрутки не відбувається. Щоб виправити це, вам потрібно змінити dispatchTouchEvent
метод Activity
і повернути успадковану версію цього методу після того, як ви закінчите з власним слухачем.
Для того , щоб зробити кілька змін в код Мірек в: додати геттер для gestureDetector
в OnSwipeTouchListener
.
public GestureDetector getGestureDetector(){
return gestureDetector;
}
Оголосіть OnSwipeTouchListener
внутрішню діяльність як поле загального класу.
OnSwipeTouchListener onSwipeTouchListener;
Змініть код використання відповідно:
onSwipeTouchListener = new OnSwipeTouchListener(MyActivity.this) {
public void onSwipeTop() {
Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
}
});
imageView.setOnTouchListener(onSwipeTouchListener);
І замініть dispatchTouchEvent
метод всередині Activity
:
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
swipeListener.getGestureDetector().onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
Тепер дії прокрутки та пальця повинні працювати.
Для того , щоб мати Click Listener
, DoubleClick Listener
,OnLongPress Listener
, Swipe Left
, Swipe Right
, Swipe Up
, Swipe Down
Одно- View
вам потрібно setOnTouchListener
. тобто
view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
@Override
public void onClick() {
super.onClick();
// your on click here
}
@Override
public void onDoubleClick() {
super.onDoubleClick();
// your on onDoubleClick here
}
@Override
public void onLongClick() {
super.onLongClick();
// your on onLongClick here
}
@Override
public void onSwipeUp() {
super.onSwipeUp();
// your swipe up here
}
@Override
public void onSwipeDown() {
super.onSwipeDown();
// your swipe down here.
}
@Override
public void onSwipeLeft() {
super.onSwipeLeft();
// your swipe left here.
}
@Override
public void onSwipeRight() {
super.onSwipeRight();
// your swipe right here.
}
});
}
Для цього вам потрібно OnSwipeTouchListener
клас, який реалізує OnTouchListener
.
public class OnSwipeTouchListener implements View.OnTouchListener {
private GestureDetector gestureDetector;
public OnSwipeTouchListener(Context c) {
gestureDetector = new GestureDetector(c, new GestureListener());
}
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
onClick();
return super.onSingleTapUp(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
onDoubleClick();
return super.onDoubleTap(e);
}
@Override
public void onLongPress(MotionEvent e) {
onLongClick();
super.onLongPress(e);
}
// Determines the fling velocity and then fires the appropriate swipe event accordingly
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeDown();
} else {
onSwipeUp();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeUp() {
}
public void onSwipeDown() {
}
public void onClick() {
}
public void onDoubleClick() {
}
public void onLongClick() {
}
}
Вам не потрібні складні обчислення. Це можна зробити просто за допомогою OnGestureListener
інтерфейсу з GestureDetector
класу.
onFling
Метод всередині ви можете виявити всі чотири напрямки, як це:
MyGestureListener.java
:
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
public class MyGestureListener implements GestureDetector.OnGestureListener{
private static final long VELOCITY_THRESHOLD = 3000;
@Override
public boolean onDown(final MotionEvent e){ return false; }
@Override
public void onShowPress(final MotionEvent e){ }
@Override
public boolean onSingleTapUp(final MotionEvent e){ return false; }
@Override
public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX,
final float distanceY){ return false; }
@Override
public void onLongPress(final MotionEvent e){ }
@Override
public boolean onFling(final MotionEvent e1, final MotionEvent e2,
final float velocityX,
final float velocityY){
if(Math.abs(velocityX) < VELOCITY_THRESHOLD
&& Math.abs(velocityY) < VELOCITY_THRESHOLD){
return false;//if the fling is not fast enough then it's just like drag
}
//if velocity in X direction is higher than velocity in Y direction,
//then the fling is horizontal, else->vertical
if(Math.abs(velocityX) > Math.abs(velocityY)){
if(velocityX >= 0){
Log.i("TAG", "swipe right");
}else{//if velocityX is negative, then it's towards left
Log.i("TAG", "swipe left");
}
}else{
if(velocityY >= 0){
Log.i("TAG", "swipe down");
}else{
Log.i("TAG", "swipe up");
}
}
return true;
}
}
використання:
GestureDetector mDetector = new GestureDetector(MainActivity.this, new MyGestureListener());
view.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(final View v, final MotionEvent event){
return mDetector.onTouchEvent(event);
}
});
velocityX
та velocityY
в onFling
методі. хоча можна експериментувати, щоб визначити, яке значення найкраще відповідає вашим потребам, але остаточне число було б універсальним.
Використовуйте SwipeListView і дозвольте йому обробляти пошук жестів для вас.
Котлінська версія @Mirek Rusin тут:
OnSwipeTouchListener.kt:
open class OnSwipeTouchListener(ctx: Context) : OnTouchListener {
private val gestureDetector: GestureDetector
companion object {
private val SWIPE_THRESHOLD = 100
private val SWIPE_VELOCITY_THRESHOLD = 100
}
init {
gestureDetector = GestureDetector(ctx, GestureListener())
}
override fun onTouch(v: View, event: MotionEvent): Boolean {
return gestureDetector.onTouchEvent(event)
}
private inner class GestureListener : SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean {
return true
}
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
var result = false
try {
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight()
} else {
onSwipeLeft()
}
result = true
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom()
} else {
onSwipeTop()
}
result = true
}
} catch (exception: Exception) {
exception.printStackTrace()
}
return result
}
}
open fun onSwipeRight() {}
open fun onSwipeLeft() {}
open fun onSwipeTop() {}
open fun onSwipeBottom() {}
}
Використання:
view.setOnTouchListener(object : OnSwipeTouchListener(context) {
override fun onSwipeTop() {
super.onSwipeTop()
}
override fun onSwipeBottom() {
super.onSwipeBottom()
}
override fun onSwipeLeft() {
super.onSwipeLeft()
}
override fun onSwipeRight() {
super.onSwipeRight()
}
})
open
ключове слово було справа для мене ...
Щоб додати також onClick, ось що я зробив.
....
// in OnSwipeTouchListener class
private final class GestureListener extends SimpleOnGestureListener {
.... // normal GestureListener code
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
onClick(); // my method
return super.onSingleTapConfirmed(e);
}
} // end GestureListener class
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
public void onClick(){
}
// as normal
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
} // end OnSwipeTouchListener class
Я використовую фрагменти, тому використовую getActivity () для контексту. Ось як я це реалізував - і це працює.
myLayout.setOnTouchListener(new OnSwipeTouchListener(getActivity()) {
public void onSwipeTop() {
Toast.makeText(getActivity(), "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(getActivity(), "bottom", Toast.LENGTH_SHORT).show();
}
public void onClick(){
Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
}
});
Метод @Edward Brey чудово працює. Якщо хтось також бажає скопіювати та вставити імпорт для OnSwipeTouchListener
, ось вони:
import android.content.Context;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
Невелика модифікація відповіді @Mirek Rusin, і тепер ви можете виявити перемикання мультитач. Цей код знаходиться на Котліні:
class OnSwipeTouchListener(ctx: Context, val onGesture: (gestureCode: Int) -> Unit) : OnTouchListener {
private val SWIPE_THRESHOLD = 200
private val SWIPE_VELOCITY_THRESHOLD = 200
private val gestureDetector: GestureDetector
var fingersCount = 0
fun resetFingers() {
fingersCount = 0
}
init {
gestureDetector = GestureDetector(ctx, GestureListener())
}
override fun onTouch(v: View, event: MotionEvent): Boolean {
if (event.pointerCount > fingersCount) {
fingersCount = event.pointerCount
}
return gestureDetector.onTouchEvent(event)
}
private inner class GestureListener : SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean {
return true
}
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
var result = false
try {
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
val gesture = when (fingersCount) {
1 -> Gesture.SWIPE_RIGHT
2 -> Gesture.TWO_FINGER_SWIPE_RIGHT
3 -> Gesture.THREE_FINGER_SWIPE_RIGHT
else -> -1
}
if (gesture > 0) {
onGesture.invoke(gesture)
}
} else {
val gesture = when (fingersCount) {
1 -> Gesture.SWIPE_LEFT
2 -> Gesture.TWO_FINGER_SWIPE_LEFT
3 -> Gesture.THREE_FINGER_SWIPE_LEFT
else -> -1
}
if (gesture > 0) {
onGesture.invoke(gesture)
}
}
resetFingers()
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
val gesture = when (fingersCount) {
1 -> Gesture.SWIPE_DOWN
2 -> Gesture.TWO_FINGER_SWIPE_DOWN
3 -> Gesture.THREE_FINGER_SWIPE_DOWN
else -> -1
}
if (gesture > 0) {
onGesture.invoke(gesture)
}
} else {
val gesture = when (fingersCount) {
1 -> Gesture.SWIPE_UP
2 -> Gesture.TWO_FINGER_SWIPE_UP
3 -> Gesture.THREE_FINGER_SWIPE_UP
else -> -1
}
if (gesture > 0) {
onGesture.invoke(gesture)
}
}
resetFingers()
}
result = true
} catch (exception: Exception) {
exception.printStackTrace()
}
return result
}
}}
Де Gesture.SWIPE_RIGHT та інші - унікальний цілочисельний покажчик жестів, який я використовую для виявлення типу жестів пізніше у своїй діяльності:
rootView?.setOnTouchListener(OnSwipeTouchListener(this, {
gesture -> log(Gesture.parseName(this, gesture))
}))
Отже, ви бачите, що тут жест - це ціла змінна величина, яка має значення, яке я пройшов раніше.
Моє рішення аналогічне вищевказаному, але я абстрагував керування жестами абстрактним класом OnGestureRegisterListener.java
, який включає в себе пальцем , натисканням та довгим клацанням жести клацань.
OnGestureRegisterListener.java
public abstract class OnGestureRegisterListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
private View view;
public OnGestureRegisterListener(Context context) {
gestureDetector = new GestureDetector(context, new GestureListener());
}
@Override
public boolean onTouch(View view, MotionEvent event) {
this.view = view;
return gestureDetector.onTouchEvent(event);
}
public abstract void onSwipeRight(View view);
public abstract void onSwipeLeft(View view);
public abstract void onSwipeBottom(View view);
public abstract void onSwipeTop(View view);
public abstract void onClick(View view);
public abstract boolean onLongClick(View view);
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
onLongClick(view);
super.onLongPress(e);
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
onClick(view);
return super.onSingleTapUp(e);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight(view);
} else {
onSwipeLeft(view);
}
result = true;
}
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom(view);
} else {
onSwipeTop(view);
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
}
І використовуйте його так. Зауважте, що ви також можете легко передати свій View
параметр.
OnGestureRegisterListener onGestureRegisterListener = new OnGestureRegisterListener(this) {
public void onSwipeRight(View view) {
// Do something
}
public void onSwipeLeft(View view) {
// Do something
}
public void onSwipeBottom(View view) {
// Do something
}
public void onSwipeTop(View view) {
// Do something
}
public void onClick(View view) {
// Do something
}
public boolean onLongClick(View view) {
// Do something
return true;
}
};
Button button = findViewById(R.id.my_button);
button.setOnTouchListener(onGestureRegisterListener);
Я робив подібні речі, але лише для горизонтальних пальців
import android.content.Context
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
abstract class OnHorizontalSwipeListener(val context: Context) : View.OnTouchListener {
companion object {
const val SWIPE_MIN = 50
const val SWIPE_VELOCITY_MIN = 100
}
private val detector = GestureDetector(context, GestureListener())
override fun onTouch(view: View, event: MotionEvent) = detector.onTouchEvent(event)
abstract fun onRightSwipe()
abstract fun onLeftSwipe()
private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
override fun onDown(e: MotionEvent) = true
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float)
: Boolean {
val deltaY = e2.y - e1.y
val deltaX = e2.x - e1.x
if (Math.abs(deltaX) < Math.abs(deltaY)) return false
if (Math.abs(deltaX) < SWIPE_MIN
&& Math.abs(velocityX) < SWIPE_VELOCITY_MIN) return false
if (deltaX > 0) onRightSwipe() else onLeftSwipe()
return true
}
}
}
І тоді його можна використовувати для перегляду компонентів
private fun listenHorizontalSwipe(view: View) {
view.setOnTouchListener(object : OnHorizontalSwipeListener(context!!) {
override fun onRightSwipe() {
Log.d(TAG, "Swipe right")
}
override fun onLeftSwipe() {
Log.d(TAG, "Swipe left")
}
}
)
}
Це питання було задано багато років тому. Тепер є краще рішення: SmartSwipe: https://github.com/luckybilly/SmartSwipe
код виглядає приблизно так:
SmartSwipe.wrap(contentView)
.addConsumer(new StayConsumer()) //contentView stay while swiping with StayConsumer
.enableAllDirections() //enable directions as needed
.addListener(new SimpleSwipeListener() {
@Override
public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
//direction:
// 1: left
// 2: right
// 4: top
// 8: bottom
}
})
;
@Mirek Rusin answeir дуже добре. Але помилка є невеликою, і виправлення потрібно -
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
if (getOnSwipeListener() != null) {
getOnSwipeListener().onSwipeRight();
}
} else {
if (getOnSwipeListener() != null) {
getOnSwipeListener().onSwipeLeft();
}
}
result = true;
}
}
else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
if (getOnSwipeListener() != null) {
getOnSwipeListener().onSwipeBottom();
}
} else {
if (getOnSwipeListener() != null) {
getOnSwipeListener().onSwipeTop();
}
}
result = true;
}
Яка різниця? Ми встановлюємо результат = true, тільки якщо ми перевірили, що всі перестановки (і SWIPE_THRESHOLD, і SWIPE_VELOCITY_THRESHOLD у порядку). Це важливо, якщо ми відкидаємо пробіг, якщо деякі доопрацювання не досягнуті, і нам доведеться робити що-небудь в методі OnSwipeTouchListener onTouchEvent!
Ось простий код Android для виявлення напрямку жестів
В MainActivity.java
і activity_main.xml
напишіть наступний код:
MainActivity.java
import java.util.ArrayList;
import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.GestureStroke;
import android.gesture.Prediction;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends Activity implements
OnGesturePerformedListener {
GestureOverlayView gesture;
GestureLibrary lib;
ArrayList<Prediction> prediction;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lib = GestureLibraries.fromRawResource(MainActivity.this,
R.id.gestureOverlayView1);
gesture = (GestureOverlayView) findViewById(R.id.gestureOverlayView1);
gesture.addOnGesturePerformedListener(this);
}
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<GestureStroke> strokeList = gesture.getStrokes();
// prediction = lib.recognize(gesture);
float f[] = strokeList.get(0).points;
String str = "";
if (f[0] < f[f.length - 2]) {
str = "Right gesture";
} else if (f[0] > f[f.length - 2]) {
str = "Left gesture";
} else {
str = "no direction";
}
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_LONG).show();
}
}
activity_main.xml
<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:android1="http://schemas.android.com/apk/res/android"
xmlns:android2="http://schemas.android.com/apk/res/android"
android:id="@+id/gestureOverlayView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android1:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Draw gesture"
android:textAppearance="?android:attr/textAppearanceMedium" />
</android.gesture.GestureOverlayView>
import android.content.Context
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
/**
* Detects left and right swipes across a view.
*/
class OnSwipeTouchListener(context: Context, onSwipeCallBack: OnSwipeCallBack?) : OnTouchListener {
private var gestureDetector : GestureDetector
private var onSwipeCallBack: OnSwipeCallBack?=null
init {
gestureDetector = GestureDetector(context, GestureListener())
this.onSwipeCallBack = onSwipeCallBack!!
}
companion object {
private val SWIPE_DISTANCE_THRESHOLD = 100
private val SWIPE_VELOCITY_THRESHOLD = 100
}
/* fun onSwipeLeft() {}
fun onSwipeRight() {}*/
override fun onTouch(v: View, event: MotionEvent): Boolean {
return gestureDetector.onTouchEvent(event)
}
private inner class GestureListener : SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean {
return true
}
override fun onFling(eve1: MotionEvent?, eve2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean {
try {
if(eve1 != null&& eve2!= null) {
val distanceX = eve2?.x - eve1?.x
val distanceY = eve2?.y - eve1?.y
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeCallBack!!.onSwipeLeftCallback()
else
onSwipeCallBack!!.onSwipeRightCallback()
return true
}
}
}catch (exception:Exception){
exception.printStackTrace()
}
return false
}
}
}
Якщо ви хочете відобразити деякі кнопки з діями, коли елемент списку прогортається, в Інтернеті є багато бібліотек, які мають таку поведінку. Я реалізував бібліотеку, яку знайшов в Інтернеті, і я дуже задоволений. Він дуже простий у використанні та дуже швидкий. Я покращив оригінальну бібліотеку і додав новий прослуховувач клацань для клацання елемента. Також я додав бібліотеку шрифтів (див. Шрифт) ( http://fortawesome.github.io/Font-Awesome/ ), і тепер ви можете просто додати назву нового елемента та вказати ім'я піктограми з шрифту awesome.
Ось посилання github
public class TranslatorSwipeTouch implements OnTouchListener
{
private String TAG="TranslatorSwipeTouch";
@SuppressWarnings("deprecation")
private GestureDetector detector=new GestureDetector(new TranslatorGestureListener());
@Override
public boolean onTouch(View view, MotionEvent event)
{
return detector.onTouchEvent(event);
}
private class TranslatorGestureListener extends SimpleOnGestureListener
{
private final int GESTURE_THRESHOULD=100;
private final int GESTURE_VELOCITY_THRESHOULD=100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent event1,MotionEvent event2,float velocityx,float velocityy)
{
try
{
float diffx=event2.getX()-event1.getX();
float diffy=event2.getY()-event1.getY();
if(Math.abs(diffx)>Math.abs(diffy))
{
if(Math.abs(diffx)>GESTURE_THRESHOULD && Math.abs(velocityx)>GESTURE_VELOCITY_THRESHOULD)
{
if(diffx>0)
{
onSwipeRight();
}
else
{
onSwipeLeft();
}
}
}
else
{
if(Math.abs(diffy)>GESTURE_THRESHOULD && Math.abs(velocityy)>GESTURE_VELOCITY_THRESHOULD)
{
if(diffy>0)
{
onSwipeBottom();
}
else
{
onSwipeTop();
}
}
}
}
catch(Exception e)
{
Log.d(TAG, ""+e.getMessage());
}
return false;
}
public void onSwipeRight()
{
//Toast.makeText(this.getClass().get, "swipe right", Toast.LENGTH_SHORT).show();
Log.i(TAG, "Right");
}
public void onSwipeLeft()
{
Log.i(TAG, "Left");
//Toast.makeText(MyActivity.this, "swipe left", Toast.LENGTH_SHORT).show();
}
public void onSwipeTop()
{
Log.i(TAG, "Top");
//Toast.makeText(MyActivity.this, "swipe top", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom()
{
Log.i(TAG, "Bottom");
//Toast.makeText(MyActivity.this, "swipe bottom", Toast.LENGTH_SHORT).show();
}
}
}
використання відповіді Едварда Брі в Котліні
view.setOnTouchListener(object: OnSwipeTouchListener(this) {
override fun onSwipeLeft() {
super.onSwipeLeft()
}
override fun onSwipeRight() {
super.onSwipeRight()
}
}
)