Как обнаружить пролистывание влево или вправо в Android?
У меня есть вид редактирования текста в Android. На этом я хочу обнаружить, проведите пальцем влево или вправо. Я могу получить его на пустом месте с помощью приведенного ниже кода. Но это не работает, когда я проведу по тексту редактирования. Как мне это сделать? Пожалуйста, дайте мне знать, если я делаю что-то не так. Спасибо.
Используемый код
switch (touchevent.getAction())
{
case MotionEvent.ACTION_DOWN:
{
oldTouchValue = touchevent.getX();
break;
}
case MotionEvent.ACTION_UP:
{
float currentX = touchevent.getX();
if (oldTouchValue < currentX)
{
// swiped left
}
if (oldTouchValue > currentX )
{
swiped right
}
break;
}
}
18 ответов
Простейший детектор движения слева направо:
В вашем классе деятельности добавьте следующие атрибуты:
private float x1,x2;
static final int MIN_DISTANCE = 150;
и переопределить onTouchEvent()
метод:
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
{
Toast.makeText(this, "left2right swipe", Toast.LENGTH_SHORT).show ();
}
else
{
// consider as something else - a screen tap for example
}
break;
}
return super.onTouchEvent(event);
}
Мне нравится код от @user2999943. Но только некоторые незначительные изменения для моих собственных целей.
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
{
// Left to Right swipe action
if (x2 > x1)
{
Toast.makeText(this, "Left to Right swipe [Next]", Toast.LENGTH_SHORT).show ();
}
// Right to left swipe action
else
{
Toast.makeText(this, "Right to Left swipe [Previous]", Toast.LENGTH_SHORT).show ();
}
}
else
{
// consider as something else - a screen tap for example
}
break;
}
return super.onTouchEvent(event);
}
Это симпатичный класс, который я использую (в случаях, когда я хочу поймать событие в View, если это ViewGroup, я использую вторую реализацию):
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class SwipeDetector implements View.OnTouchListener{
private int min_distance = 100;
private float downX, downY, upX, upY;
private View v;
private onSwipeEvent swipeEventListener;
public SwipeDetector(View v){
this.v=v;
v.setOnTouchListener(this);
}
public void setOnSwipeListener(onSwipeEvent listener)
{
try{
swipeEventListener=listener;
}
catch(ClassCastException e)
{
Log.e("ClassCastException","please pass SwipeDetector.onSwipeEvent Interface instance",e);
}
}
public void onRightToLeftSwipe(){
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.RIGHT_TO_LEFT);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
}
public void onLeftToRightSwipe(){
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.LEFT_TO_RIGHT);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
}
public void onTopToBottomSwipe(){
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.TOP_TO_BOTTOM);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
}
public void onBottomToTopSwipe(){
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.BOTTOM_TO_TOP);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
}
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
//HORIZONTAL SCROLL
if(Math.abs(deltaX) > Math.abs(deltaY))
{
if(Math.abs(deltaX) > min_distance){
// left or right
if(deltaX < 0)
{
this.onLeftToRightSwipe();
return true;
}
if(deltaX > 0) {
this.onRightToLeftSwipe();
return true;
}
}
else {
//not long enough swipe...
return false;
}
}
//VERTICAL SCROLL
else
{
if(Math.abs(deltaY) > min_distance){
// top or down
if(deltaY < 0)
{ this.onTopToBottomSwipe();
return true;
}
if(deltaY > 0)
{ this.onBottomToTopSwipe();
return true;
}
}
else {
//not long enough swipe...
return false;
}
}
return true;
}
}
return false;
}
public interface onSwipeEvent
{
public void SwipeEventDetected(View v, SwipeTypeEnum SwipeType);
}
public SwipeDetector setMinDistanceInPixels(int min_distance)
{
this.min_distance=min_distance;
return this;
}
public enum SwipeTypeEnum
{
RIGHT_TO_LEFT,LEFT_TO_RIGHT,TOP_TO_BOTTOM,BOTTOM_TO_TOP
}
}
и это пример использования:
filters_container=(RelativeLayout)root.findViewById(R.id.filters_container);
new SwipeDetector(filters_container).setOnSwipeListener(new SwipeDetector.onSwipeEvent() {
@Override
public void SwipeEventDetected(View v, SwipeDetector.SwipeTypeEnum swipeType) {
if(swipeType==SwipeDetector.SwipeTypeEnum.LEFT_TO_RIGHT)
getActivity().onBackPressed();
}
});
В некоторых случаях вы хотели бы обнаружить жесты смахивания на контейнере и передать сенсорные события дочерним элементам, чтобы в этом случае вы могли создать пользовательскую группу представлений, скажем, RelativeLayout и переопределить onInterceptTouchEvent, и там вы можете обнаружить событие смахивания. без блокировки передачи события Touch для ваших дочерних представлений, например:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
public class SwipeDetectRelativeLayout extends RelativeLayout {
private float x1,x2;
static final int MIN_DISTANCE=150;
private onSwipeEventDetected mSwipeDetectedListener;
public SwipeDetectRelativeLayout(Context context) {
super(context);
}
public SwipeDetectRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeDetectRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch(ev.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = ev.getX();
break;
case MotionEvent.ACTION_UP:
x2 = ev.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
{
//swiping right to left
if(deltaX<0)
{
if(mSwipeDetectedListener!=null)
mSwipeDetectedListener.swipeEventDetected();
}
}
break;
}
return super.onInterceptTouchEvent(ev);
}
public interface onSwipeEventDetected
{
public void swipeEventDetected();
}
public void registerToSwipeEvents(onSwipeEventDetected listener)
{
this.mSwipeDetectedListener=listener;
}
}
Размах события являются своего рода onTouch
События. Просто упростив ответ @Gal Rom, просто следите за вертикальными и горизонтальными дельтами, и с помощью небольшой математики вы сможете определить, каким было движение touchEvent. (Опять же, позвольте мне подчеркнуть, что это было ОБЯЗАТЕЛЬНО на основе предыдущего ответа, но простота может понравиться новичкам). Идея состоит в том, чтобы расширить OnTouchListener, определить, какой именно размах (касание) только что произошел, и вызвать определенные методы для каждого вида.
public class SwipeListener implements View.OnTouchListener {
private int min_distance = 100;
private float downX, downY, upX, upY;
View v;
@Override
public boolean onTouch(View v, MotionEvent event) {
this.v = v;
switch(event.getAction()) { // Check vertical and horizontal touches
case MotionEvent.ACTION_DOWN: {
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
//HORIZONTAL SCROLL
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (Math.abs(deltaX) > min_distance) {
// left or right
if (deltaX < 0) {
this.onLeftToRightSwipe();
return true;
}
if (deltaX > 0) {
this.onRightToLeftSwipe();
return true;
}
} else {
//not long enough swipe...
return false;
}
}
//VERTICAL SCROLL
else {
if (Math.abs(deltaY) > min_distance) {
// top or down
if (deltaY < 0) {
this.onTopToBottomSwipe();
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe();
return true;
}
} else {
//not long enough swipe...
return false;
}
}
return false;
}
}
return false;
}
public void onLeftToRightSwipe(){
Toast.makeText(v.getContext(),"left to right",
Toast.LENGTH_SHORT).show();
}
public void onRightToLeftSwipe() {
Toast.makeText(v.getContext(),"right to left",
Toast.LENGTH_SHORT).show();
}
public void onTopToBottomSwipe() {
Toast.makeText(v.getContext(),"top to bottom",
Toast.LENGTH_SHORT).show();
}
public void onBottomToTopSwipe() {
Toast.makeText(v.getContext(),"bottom to top",
Toast.LENGTH_SHORT).show();
}
}
Я написал простой класс, который позволяет легко обнаруживать события смахивания - TOP, RIGHT, BOTTOM, LEFT.
1: обнаружение отдельного события смахивания
// Detect and consume specific events
// {Available methods} - detectTop, detectRight, detectBottom, detectLeft
SwipeEvents.detectTop(swipeElement, new SwipeEvents.SwipeSingleCallback() {
@Override
public void onSwipe() {
showToast("Swiped - detectTop");
}
});
2: обнаружение любого из событий смахивания с одним обратным вызовом.
SwipeEvents.detect( swipeElement, new SwipeEvents.SwipeCallback() {
@Override
public void onSwipeTop() {
//Swiped top
}
@Override
public void onSwipeRight() {
//Swiped right
}
@Override
public void onSwipeBottom() {
//Swiped bottom
}
@Override
public void onSwipeLeft() {
//Swiped left
}
});
Вот сообщение в блоге с объяснением того, как использовать: http://bmutinda.com/android-detect-swipe-events/
Я также создал Gist для фрагментов кода, доступных здесь: https://gist.github.com/bmutinda/9578f70f1df9bd0687b8
Благодарю.
Детектор движения слева направо и справа налево
Во-первых, объявите две переменные типа данных float.
private float x1, x2;
Во-вторых, подключите ваше представление XML в Java. Как у меня ImageView
ImageView img = (ImageView) findViewById(R.id.imageView);
В-третьих, setOnTouchListener
на ваше ImageView
,
img.setOnTouchListener(
new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (deltaX < 0) {
Toast.makeText(MainActivity.this,
"Right to Left swipe",
Toast.LENGTH_SHORT).show();
}else if(deltaX >0){
Toast.makeText(MainActivity.this,
"Left to Right swipe",
Toast.LENGTH_SHORT).show();
}
break;
}
return false;
}
});
Вы должны расширить класс от View.OnTouchListener
и справиться с onTouch
метод, переопределив его.
interface SwipeListener {
fun onSwipeLeft()
fun onSwipeRight()
}
class SwipeGestureListener internal constructor(
private val listener: SwipeListener,
private val minDistance: Int = DEFAULT_SWIPE_MIN_DISTANCE
) : View.OnTouchListener {
companion object {
const val DEFAULT_SWIPE_MIN_DISTANCE = 200
}
private var anchorX = 0F
override fun onTouch(view: View, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
anchorX = event.x
return true
}
MotionEvent.ACTION_UP -> {
if (abs(event.x - anchorX) > minDistance) {
if (event.x > anchorX) {
listener.onSwipeRight()
} else {
listener.onSwipeLeft()
}
}
return true
}
}
return view.performClick()
}
}
Вы можете легко реализовать это в своем Activity
или Fragment
.
class MainActivity : AppCompatActivity(), SwipeListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewGroup.setOnTouchListener(SwipeGestureListener(this))
}
override fun onSwipeLeft() {
Toast.makeText(this, "Swipe Left", Toast.LENGTH_SHORT).show()
}
override fun onSwipeRight() {
Toast.makeText(this, "Swipe Right", Toast.LENGTH_SHORT).show()
}
}
Я хочу добавить к принятому ответу, который работает частично, но отсутствует переменная времени, что делает его идеальным.
Простейший детектор движения слева направо с переменной времени:
В вашем классе деятельности добавьте следующие атрибуты:
private float x1,x2;
private long startClickTime;
static final int MIN_DISTANCE = 150;
static final int MAX_SWIPE_TIME = 200;
и переопределить метод onTouchEvent ():
@Override
public boolean onTouchEvent(MotionEvent event)
{
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN:
startClickTime = Calendar.getInstance().getTimeInMillis();
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE && clickDuration < MAX_SWIPE_TIME)
{
Toast.makeText(this, "left2right swipe", Toast.LENGTH_SHORT).show ();
}
else
{
// consider as something else - a screen tap for example
}
break;
}
return super.onTouchEvent(event);
}
Я думаю, что вы хотите, называется броском. MotionEvents можно использовать для определения направления броска.
public class MainActivity extends Activity implements GestureDetector.OnGestureListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stellar_layout);
mDetector = new GestureDetectorCompat(this, this);
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.d(tag, "onFling:\n " + event1.toString()+ "\n " + event2.toString());
/* prints the following
MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=297.0, y[0]=672.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=488341979, downTime=488341979, deviceId=6, source=0x1002 }
MotionEvent { action=ACTION_UP, id[0]=0, x[0]=560.0, y[0]=583.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=488342047, downTime=488341979, deviceId=6, source=0x1002 }
*/
return true;
}
}
http://developer.android.com/training/gestures/detector.html
Это должно помочь вам, может быть...
private final GestureDetector.SimpleOnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.i("gestureDebug333", "doubleTapped:" + e);
return super.onDoubleTap(e);
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
Log.i("gestureDebug333", "doubleTappedEvent:" + e);
return super.onDoubleTapEvent(e);
}
@Override
public boolean onDown(MotionEvent e) {
Log.i("gestureDebug333", "onDown:" + e);
return super.onDown(e);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.i("gestureDebug333", "flinged:" + e1 + "---" + e2);
Log.i("gestureDebug333", "fling velocity:" + velocityX + "---" + velocityY);
if (e1.getAction() == MotionEvent.ACTION_DOWN && e1.getX() > (e2.getX() + 300)){
// Toast.makeText(context, "flinged right to left", Toast.LENGTH_SHORT).show();
goForward();
}
if (e1.getAction() == MotionEvent.ACTION_DOWN && e2.getX() > (e1.getX() + 300)){
//Toast.makeText(context, "flinged left to right", Toast.LENGTH_SHORT).show();
goBack();
}
return super.onFling(e1, e2, velocityX, velocityY);
}
@Override
public void onLongPress(MotionEvent e) {
super.onLongPress(e);
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return super.onScroll(e1, e2, distanceX, distanceY);
}
@Override
public void onShowPress(MotionEvent e) {
super.onShowPress(e);
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
return super.onSingleTapConfirmed(e);
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return super.onSingleTapUp(e);
}
};
После целого дня работы над этой функцией наконец-то удалось получить правильный ответ.
Сначала создайте следующие классы:
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by hoshyar on 1/19/17.
*/
public class SwipeDetector implements View.OnTouchListener {
public static enum Action {
LR, // Left to Right
RL, // Right to Left
TB, // Top to bottom
BT, // Bottom to Top
None // when no action was detected
}
private static final String logTag = "Swipe";
private static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
private Action mSwipeDetected = Action.None;
public boolean swipeDetected() {
return mSwipeDetected != Action.None;
}
public Action getAction() {
return mSwipeDetected;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
mSwipeDetected = Action.None;
return false;
case MotionEvent.ACTION_MOVE:
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
Log.i(logTag,String.valueOf(deltaX));
Log.i(logTag,String.valueOf(deltaX));
if (deltaY>0 && deltaY<10 && deltaX<0 || deltaY==0 && deltaX>-15 && deltaX<0){
Log.i(logTag,"to right");
}if (deltaY>=0 && deltaY<10 && deltaX>0 || deltaY<0 && deltaX>15 && deltaX<40){
Log.i(logTag,"to left");
}
if (Math.abs(deltaX) > MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
mSwipeDetected = Action.LR;
return false;
}
if (deltaX > 0) {
mSwipeDetected = Action.RL;
return false;
}
} else if (Math.abs(deltaY) > MIN_DISTANCE) {
if (deltaY < 0) {
Log.i(logTag,"to bottom");
mSwipeDetected = Action.TB;
return false;
}
if (deltaY > 0) {
Log.i(logTag,"to up");
mSwipeDetected = Action.BT;
return false;
}
}
return true;
}
return false;
}
}
Наконец на объект, который вы хотите применить. Мой пример:
SwipeDetector swipeDetector = new SwipeDetector();
listView.setOnTouchListener(swipeDetector);
Удачи.
Обнаружение удара в четырех направлениях
private float x1,x2,y1,y2;
static final int MIN_DISTANCE = 70;
а также
switch(pSceneTouchEvent.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = pSceneTouchEvent.getX();
y1 = pSceneTouchEvent.getY();
break;
case MotionEvent.ACTION_UP:
x2 = pSceneTouchEvent.getX();
y2 = pSceneTouchEvent.getY();
float deltaX = x2 - x1;
float deltaY = y2 - y1;
if (deltaX > MIN_DISTANCE)
{
swipeLeftToRight();
}
else if( Math.abs(deltaX) > MIN_DISTANCE)
{
swipeRightToLeft();
}
else if(deltaY > MIN_DISTANCE){
swipeTopToBottom();
}
else if( Math.abs(deltaY) > MIN_DISTANCE){
swipeBottopmToTop();
}
break;
}
Вот общий детектор смахивания влево для любого вида в котлине с использованием привязки данных
@BindingAdapter("onSwipeLeft")
fun View.setOnSwipeLeft(runnable: Runnable) {
setOnTouchListener(object : View.OnTouchListener {
var x0 = 0F; var y0 = 0F; var t0 = 0L
val defaultClickDuration = 200
override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean {
motionEvent?.let { event ->
when(event.action) {
MotionEvent.ACTION_DOWN -> {
x0 = event.x; y0 = event.y; t0 = System.currentTimeMillis()
}
MotionEvent.ACTION_UP -> {
val x1 = event.x; val y1 = event.y; val t1 = System.currentTimeMillis()
if (x0 == x1 && y0 == y1 && (t1 - t0) < defaultClickDuration) {
performClick()
return false
}
if (x0 > x1) { runnable.run() }
}
else -> {}
}
}
return true
}
})
}
а затем использовать его в своем макете:
app:onSwipeLeft="@{() -> viewModel.swipeLeftHandler()}"
Короткая и простая версия:
1. Сначала создайте этот абстрактный класс
public abstract class HorizontalSwipeListener implements View.OnTouchListener {
private float firstX;
private int minDistance;
HorizontalSwipeListener(int minDistance) {
this.minDistance = minDistance;
}
abstract void onSwipeRight();
abstract void onSwipeLeft();
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
firstX = event.getX();
return true;
case MotionEvent.ACTION_UP:
float secondX = event.getX();
if (Math.abs(secondX - firstX) > minDistance) {
if (secondX > firstX) {
onSwipeLeft();
} else {
onSwipeRight();
}
}
return true;
}
return view.performClick();
}
}
2. Затем создайте конкретный класс, реализующий то, что вам нужно:
public class SwipeListener extends HorizontalSwipeListener {
public SwipeListener() {
super(200);
}
@Override
void onSwipeRight() {
System.out.println("right");
}
@Override
void onSwipeLeft() {
System.out.println("left");
}
}
Если вы хотите перехватить событие с начала свайпа, вы можете использовать MotionEvent.ACTION_MOVE и сохранить первое значение для сравнения.
private float upX1;
private float upX2;
private float upY1;
private float upY2;
private boolean isTouchCaptured = false;
static final int min_distance = 100;
viewObject.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
downX = event.getX();
downY = event.getY();
if (!isTouchCaptured) {
upX1 = event.getX();
upY1 = event.getY();
isTouchCaptured = true;
} else {
upX2 = event.getX();
upY2 = event.getY();
float deltaX = upX1 - upX2;
float deltaY = upY1 - upY2;
//HORIZONTAL SCROLL
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (Math.abs(deltaX) > min_distance) {
// left or right
if (deltaX < 0) {
return true;
}
if (deltaX > 0) {
return true;
}
} else {
//not long enough swipe...
return false;
}
}
//VERTICAL SCROLL
else {
if (Math.abs(deltaY) > min_distance) {
// top or down
if (deltaY < 0) {
return false;
}
if (deltaY > 0) {
return false;
}
} else {
//not long enough swipe...
return false;
}
}
}
return false;
}
case MotionEvent.ACTION_UP: {
isTouchCaptured = false;
}
}
return false;
}
});
public class TransferMarket extends Activity {
float x1,x2;
float y1, y2;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transfer_market);
}
// onTouchEvent () method gets called when User performs any touch event on screen
// Method to handle touch event like left to right swap and right to left swap
public boolean onTouchEvent(MotionEvent touchevent)
{
switch (touchevent.getAction())
{
// when user first touches the screen we get x and y coordinate
case MotionEvent.ACTION_DOWN:
{
x1 = touchevent.getX();
y1 = touchevent.getY();
break;
}
case MotionEvent.ACTION_UP:
{
x2 = touchevent.getX();
y2 = touchevent.getY();
//if left to right sweep event on screen
if (x1 < x2)
{
Toast.makeText(this, "Left to Right Swap Performed", Toast.LENGTH_LONG).show();
}
// if right to left sweep event on screen
if (x1 > x2)
{
Toast.makeText(this, "Right to Left Swap Performed", Toast.LENGTH_LONG).show();
}
// if UP to Down sweep event on screen
if (y1 < y2)
{
Toast.makeText(this, "UP to Down Swap Performed", Toast.LENGTH_LONG).show();
}
//if Down to UP sweep event on screen
if (y1 > y2)
{
Toast.makeText(this, "Down to UP Swap Performed", Toast.LENGTH_LONG).show();
}
break;
}
}
return false;
}
Чтобы обнаружить жесты смахивания специально для движений влево или вправо в Android, вы можете использовать обнаружение жестов, предоставляемоеGestureDetector
сорт
вы можете использовать этот код:
val gestureListener = object : GestureDetector.SimpleOnGestureListener() {
private val SWIPE_THRESHOLD = 100
private val SWIPE_VELOCITY_THRESHOLD = 100
override fun onFling(
e1: MotionEvent,
e2: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
val deltaX = e2.x - e1.x
val deltaY = e2.y - e1.y
if (Math.abs(deltaX) > Math.abs(deltaY)
&& Math.abs(deltaX) > SWIPE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD
) {
if (deltaX > 0) {
// Swipe right detected
} else {
// Swipe left detected
}
return true
}
return false
}
}
также :
val gestureDetector = GestureDetector(this, gestureListener)
view.setOnTouchListener { v, event ->
gestureDetector.onTouchEvent(event)
true // Return 'true' to indicate that you're consuming the touch event
}
Лучший ответ - @Gal Rom 's. есть больше информации об этом: сначала коснитесь возврата события к дочерним представлениям. и если вы определяете для них прослушиватель onClick или onTouch, представление parnt (например, фрагмент) не получит никакого прослушивателя касания. Так что если вы хотите определить прослушиватель смахивания для фрагмента в этой ситуации, вы должны реализовать его в новом классе:
package com.neganet.QRelations.fragments;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class SwipeListenerFragment extends FrameLayout {
private float x1,x2;
static final int MIN_DISTANCE=150;
private onSwipeEventDetected mSwipeDetectedListener;
public SwipeListenerFragment(Context context) {
super(context);
}
public SwipeListenerFragment(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeListenerFragment(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean result=false;
switch(ev.getAction())
{
case MotionEvent.ACTION_DOWN:
x1 = ev.getX();
break;
case MotionEvent.ACTION_UP:
x2 = ev.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
{
if(deltaX<0)
{
result=true;
if(mSwipeDetectedListener!=null)
mSwipeDetectedListener.swipeLeftDetected();
}else if(deltaX>0){
result=true;
if(mSwipeDetectedListener!=null)
mSwipeDetectedListener.swipeRightDetected();
}
}
break;
}
return result;
}
public interface onSwipeEventDetected
{
public void swipeLeftDetected();
public void swipeRightDetected();
}
public void registerToSwipeEvents(onSwipeEventDetected listener)
{
this.mSwipeDetectedListener=listener;
}
}
Я изменил класс @Gal Rom. Таким образом, он может обнаружить как правое, так и левое движение и, в частности, возвращает onInterceptTouchEvent true после обнаружения. это важно, потому что если мы не делаем это несколько раз, дочерние представления могут получить событие, и оба из Swipe для фрагмента и onClick для дочернего представления (например) запускаются и вызывают некоторые проблемы. после создания этого класса вы должны изменить свой XML-файл фрагмента:
<com.neganet.QRelations.fragments.SwipeListenerFragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:id="@+id/main_list_layout"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_height="match_parent" tools:context="com.neganet.QRelations.fragments.mainList"
android:background="@color/main_frag_back">
<!-- TODO: Update blank fragment layout -->
<android.support.v7.widget.RecyclerView
android:id="@+id/farazList"
android:scrollbars="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="left|center_vertical" />
</com.neganet.QRelations.fragments.SwipeListenerFragment>
Вы видите, что начальный тег - это класс, который мы создали. теперь в классе фрагмента:
View view=inflater.inflate(R.layout.fragment_main_list, container, false);
SwipeListenerFragment tdView=(SwipeListenerFragment) view;
tdView.registerToSwipeEvents(this);
and then Implement SwipeListenerFragment.onSwipeEventDetected in it:
@Override
public void swipeLeftDetected() {
Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
}
@Override
public void swipeRightDetected() {
Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
}
Это немного сложно, но работает отлично:)