To detect the movement of Swipe above the buttons or any other view, without having to implement this logic in each of the views, we need to find a way to intercept that movement before they.
The class Viewgroup has the method onInterceptTouchEvent() which, when implemented, makes it possible to intercept Motionevent which are sent to views daughters.
If the method returns true
, the Motionevent will be passed to the method onTouchEvent()
of Viewgroup, otherwise, is passed to onTouchEvent()
of view where the event took place.
We will then have to write a class that inherits from a Viewgroup(in the case Framelayout) and implement the methods onInterceptTouchEvent()
and onTouchEvent()
in order to treat the movement of Swipe.
public class SwipeInterceptor extends FrameLayout {
public interface OnSwipeListener{
public void onSwipeLeft();
public void onSwipeRight();
}
private OnSwipeListener mSwipeListener;
private int mTouchSlop;
private boolean mIsDragged;
private float mLastX;
private float mLastY;
private float mStartX;
private float mDeltaXTotal = 0;
public SwipeInterceptor(Context context, AttributeSet attrs) {
super(context, attrs);
setTouchSlop(context);
}
//Api level 21 ou superior
/* public SwipeInterceptor(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setTouchSlop(context);
}*/
public SwipeInterceptor(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
setTouchSlop(context);
}
public SwipeInterceptor(Context context) {
super(context);
setTouchSlop(context);
}
public void setOnSwipeListenner(OnSwipeListener listener) {
mSwipeListener = listener;
}
private void setTouchSlop(Context context){
ViewConfiguration vc = ViewConfiguration.get(context);
mTouchSlop = vc.getScaledTouchSlop();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = event.getX();
mLastY = event.getY();
mStartX = mLastX;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
mIsDragged = false;
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
float xDelta = Math.abs(x - mLastX);
float yDelta = Math.abs(y - mLastY);
float xDeltaTotal = x - mStartX;
if (xDelta > yDelta && Math.abs(xDeltaTotal) > mTouchSlop) {
mIsDragged = true;
mStartX = x;
return true;
}
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (mIsDragged && mSwipeListener != null) {
if(mDeltaXTotal > 0)
mSwipeListener.onSwipeRight();
else mSwipeListener.onSwipeLeft();
}
mIsDragged = false;
mDeltaXTotal = 0;
break;
case MotionEvent.ACTION_MOVE:
float x = event.getX();
float y = event.getY();
float xDelta = Math.abs(x - mLastX);
float yDelta = Math.abs(y - mLastY);
mDeltaXTotal = x - mStartX;
if (!mIsDragged && xDelta > yDelta && Math.abs(mDeltaXTotal) > mTouchSlop) {
mIsDragged = true;
mStartX = x;
mDeltaXTotal = 0;
}
mLastX = x;
mLastY = y;
break;
}
return true;
}
}
How to verify the method onInterceptTouchEvent()
only returns true
in the case of MotionEvent.ACTION_MOVE
, because that’s all the movement we want to intercept.
The whole code comes down to some mathematics to know if the movement made should be considered as a Swipe and its direction.
Class declares the interface OnSwipeListener
with the methods onSwipeLeft()
and onSwipeRight()
that will be called when these movements are detected.
The class that implements them must be registered through the method setOnSwipeListenner()
.
Implementation
The implementation goes through, first put your layout within our Framelayout
<nome_da_sua_package.SwipeInterceptor xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/swipe">
<!-- coloque aqui o seu layout -->
</nome_da_sua_package.SwipeInterceptor>
and then implement the interface OnSwipeListener
.
One of the possible ways is to make your Activity implement it:
public class MainActivity extends Activity implements OnSwipeListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Obtém a referência ao SwipeInterceptor.
SwipeInterceptor swipe = (SwipeInterceptor)findViewById(R.id.swipe);
//Registra a nossa Activity para receber os eventos onSwipeLeft e onSwipeRight
swipe.setOnSwipeListenner(this);
}
// Declaração dos métodos da interface OnSwipeListener
@Override
public void onSwipeLeft() {
Toast.makeText(MainActivity.this, "Swipe Left", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeRight() {
Toast.makeText(MainActivity.this, "Swipe Right", Toast.LENGTH_SHORT).show();
}
}
Source of inspiration: Documentation of Android and this article.
I have a question this method is for which version of
Android
– Vale
I think it works in any version.
– ramaral
to think it works on API 11 and higher, needed to test on this API, to using genymotion but has this API.
– Vale
I don’t understand your doubt.
– ramaral
is that I needed this version of android to test, using genymotion that a great emulator to test the applications, so I asked a question about it but no one answered yet http://answall.com/questions/69598/como-installr-api-11-do-android-no-genymotion
– Vale
If the genymotion there’s nothing to do.
– ramaral
Regarding your answer how to use to keep changing layout example I have 3 layout while making the move to right it will change layout, time that end it repeats so the same to left
– Vale
Best to use one Viewpager
– ramaral