ユーザーが画面の任意の場所で右スワイプを提供したら、Activity
を終了する必要があります。私は GestureDetector
を試してみましたが、ScrollView
とRescyclerView
のどちらもActivity
とに存在しない場合は問題ありませんまた、onClickListener
のあるビューでは、スワイプを検出できません。そのため、ビューをすべての最上部のレイアウトにプログラムでオーバーレイして別の方法を試してから、その上でスワイプイベントを検出しようとしました。
_private void swipeOverToExit(ViewGroup rootView) {
OverlayLayout child = new OverlayLayout(this);
ViewGroup.LayoutParams layoutParams =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
child.setLayoutParams(layoutParams);
rootView.addView(child);
}
_
OverlayLayout
_public class OverlayLayout extends RelativeLayout {
private float x1, x2;
private final int MIN_DISTANCE = 150;
public OverlayLayout(Context context) {
super(context);
}
public OverlayLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.Lollipop)
public OverlayLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* logic there.
*/
final int action = MotionEventCompat.getActionMasked(event);
Logger.logD("Intercept===", action + "");
// Always handle the case of the touch gesture being complete.
if (action == MotionEvent.ACTION_DOWN) {
return true; // Intercept touch event, let the parent handle swipe
}
Logger.logD("===", "Out side" + action + "");
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
return false;
}
@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) {
Logger.logD("Swipe Right===", MIN_DISTANCE + "");
return true;
} else {
Logger.logD("Tap===", "Tap===");
return super.onTouchEvent(event);
}
}
return true;
}
}
_
ロジックは、OverlayLayout
に対してスワイプ操作が実行された場合に他のビューへのタッチイベントをインターセプトし、さらにActivity
に到達することです。しかし、OverlayLayout
でスワイプイベントを検出できるようになりましたが、onTouchEvent
のelse条件でreturn super.onTouchEvent(event);
を返しても、他のビューは応答しませんでした。私のコードにあります。どなたかご協力ください。私はここに固定されており、トリックを学ぶのにとても興奮しています:)
あなたがやろうとしていることは、基本的にAndroid Wearのデフォルトの動作であり、アプリを終了するための_Android Watches
_の標準的な方法と見なされます。 Android wear DismissOverlayView では、すべての重い作業が行われます。
スマートフォンには戻るボタンがありますが、Wearは画面を終了するために長押しまたはスワイプで閉じるパターンに依存しています。 Androidスマートフォンでウェアパターンを混合すると、バックプレスのアクティビティを却下する必要があります。スマートフォンはユーザーを混乱させます。少なくとも、誤って終了しないように警告ダイアログを表示してください。
ソリューション
私が見ると、この質問はAndroid Activity
でタグ付けされています。_Base Activityを作成して、ジェスチャーをスワイプし、finish()
自体を左から右にスワイプします。
基本アクティビティクラスは次のようになります。
_ public abstract class SwipeDismissBaseActivity extends AppCompatActivity {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gestureDetector = new GestureDetector(new SwipeDetector());
}
private class SwipeDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH,
// then dismiss the swipe.
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// Swipe from left to right.
// The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE)
// and a certain velocity (SWIPE_THRESHOLD_VELOCITY).
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
finish();
return true;
}
return false;
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TouchEvent dispatcher.
if (gestureDetector != null) {
if (gestureDetector.onTouchEvent(ev))
// If the gestureDetector handles the event, a swipe has been
// executed and no more needs to be done.
return true;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
}
_
これで、この基本アクティビティを拡張する他のアクティビティを作成できるようになり、
Inheritance
は自動的にスワイプを採用して動作を終了させます。
_public class SomeActivity extends SwipeDismissBaseActivity {
_
この方法の利点
このようにスワイプするためにFunctionを使用していますを試してください
スワイプするビュー...
yourview.setOnTouchListener(new SimpleGestureFilter(this)); // yourview is layout or container to swipe
SimpleGestureFilterクラス
public class SimpleGestureFilter implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
private Context activity;
static final int MIN_DISTANCE = 100;// TODO change this runtime based on screen resolution. for 1920x1080 is to small the 100 distance
private float downX, downY, upX, upY;
// private NDAAgreementActivity mMainActivity;
public SimpleGestureFilter(Context mainActivity) {
activity = mainActivity;
}
public void onRightToLeftSwipe() {
//do your code to right to left
}
public void onLeftToRightSwipe() {
//do your code to left to right
}
public void onTopToBottomSwipe() {
}
public void onBottomToTopSwipe() {
}
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;
// swipe horizontal?
if (Math.abs(deltaX) > MIN_DISTANCE) {
// left or right
if (deltaX < 0) {
this.onLeftToRightSwipe();
return true;
}
if (deltaX > 0) {
this.onRightToLeftSwipe();
return true;
}
} else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long horizontally, need at least " + MIN_DISTANCE);
// return false; // We don't consume the event
}
// swipe vertical?
if (Math.abs(deltaY) > MIN_DISTANCE) {
// top or down
if (deltaY < 0) {
this.onTopToBottomSwipe();
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe();
return true;
}
} else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long vertically, need at least " + MIN_DISTANCE);
// return false; // We don't consume the event
}
return false; // no swipe horizontally and no swipe vertically
}// case MotionEvent.ACTION_UP:
}
return false;
}
}
RecyclerViewとScrollViewで発生する問題は、子要素が親より先にフォーカスを取得することに関係していると思います。 Recycler/ScrollビューにAndroid:descendantFocusability="beforeDescendants"
を設定してみてください。
アクティビティオーバーレイについても同じ問題に直面しています。これは私のために働いた
1)SwipeListenerを定義する
public class SwipeListener implements View.OnTouchListener {
private SwipeListenerInterface activity;
private float downX, downY, upX, upY;
public SwipeListener(SwipeListenerInterface activity) {
this.activity = activity;
}
public void onRightToLeftSwipe(View v) {
Log.i(logTag, "RightToLeftSwipe!");
activity.onRightToLeftSwipe(v);
}
public void onLeftToRightSwipe(View v) {
Log.i(logTag, "LeftToRightSwipe!");
activity.onLeftToRightSwipe(v);
}
public void onTopToBottomSwipe(View v) {
Log.i(logTag, "TopToBottomSwipe!");
activity.onTopToBottomSwipe(v);
}
public void onBottomToTopSwipe(View v) {
Log.i(logTag, "BottomToTopSwipe!");
activity.onBottomToTopSwipe(v);
}
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;
if (deltaX < 0 ) {
this.onLeftToRightSwipe(v);
return true;
}
if (deltaX > 0 ) {
this.onRightToLeftSwipe(v);
return true;
}
if (deltaY < 0) {
this.onTopToBottomSwipe(v);
return true;
}
if (deltaY > 0) {
this.onBottomToTopSwipe(v);
return true;
}
}
}
return false;
}
public void setSwipeRestrictions(int swipeRestrictionX, int swipeRestrictionY) {
this.swipeRestrictionX = swipeRestrictionX;
this.swipeRestrictionY = swipeRestrictionY;
}
2)以下の参照インターフェースを使用
public interface SwipeListenerInterface {
void onRightToLeftSwipe(View v);
void onLeftToRightSwipe(View v);
void onTopToBottomSwipe(View v);
void onBottomToTopSwipe(View v);
}
3)オブジェクトを作成し、それをoverlayViewにバインドします(コールバックを受信できるように、必ずインターフェースをoverLayビューに調整してください)。
sl = new SwipeListener(this);
overlayView.setOnTouchListener(sl);
SwipeBack はAndroidライブラリはActivities
がAndroid "back-button "は機能しますが、スワイプジェスチャーを使用することで、非常に直感的な方法で実行できます。
Maven Centralから入手する
compile 'com.hannesdorfmann:swipeback:1.0.4'
基本アクティビティを作成し、メソッドを書き留めます
public void initDrawerSwipe(int layoutId) {
SwipeBack.attach(this, Position.LEFT)
.setContentView(layoutId)
.setSwipeBackView(R.layout.layout_swipe_back)
.setSwipeBackTransformer(new SlideSwipeBackTransformer() {
@Override
public void onSwipeBackCompleted(SwipeBack swipeBack, Activity activity) {
supportFinishAfterTransition();
}
});
}
その後、基本アクティビティに配置されたメソッドにレイアウトIDを渡します
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initDrawerSwipe(R.layout.activity_stylists);
}
これは、クエリで指摘したすべてのシナリオでうまく機能します。