グリッド レイアウトでのフリング ジェスチャ検出
-
06-09-2019 - |
質問
私は手に入れたい fling
私のAndroidアプリケーションで動作するジェスチャ検出。
私が持っているのは、 GridLayout
9が含まれています ImageView
s.ソースは次の場所にあります。 Romain Guys のグリッド レイアウト.
私が取ったそのファイルはRomain Guyのものです フォトストリームアプリケーション わずかに調整されているだけです。
単純なクリックの状況では、設定するだけで済みます。 onClickListener
それぞれに ImageView
私がメインになるように追加します activity
実装するもの View.OnClickListener
. 。を認識するものを実装するのは、無限に複雑に思えます。 fling
. 。これはまたがる可能性があるためだと思います views
?
私のアクティビティが実装された場合
OnGestureListener
それをジェスチャーリスナーとして設定する方法がわかりませんGrid
またはImage
私が追加するビュー。public class SelectFilterActivity extends Activity implements View.OnClickListener, OnGestureListener { ...
私のアクティビティが実装された場合
OnTouchListener
それなら私には何もありませんonFling
する方法override
(パラメーターとして2つのイベントがあり、Flingが注目に値するかどうかを判断できます)。public class SelectFilterActivity extends Activity implements View.OnClickListener, OnTouchListener { ...
カスタムしたら
View
, 、 のようにGestureImageView
それは伸びるImageView
アクティビティにそれを伝える方法がわかりません。fling
という視点から発生しました。いずれにせよ、これを試してみましたが、画面に触れてもメソッドは呼び出されませんでした。
本当に必要なのは、これが複数のビューにわたって機能する具体的な例です。これをいつ、何を、どのように添付すればよいですか listener
?シングルクリックも検出できる必要があります。
// Gesture detection
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
int dx = (int) (e2.getX() - e1.getX());
// don't accept the fling if it's too short
// as it may conflict with a button push
if (Math.abs(dx) > MAJOR_MOVE && Math.abs(velocityX) > Math.absvelocityY)) {
if (velocityX > 0) {
moveRight();
} else {
moveLeft();
}
return true;
} else {
return false;
}
}
});
フリングをキャプチャするために、画面の上部に透明なビューを配置することはできますか?
私がそうしないことを選択した場合 inflate
XML からの子画像ビューを渡すことはできますか? GestureDetector
の新しいサブクラスへのコンストラクター パラメーターとして ImageView
私が作るの?
これは私が取得しようとしている非常に単純なアクティビティです fling
機能する検出: SelectFilterActivity (フォトストリームから適応).
私はこれらのソースを見てきました:
これまでのところ何もうまくいかなかったので、いくつかのヒントを期待していました。
解決
のおかげでそのコードが、私は私の状況に適応将軍
で、ます。あなたの活動は通常通りimplementOnClickListener
してみましょう。
public class SelectFilterActivity extends Activity implements OnClickListener {
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;
View.OnTouchListener gestureListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* ... */
// Gesture detection
gestureDetector = new GestureDetector(this, new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// nothing
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
}
}
あなたがメインのレイアウトに追加するすべてのビューに、あなたのジェスチャーリスナーを取り付け;
// Do this for each view added to the grid
imageView.setOnClickListener(SelectFilterActivity.this);
imageView.setOnTouchListener(gestureListener);
あなたのオーバーライドされたメソッドがヒットしているように、、畏敬の念活動のonClick(View v)
とジェスチャーリスナーのonFling
両方をご覧ます。
public void onClick(View v) {
Filter f = (Filter) v.getTag();
FilterFullscreenActivity.show(this, input, f);
}
ポスト「情事」ダンスはオプションですが奨励されています。
他のヒント
上記の回答の一つは、異なる画素密度を取り扱う言及が、手でスワイプパラメータを計算示唆する。あなたが実際にViewConfiguration
クラスを使用して、システムからのスケーリングし、合理的な値を得ることができることは注目に値するます:
final ViewConfiguration vc = ViewConfiguration.get(getContext());
final int swipeMinDistance = vc.getScaledPagingTouchSlop();
final int swipeThresholdVelocity = vc.getScaledMinimumFlingVelocity();
final int swipeMaxOffPath = vc.getScaledTouchSlop();
// (there is also vc.getScaledMaximumFlingVelocity() one could check against)
私は、これらの値を使用すると、システムのアプリケーションと残りの部分との間、より一貫性が情事の「フィーリング」を引き起こすことに気づいています。
私はそれが少し異なるやる、とView.onTouchListener
を実装して、余分な検出器のクラスを書いた。
onCreate
isは、単純にこのような最低のレイアウトに追加します
ActivitySwipeDetector activitySwipeDetector = new ActivitySwipeDetector(this);
lowestLayout = (RelativeLayout)this.findViewById(R.id.lowestLayout);
lowestLayout.setOnTouchListener(activitySwipeDetector);
id.lowestLayoutビューレイアウト階層の最下位とlowestLayoutはRelativeLayout
のように宣言されているためであるid.xxxそして、実際の活動スワイプ検出器のクラスがあります:
public class ActivitySwipeDetector implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
private Activity activity;
static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
public ActivitySwipeDetector(Activity activity){
this.activity = activity;
}
public void onRightSwipe(){
Log.i(logTag, "RightToLeftSwipe!");
activity.doSomething();
}
public void onLeftSwipe(){
Log.i(logTag, "LeftToRightSwipe!");
activity.doSomething();
}
public void onDownSwipe(){
Log.i(logTag, "onTopToBottomSwipe!");
activity.doSomething();
}
public void onUpSwipe(){
Log.i(logTag, "onBottomToTopSwipe!");
activity.doSomething();
}
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) > Math.abs(deltaY))
{
if(Math.abs(deltaX) > MIN_DISTANCE){
// left or right
if(deltaX > 0) { this.onRightSwipe(); return true; }
if(deltaX < 0) { this.onLeftSwipe(); return true; }
}
else {
Log.i(logTag, "Horizontal Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
return false; // We don't consume the event
}
}
// swipe vertical?
else
{
if(Math.abs(deltaY) > MIN_DISTANCE){
// top or down
if(deltaY < 0) { this.onDownSwipe(); return true; }
if(deltaY > 0) { this.onUpSwipe(); return true; }
}
else {
Log.i(logTag, "Vertical Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
return false; // We don't consume the event
}
}
return true;
}
}
return false;
}
}
私にとって本当に良い作品!
のソリューションを少し変更して修復しました トーマス・ファンクハウザー
システム全体は 2 つのファイルで構成されます。 スワイプインターフェイス そして アクティビティスワイプ検出器
スワイプインターフェイス.java
import android.view.View;
public interface SwipeInterface {
public void bottom2top(View v);
public void left2right(View v);
public void right2left(View v);
public void top2bottom(View v);
}
検出器
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class ActivitySwipeDetector implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
private SwipeInterface activity;
static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
public ActivitySwipeDetector(SwipeInterface activity){
this.activity = activity;
}
public void onRightToLeftSwipe(View v){
Log.i(logTag, "RightToLeftSwipe!");
activity.right2left(v);
}
public void onLeftToRightSwipe(View v){
Log.i(logTag, "LeftToRightSwipe!");
activity.left2right(v);
}
public void onTopToBottomSwipe(View v){
Log.i(logTag, "onTopToBottomSwipe!");
activity.top2bottom(v);
}
public void onBottomToTopSwipe(View v){
Log.i(logTag, "onBottomToTopSwipe!");
activity.bottom2top(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;
// swipe horizontal?
if(Math.abs(deltaX) > MIN_DISTANCE){
// left or right
if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; }
if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; }
}
else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
}
// swipe vertical?
if(Math.abs(deltaY) > MIN_DISTANCE){
// top or down
if(deltaY < 0) { this.onTopToBottomSwipe(v); return true; }
if(deltaY > 0) { this.onBottomToTopSwipe(v); return true; }
}
else {
Log.i(logTag, "Swipe was only " + Math.abs(deltaX) + " long, need at least " + MIN_DISTANCE);
v.performClick();
}
}
}
return false;
}
}
次のように使用されます。
ActivitySwipeDetector swipe = new ActivitySwipeDetector(this);
LinearLayout swipe_layout = (LinearLayout) findViewById(R.id.swipe_layout);
swipe_layout.setOnTouchListener(swipe);
そして実装にあたっては Activity
からのメソッドを実装する必要があります スワイプインターフェイス, 、どのビューで スワイプイベント と呼ばれていました。
@Override
public void left2right(View v) {
switch(v.getId()){
case R.id.swipe_layout:
// do your stuff here
break;
}
}
上記のスワイプジェスチャー検出コードは非常に便利です!ただし、次の相対値は、絶対値ではなく、(REL_SWIPE)
(SWIPE_)
使用して、このソリューション密度はとらわれないようにしたいことがあります。
DisplayMetrics dm = getResources().getDisplayMetrics();
int REL_SWIPE_MIN_DISTANCE = (int)(SWIPE_MIN_DISTANCE * dm.densityDpi / 160.0f);
int REL_SWIPE_MAX_OFF_PATH = (int)(SWIPE_MAX_OFF_PATH * dm.densityDpi / 160.0f);
int REL_SWIPE_THRESHOLD_VELOCITY = (int)(SWIPE_THRESHOLD_VELOCITY * dm.densityDpi / 160.0f);
によって提案された私のバージョンのソリューション トーマス・ファンクハウザー そして マレク・セベラ (垂直スワイプは処理しません):
スワイプインターフェイス.java
import android.view.View;
public interface SwipeInterface {
public void onLeftToRight(View v);
public void onRightToLeft(View v);
}
アクティビティスワイプ検出器.java
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
public class ActivitySwipeDetector implements View.OnTouchListener {
static final String logTag = "ActivitySwipeDetector";
private SwipeInterface activity;
private float downX, downY;
private long timeDown;
private final float MIN_DISTANCE;
private final int VELOCITY;
private final float MAX_OFF_PATH;
public ActivitySwipeDetector(Context context, SwipeInterface activity){
this.activity = activity;
final ViewConfiguration vc = ViewConfiguration.get(context);
DisplayMetrics dm = context.getResources().getDisplayMetrics();
MIN_DISTANCE = vc.getScaledPagingTouchSlop() * dm.density;
VELOCITY = vc.getScaledMinimumFlingVelocity();
MAX_OFF_PATH = MIN_DISTANCE * 2;
}
public void onRightToLeftSwipe(View v){
Log.i(logTag, "RightToLeftSwipe!");
activity.onRightToLeft(v);
}
public void onLeftToRightSwipe(View v){
Log.i(logTag, "LeftToRightSwipe!");
activity.onLeftToRight(v);
}
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN: {
Log.d("onTouch", "ACTION_DOWN");
timeDown = System.currentTimeMillis();
downX = event.getX();
downY = event.getY();
return true;
}
case MotionEvent.ACTION_UP: {
Log.d("onTouch", "ACTION_UP");
long timeUp = System.currentTimeMillis();
float upX = event.getX();
float upY = event.getY();
float deltaX = downX - upX;
float absDeltaX = Math.abs(deltaX);
float deltaY = downY - upY;
float absDeltaY = Math.abs(deltaY);
long time = timeUp - timeDown;
if (absDeltaY > MAX_OFF_PATH) {
Log.i(logTag, String.format("absDeltaY=%.2f, MAX_OFF_PATH=%.2f", absDeltaY, MAX_OFF_PATH));
return v.performClick();
}
final long M_SEC = 1000;
if (absDeltaX > MIN_DISTANCE && absDeltaX > time * VELOCITY / M_SEC) {
if(deltaX < 0) { this.onLeftToRightSwipe(v); return true; }
if(deltaX > 0) { this.onRightToLeftSwipe(v); return true; }
} else {
Log.i(logTag, String.format("absDeltaX=%.2f, MIN_DISTANCE=%.2f, absDeltaX > MIN_DISTANCE=%b", absDeltaX, MIN_DISTANCE, (absDeltaX > MIN_DISTANCE)));
Log.i(logTag, String.format("absDeltaX=%.2f, time=%d, VELOCITY=%d, time*VELOCITY/M_SEC=%d, absDeltaX > time * VELOCITY / M_SEC=%b", absDeltaX, time, VELOCITY, time * VELOCITY / M_SEC, (absDeltaX > time * VELOCITY / M_SEC)));
}
}
}
return false;
}
}
この質問は少し古いもので、2011 年 7 月に Google がリリースしました。 互換性パッケージ、リビジョン 3) これには、 ViewPager
Android 1.6以降で動作します。の GestureListener
この質問に対して投稿された回答は、Android ではあまりエレガントとは思えません。Android ギャラリーで写真を切り替えたり、新しい Play マーケット アプリでビューを切り替えたりするために使用されるコードを探している場合は、間違いなくそれが見つかります。 ViewPager
.
詳細については、次のリンクを参照してください。
あなたはすべてのジェスチャーのために直接使用することができます内蔵のインタフェースがあります:
ここでは、基本的なレベルのユーザーのための説明は次のとおりです。する
2つの輸入は両方がdiferentであることを選択する際に注意することがあります
Web (およびこのページ) には、ViewConfiguration を使用するという提案があります。getScaledTouchSlop() デバイススケールの値を取得するには SWIPE_MIN_DISTANCE
.
getScaledTouchSlop()
を対象としています。スクロール スワイプではなく、「しきい値」距離。スクロールのしきい値距離は、「ページ間のスイング」しきい値距離より小さくなければなりません。たとえば、この関数は私の Samsung GS2 では 12 ピクセルを返しますが、このページで引用されている例は約 100 ピクセルです。
API レベル 8 (Android 2.2、Froyo) では、次のことが可能になります。 getScaledPagingTouchSlop()
, 、ページのスワイプを目的としています。私のデバイスでは、24 (ピクセル) が返されます。したがって、API レベルが 8 未満の場合は、「2 *」と考えます。 getScaledTouchSlop()
」を「標準」スワイプしきい値にする必要があります。しかし、画面が小さい私のアプリケーションのユーザーからは、数が少なすぎると言われました...私のアプリケーションと同様に、垂直方向にスクロールしたり、水平方向にページを変更したりできます。提案された値では、スクロールせずにページが変更されることがあります。
またマイナー強化など。
try / catchブロックの主な理由は、E1は初期動作のためにnullになるかもしれないということです。 try / catchに加えて、ヌルとリターンのためのテストが含まれています。 次のような
if (e1 == null || e2 == null) return false;
try {
...
} catch (Exception e) {}
return false;
ここには素晴らしい情報がたくさんあります。残念なことに、このフリング処理コードの多くは、これが多くのアプリケーションにとって不可欠であると思われているにもかかわらず、さまざまな完成状態でさまざまなサイトに散在しています。
時間をかけて作成しました 投げリスナー 適切な条件が満たされていることを確認します。を追加しました ページフリングリスナー これにより、フリングがページフリングのしきい値を満たしていることを確認するためのチェックがさらに追加されます。これらのリスナーは両方とも、フリングを水平軸または垂直軸に簡単に制限できます。でどのように使用されているかを見ることができます。 スライド画像のビュー. 。ここの人々がほとんどの研究を行ったことを認めます。私はそれを使用可能なライブラリにまとめただけです。
ここ数日は、Android でのコーディングに初めて挑戦したときのことです。期待する もっともっと 来ること。
これは誰もが作業実施を望んでいる場合は、上部の2つの答えの組み合わせ答えです。
package com.yourapplication;
import android.content.Context;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
public abstract class OnSwipeListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeListener(Context context){
gestureDetector = new GestureDetector(context, new OnSwipeGestureListener(context));
gestureDetector.setIsLongpressEnabled(false);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class OnSwipeGestureListener extends GestureDetector.SimpleOnGestureListener {
private final int minSwipeDelta;
private final int minSwipeVelocity;
private final int maxSwipeVelocity;
private OnSwipeGestureListener(Context context) {
ViewConfiguration configuration = ViewConfiguration.get(context);
// We think a swipe scrolls a full page.
//minSwipeDelta = configuration.getScaledTouchSlop();
minSwipeDelta = configuration.getScaledPagingTouchSlop();
minSwipeVelocity = configuration.getScaledMinimumFlingVelocity();
maxSwipeVelocity = configuration.getScaledMaximumFlingVelocity();
}
@Override
public boolean onDown(MotionEvent event) {
// Return true because we want system to report subsequent events to us.
return true;
}
// NOTE: see http://stackoverflow.com/questions/937313/android-basic-gesture-detection
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX,
float velocityY) {
boolean result = false;
try {
float deltaX = event2.getX() - event1.getX();
float deltaY = event2.getY() - event1.getY();
float absVelocityX = Math.abs(velocityX);
float absVelocityY = Math.abs(velocityY);
float absDeltaX = Math.abs(deltaX);
float absDeltaY = Math.abs(deltaY);
if (absDeltaX > absDeltaY) {
if (absDeltaX > minSwipeDelta && absVelocityX > minSwipeVelocity
&& absVelocityX < maxSwipeVelocity) {
if (deltaX < 0) {
onSwipeLeft();
} else {
onSwipeRight();
}
}
result = true;
} else if (absDeltaY > minSwipeDelta && absVelocityY > minSwipeVelocity
&& absVelocityY < maxSwipeVelocity) {
if (deltaY < 0) {
onSwipeTop();
} else {
onSwipeBottom();
}
}
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
public void onSwipeLeft() {}
public void onSwipeRight() {}
public void onSwipeTop() {}
public void onSwipeBottom() {}
}
使用できます ドロイドクエリ フリング、クリック、ロングクリック、カスタム イベントを処理するライブラリ。実装は以下の私の以前の回答に基づいて構築されていますが、 ドロイドクエリ 洗練されたシンプルな構文を提供します。
//global variables private boolean isSwiping = false;
private SwipeDetector.Direction swipeDirection = null;
private View v;//must be instantiated before next call.
//swipe-handling code
$.with(v).swipe(new Function() {
@Override
public void invoke($ droidQuery, Object... params) {
if (params[0] == SwipeDetector.Direction.START)
isSwiping = true;
else if (params[0] == SwipeDetector.Direction.STOP) {
if (isSwiping) { isSwiping = false;
if (swipeDirection != null) {
switch(swipeDirection) {
case DOWN : //TODO: Down swipe complete, so do something
break;
case UP :
//TODO: Up swipe complete, so do something
break;
case LEFT :
//TODO: Left swipe complete, so do something
break;
case RIGHT :
//TODO: Right swipe complete, so do something
break;
default : break;
}
} }
}
else {
swipeDirection = (SwipeDetector.Direction) params[0];
}
}
});
元の回答
この回答では、他の回答のコンポーネントを組み合わせて使用します。で構成されています。 SwipeDetector
このクラスには、イベントをリッスンするための内部インターフェイスがあります。私も提供しています RelativeLayout
をオーバーライドする方法を示します View
さんの onTouch
スワイプ イベントとその他の検出されたイベント (クリックやロングクリックなど) の両方を許可するメソッド。
スワイプディテクター
package self.philbrown;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
/**
* Detect Swipes on a per-view basis. Based on original code by Thomas Fankhauser on StackOverflow.com,
* with adaptations by other authors (see link).
* @author Phil Brown
* @see <a href="http://stackoverflow.com/questions/937313/android-basic-gesture-detection">android-basic-gesture-detection</a>
*/
public class SwipeDetector implements View.OnTouchListener
{
/**
* The minimum distance a finger must travel in order to register a swipe event.
*/
private int minSwipeDistance;
/** Maintains a reference to the first detected down touch event. */
private float downX, downY;
/** Maintains a reference to the first detected up touch event. */
private float upX, upY;
/** provides access to size and dimension contants */
private ViewConfiguration config;
/**
* provides callbacks to a listener class for various swipe gestures.
*/
private SwipeListener listener;
public SwipeDetector(SwipeListener listener)
{
this.listener = listener;
}
/**
* {@inheritDoc}
*/
public boolean onTouch(View v, MotionEvent event)
{
if (config == null)
{
config = ViewConfiguration.get(v.getContext());
minSwipeDistance = config.getScaledTouchSlop();
}
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) > minSwipeDistance)
{
// left or right
if (deltaX < 0)
{
if (listener != null)
{
listener.onRightSwipe(v);
return true;
}
}
if (deltaX > 0)
{
if (listener != null)
{
listener.onLeftSwipe(v);
return true;
}
}
}
// swipe vertical?
if(Math.abs(deltaY) > minSwipeDistance)
{
// top or down
if (deltaY < 0)
{
if (listener != null)
{
listener.onDownSwipe(v);
return true;
}
}
if (deltaY > 0)
{
if (listener != null)
{
listener.onUpSwipe(v);
return true;
}
}
}
}
return false;
}
/**
* Provides callbacks to a registered listener for swipe events in {@link SwipeDetector}
* @author Phil Brown
*/
public interface SwipeListener
{
/** Callback for registering a new swipe motion from the bottom of the view toward its top. */
public void onUpSwipe(View v);
/** Callback for registering a new swipe motion from the left of the view toward its right. */
public void onRightSwipe(View v);
/** Callback for registering a new swipe motion from the right of the view toward its left. */
public void onLeftSwipe(View v);
/** Callback for registering a new swipe motion from the top of the view toward its bottom. */
public void onDownSwipe(View v);
}
}
スワイプインターセプタービュー
package self.philbrown;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
import com.npeinc.module_NPECore.model.SwipeDetector;
import com.npeinc.module_NPECore.model.SwipeDetector.SwipeListener;
/**
* View subclass used for handling all touches (swipes and others)
* @author Phil Brown
*/
public class SwipeInterceptorView extends RelativeLayout
{
private SwipeDetector swiper = null;
public void setSwipeListener(SwipeListener listener)
{
if (swiper == null)
swiper = new SwipeDetector(listener);
}
public SwipeInterceptorView(Context context) {
super(context);
}
public SwipeInterceptorView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeInterceptorView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent e)
{
boolean swipe = false, touch = false;
if (swiper != null)
swipe = swiper.onTouch(this, e);
touch = super.onTouchEvent(e);
return swipe || touch;
}
}
答えるには遅すぎることはわかっていますが、それでも投稿しています ListView のスワイプ検出 その使い方 ListView 項目のスワイプ タッチ リスナー.
参考:Exterminator13(このページの回答の 1 つ)
一つ作ってください ActivitySwipeDetector.class
package com.example.wocketapp;
import android.content.Context;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
public class ActivitySwipeDetector implements View.OnTouchListener
{
static final String logTag = "SwipeDetector";
private SwipeInterface activity;
private float downX, downY;
private long timeDown;
private final float MIN_DISTANCE;
private final int VELOCITY;
private final float MAX_OFF_PATH;
public ActivitySwipeDetector(Context context, SwipeInterface activity)
{
this.activity = activity;
final ViewConfiguration vc = ViewConfiguration.get(context);
DisplayMetrics dm = context.getResources().getDisplayMetrics();
MIN_DISTANCE = vc.getScaledPagingTouchSlop() * dm.density;
VELOCITY = vc.getScaledMinimumFlingVelocity();
MAX_OFF_PATH = MIN_DISTANCE * 2;
}
public void onRightToLeftSwipe(View v)
{
Log.i(logTag, "RightToLeftSwipe!");
activity.onRightToLeft(v);
}
public void onLeftToRightSwipe(View v)
{
Log.i(logTag, "LeftToRightSwipe!");
activity.onLeftToRight(v);
}
public boolean onTouch(View v, MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
Log.d("onTouch", "ACTION_DOWN");
timeDown = System.currentTimeMillis();
downX = event.getX();
downY = event.getY();
v.getParent().requestDisallowInterceptTouchEvent(false);
return true;
}
case MotionEvent.ACTION_MOVE:
{
float y_up = event.getY();
float deltaY = y_up - downY;
float absDeltaYMove = Math.abs(deltaY);
if (absDeltaYMove > 60)
{
v.getParent().requestDisallowInterceptTouchEvent(false);
}
else
{
v.getParent().requestDisallowInterceptTouchEvent(true);
}
}
break;
case MotionEvent.ACTION_UP:
{
Log.d("onTouch", "ACTION_UP");
long timeUp = System.currentTimeMillis();
float upX = event.getX();
float upY = event.getY();
float deltaX = downX - upX;
float absDeltaX = Math.abs(deltaX);
float deltaY = downY - upY;
float absDeltaY = Math.abs(deltaY);
long time = timeUp - timeDown;
if (absDeltaY > MAX_OFF_PATH)
{
Log.e(logTag, String.format(
"absDeltaY=%.2f, MAX_OFF_PATH=%.2f", absDeltaY,
MAX_OFF_PATH));
return v.performClick();
}
final long M_SEC = 1000;
if (absDeltaX > MIN_DISTANCE && absDeltaX > time * VELOCITY / M_SEC)
{
v.getParent().requestDisallowInterceptTouchEvent(true);
if (deltaX < 0)
{
this.onLeftToRightSwipe(v);
return true;
}
if (deltaX > 0)
{
this.onRightToLeftSwipe(v);
return true;
}
}
else
{
Log.i(logTag,
String.format(
"absDeltaX=%.2f, MIN_DISTANCE=%.2f, absDeltaX > MIN_DISTANCE=%b",
absDeltaX, MIN_DISTANCE,
(absDeltaX > MIN_DISTANCE)));
Log.i(logTag,
String.format(
"absDeltaX=%.2f, time=%d, VELOCITY=%d, time*VELOCITY/M_SEC=%d, absDeltaX > time * VELOCITY / M_SEC=%b",
absDeltaX, time, VELOCITY, time * VELOCITY
/ M_SEC, (absDeltaX > time * VELOCITY
/ M_SEC)));
}
v.getParent().requestDisallowInterceptTouchEvent(false);
}
}
return false;
}
public interface SwipeInterface
{
public void onLeftToRight(View v);
public void onRightToLeft(View v);
}
}
次のようにアクティビティ クラスから呼び出します。
yourLayout.setOnTouchListener(new ActivitySwipeDetector(this, your_activity.this));
そして忘れないでください 埋め込む スワイプインターフェイス これにより、2 つの @override メソッドが提供されます。
@Override
public void onLeftToRight(View v)
{
Log.e("TAG", "L to R");
}
@Override
public void onRightToLeft(View v)
{
Log.e("TAG", "R to L");
}
ジェスチャは、タッチスクリーンとユーザとの間の相互作用を誘発するそれらの微妙な動きです。それは最後の指が表面を離れた地点に、画面上の最初のタッチの間の時間持続します。
Androidのは、使用して GestureDetector に呼ばれるクラスを提供してくれた私達ができますのがダウンタップし、アップ、垂直方向と水平方向(情事)をスワイプなどの一般的なジェスチャー、ロングとショートプレス、ダブルタップなどを検出します。そしてそれらにリスナーを添付。
私たちの活動クラスが(ためGestureDetector.OnDoubleTapListener を実装してくださいそして、すべての実装をダブルタップジェスチャーの検出)と GestureDetector.OnGestureListenerインターフェース抽象methods.For詳細。あなたは https://developer.android.com/training/gestures/detector.html <訪問するかもしれません/>。 礼儀の
のデモ試験。 GestureDetectorDemo の
あなたは
、別のクラスを作成したり、コード複合体を作るのが好きいけない場合
あなただけのOnTouchListener内GestureDetector変数を作成し、
namVyuVarはあなたのリスナーを設定する必要のあるビューの任意の名前を指定できます。
namVyuVar.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View view, MotionEvent MsnEvtPsgVal)
{
flingActionVar.onTouchEvent(MsnEvtPsgVal);
return true;
}
GestureDetector flingActionVar = new GestureDetector(getApplicationContext(), new GestureDetector.SimpleOnGestureListener()
{
private static final int flingActionMinDstVac = 120;
private static final int flingActionMinSpdVac = 200;
@Override
public boolean onFling(MotionEvent fstMsnEvtPsgVal, MotionEvent lstMsnEvtPsgVal, float flingActionXcoSpdPsgVal, float flingActionYcoSpdPsgVal)
{
if(fstMsnEvtPsgVal.getX() - lstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
{
// TskTdo :=> On Right to Left fling
return false;
}
else if (lstMsnEvtPsgVal.getX() - fstMsnEvtPsgVal.getX() > flingActionMinDstVac && Math.abs(flingActionXcoSpdPsgVal) > flingActionMinSpdVac)
{
// TskTdo :=> On Left to Right fling
return false;
}
if(fstMsnEvtPsgVal.getY() - lstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
{
// TskTdo :=> On Bottom to Top fling
return false;
}
else if (lstMsnEvtPsgVal.getY() - fstMsnEvtPsgVal.getY() > flingActionMinDstVac && Math.abs(flingActionYcoSpdPsgVal) > flingActionMinSpdVac)
{
// TskTdo :=> On Top to Bottom fling
return false;
}
return false;
}
});
});
皆様へ:忘れないでください ケース MotionEvent.ACTION_CANCEL:
ACTION_UP なしで 30% のスワイプを呼び出します
この場合は ACTION_UP と同じです
私はトーマスのクラスを取って、自分の活動やフラグメントにイベントを送信するインターフェイスを追加し、より一般的なクラスをnedded。 それはあなたがインターフェイスを実装してくださいコンストラクタ上のリスナーを登録しますかClassCastExceptionがthorwnされます。インタフェースは、定義された4つの最終的な整数のいずれかを返します そして、クラスでそれをすると活性化されたビューを返します。
import android.app.Activity;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class SwipeDetector implements View.OnTouchListener{
static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
public final static int RIGHT_TO_LEFT=1;
public final static int LEFT_TO_RIGHT=2;
public final static int TOP_TO_BOTTOM=3;
public final static int BOTTOM_TO_TOP=4;
private View v;
private onSwipeEvent swipeEventListener;
public SwipeDetector(Activity activity,View v){
try{
swipeEventListener=(onSwipeEvent)activity;
}
catch(ClassCastException e)
{
Log.e("ClassCastException",activity.toString()+" must implement SwipeDetector.onSwipeEvent");
}
this.v=v;
}
public SwipeDetector(Fragment fragment,View v){
try{
swipeEventListener=(onSwipeEvent)fragment;
}
catch(ClassCastException e)
{
Log.e("ClassCastException",fragment.toString()+" must implement SwipeDetector.onSwipeEvent");
}
this.v=v;
}
public void onRightToLeftSwipe(){
swipeEventListener.SwipeEventDetected(v,RIGHT_TO_LEFT);
}
public void onLeftToRightSwipe(){
swipeEventListener.SwipeEventDetected(v,LEFT_TO_RIGHT);
}
public void onTopToBottomSwipe(){
swipeEventListener.SwipeEventDetected(v,TOP_TO_BOTTOM);
}
public void onBottomToTopSwipe(){
swipeEventListener.SwipeEventDetected(v,BOTTOM_TO_TOP);
}
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 , int SwipeType);
}
}