70

ダブルタップの実装に問題があります。を実装しましたonGestureListenergestureDetector、どこに問題があるのか​​わかりません。コードは次のとおりです。

 public class home extends TabActivity implements OnGestureListener {
    /** Called when the activity is first created. */

 private EditText queryText;
 private ResultsAdapter m_adapter;
 private ProgressDialog pd;
 final Handler h = new Handler();
 private TabHost mTabHost;
 private ArrayList<SearchItem> sResultsArr = new ArrayList<SearchItem>();
 private String queryStr;
 private JSONObject searchResponse;
 private GestureDetector gestureScanner;

 final Runnable mUpdateResults = new Runnable() {
        public void run() {
         updateListUi();
        }
    };

 @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button search = (Button)findViewById(R.id.search);
        Button testButt = (Button)findViewById(R.id.testbutt);
        queryText = (EditText)findViewById(R.id.query);
        ListView lvr = (ListView)findViewById(R.id.search_results);

      //initialise the arrayAdapter
        this.m_adapter = new ResultsAdapter(home.this, R.layout.listrow, sResultsArr);
        lvr.setAdapter(this.m_adapter);
        lvr.setOnItemClickListener(new OnItemClickListener(){
   @Override
   public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
     long arg3) {
    // TODO Auto-generated method stub
         pd = ProgressDialog.show(home.this, null,"Loading products from server", true, false);

   }

        });
        gestureScanner = new GestureDetector(this,this);
        gestureScanner.setOnDoubleTapListener(new OnDoubleTapListener(){ 
            public boolean onDoubleTap(MotionEvent e) { 
                 //viewA.setText("-" + "onDoubleTap" + "-"); 
         pd = ProgressDialog.show(home.this, null,"Loading products from server", true, false);

                 return false; 
            } 
            public boolean onDoubleTapEvent(MotionEvent e) { 
                // viewA.setText("-" + "onDoubleTapEvent" + "-"); 
                 return false; 
            } 
            public boolean onSingleTapConfirmed(MotionEvent e) { 
                 //viewA.setText("-" + "onSingleTapConfirmed" + "-"); 
                 return false; 
            } 

     });


        //initialise tab contents
        mTabHost = getTabHost();
        mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Home").setContent(R.id.homepage));
        mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Search Results").setContent(R.id.tab2));
        mTabHost.setCurrentTab(0);

        //sets the respective listeners
        testButt.setOnClickListener(new View.OnClickListener() {
        public void onClick(View arg0) {

         if(mTabHost.getTabWidget().getVisibility()==View.GONE){
          mTabHost.getTabWidget().setVisibility(View.VISIBLE);
         }
         else{
          mTabHost.getTabWidget().setVisibility(View.GONE);
         }
        }
     });

        search.setOnClickListener(new View.OnClickListener() {
        public void onClick(View arg0) {
         sResultsArr.clear();
         queryStr = "http://rose.mosuma.com/mobile?query=" + queryText.getText().toString();
         pd = ProgressDialog.show(home.this, null,"Loading products from server", true, false);
         goSearch();
      }
     });
    }

 //updates the listUI whenever after receiving the response from the server
 public void updateListUi(){  
    if(sResultsArr.size() > 0){

       }

    try{
     String ptypename;
     int count;
     LinearLayout ptypebar = (LinearLayout)findViewById(R.id.productCat);
     ptypebar.removeAllViews();
     JSONArray ptypes = searchResponse.getJSONArray("ptypes"); 
     for(int index =0;index < ptypes.length();index++){
      JSONObject ptype = ptypes.getJSONObject(index);
      count = ptype.getInt("count");      
      ptypename = ptype.getString("ptypename"); 

      //add into tab 2's UI

      //ImageView icon = new ImageView(this);
      TextView t = new TextView(home.this);
      t.setText(ptypename + " (" + count + ")");
      ptypebar.addView(t);
     }
    }
    catch(JSONException e){

    }
   //if(m_adapter.getItems() != sResultsArr){
    ArrayList<SearchItem> a  = m_adapter.getItems(); 
    a = sResultsArr;
   //}
      m_adapter.notifyDataSetChanged();
     pd.dismiss();
 }

 public void goSearch(){
  mTabHost.setCurrentTab(1);

  //separate thread for making http request and updating the arraylist
  Thread t = new Thread() {
           public void run() {

            searchResponse = sendSearchQuery(queryStr);
            try{
             JSONArray results = searchResponse.getJSONArray("results");

             //this is stupid. i probably have to see how to make a json adapter
             for(int index =0;index < results.length();index++){

              JSONObject product = results.getJSONObject(index);

              //gets the searched products from the json object
              URL imgUrl =  new URL(product.getString("image"));
              String productname = product.getString("productname");
              String ptypename = product.getString("ptypename");
              int pid = product.getInt("pid");
              int positive = product.getInt("pos");
              int negative = product.getInt("neg");
              int neutral = product.getInt("neu");


              SearchItem item  = new SearchItem(imgUrl,productname,ptypename,neutral,positive,negative,pid);
              sResultsArr.add(item);
             }
            }
            catch(JSONException e){

            }
            catch(Exception e){

               }
            //returns back to UI therad
            h.post(mUpdateResults);
           }
       };
       t.start();
 }

 //sends a request with qry as URL
 //and receives back a JSONobject as response
 public JSONObject sendSearchQuery(String qry){
  HttpRequest r = new HttpRequest();
  JSONObject response = r.sendHttpRequest(qry);  
  return response;
 }

 @Override
 public boolean onDown(MotionEvent arg0) {
      return gestureScanner.onTouchEvent(arg0); 
 }

 @Override
 public boolean onFling(MotionEvent arg0, MotionEvent arg1, float arg2,
   float arg3) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 public void onLongPress(MotionEvent arg0) {
  // TODO Auto-generated method stub

 }

 @Override
 public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
   float arg3) {
  // TODO Auto-generated method stub
  return false;
 }

 @Override
 public void onShowPress(MotionEvent arg0) {
  // TODO Auto-generated method stub

 }

 @Override
 public boolean onSingleTapUp(MotionEvent arg0) {
  // TODO Auto-generated method stub
  return false;
 }

ああ、別の質問ですが、私ListViewが持っている場合、 onItemClickListenerAndroidはシングルタップまたはダブルタップの間でそれを検出できますか?

4

25 に答える 25

115

GestureDetectorを使用できます。次のコードを参照してください。

public class MyView extends View {

    GestureDetector gestureDetector;

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
                // creating new gesture detector
        gestureDetector = new GestureDetector(context, new GestureListener());
    }

    // skipping measure calculation and drawing

        // delegate the event to the gesture detector
    @Override
    public boolean onTouchEvent(MotionEvent e) {
        return gestureDetector.onTouchEvent(e);
    }


    private class GestureListener extends GestureDetector.SimpleOnGestureListener {

        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
        // event when double tap occurs
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            float x = e.getX();
            float y = e.getY();

            Log.d("Double Tap", "Tapped at: (" + x + "," + y + ")");

            return true;
        }
    }
}

リスナーの他のメソッドをオーバーライドして、シングルタップやフリンジなどを取得できます。

于 2011-06-09T08:28:12.330 に答える
73

GestureDetectorの軽量な代替手段として、このクラスを使用できます

public abstract class DoubleClickListener implements OnClickListener {

    private static final long DOUBLE_CLICK_TIME_DELTA = 300;//milliseconds

    long lastClickTime = 0;

    @Override
    public void onClick(View v) {
        long clickTime = System.currentTimeMillis();
        if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){
            onDoubleClick(v);
        } else {
            onSingleClick(v);
        }
        lastClickTime = clickTime;
    }

    public abstract void onSingleClick(View v);
    public abstract void onDoubleClick(View v);
}

例:

    view.setOnClickListener(new DoubleClickListener() {

        @Override
        public void onSingleClick(View v) {

        }

        @Override
        public void onDoubleClick(View v) {

        }
    });
于 2014-02-13T20:08:44.550 に答える
23

なぜロングプレスを使わないのですか?それとも、すでにそれを他の何かに使用していますか?ダブルタッチに対する長押しの利点:

  • 長押しはUIガイドラインで推奨される操作ですが、ダブルタッチはそうではありません。
  • それはユーザーが期待するものです。ユーザーはダブルタッチアクションを探しに行かないため、見つけられない可能性があります
  • すでにAPIで処理されています
  • ダブルタッチを実装すると、シングルタッチの処理に影響します。これは、すべてのシングルタッチがダブルタッチに変わるかどうかを確認してから処理する必要があるためです。
于 2010-02-07T21:19:19.773 に答える
16

「Bughi」、「DoubleClickListner」、「JayantArora」タイマーを1つの含まれるクラスに組み合わせます。

public abstract class DoubleClickListener implements OnClickListener {

    private Timer timer = null;  //at class level;
    private int DELAY   = 400;

    private static final long DOUBLE_CLICK_TIME_DELTA = 300;//milliseconds

    long lastClickTime = 0;

    @Override
    public void onClick(View v) {
        long clickTime = System.currentTimeMillis();
        if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){
            processDoubleClickEvent(v);
        } else {
            processSingleClickEvent(v);
        }
        lastClickTime = clickTime;
    }



    public void processSingleClickEvent(final View v){

        final Handler handler=new Handler();
        final Runnable mRunnable=new Runnable(){
            public void run(){
                onSingleClick(v); //Do what ever u want on single click

            }
        };

        TimerTask timertask=new TimerTask(){
            @Override
            public void run(){
                handler.post(mRunnable);
            }
        };
        timer=new Timer();
        timer.schedule(timertask,DELAY);

    }

    public void processDoubleClickEvent(View v){
        if(timer!=null)
        {
            timer.cancel(); //Cancels Running Tasks or Waiting Tasks.
            timer.purge();  //Frees Memory by erasing cancelled Tasks.
        }
        onDoubleClick(v);//Do what ever u want on Double Click
    }

    public abstract void onSingleClick(View v);

    public abstract void onDoubleClick(View v);
}

と呼ぶことができます:

view.setOnClickListener(new DoubleClickListener() {

            @Override
            public void onSingleClick(View v) {

            }

            @Override
            public void onDoubleClick(View v) {

            }
        });
于 2016-11-15T18:22:54.867 に答える
8

カスタムビューを使用したくない場合は、次の方法を使用できます。例:ImageView

// class level

GestureDetector gestureDetector;
boolean tapped;
ImageView imageView;

// inside onCreate of Activity or Fragment
gestureDetector = new GestureDetector(context,new GestureListener());

// ------------------------------------------------ --------------------------------

public class GestureListener extends
        GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {

        return true;
    }

    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) {

        tapped = !tapped;

        if (tapped) {



        } else {



        }

        return true;
    }
}

// ------------------------------------------------ --------------------------------

ImageViewの場合

imageView.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            return gestureDetector.onTouchEvent(event);
        }

    });
于 2013-04-26T09:13:52.423 に答える
4

これは私の解決策であり、デフォルトを使用しますsetOnItemClickListener()。実装するのと同じタスクがありました。すぐに、例とカスタムクラスをgithubに投稿します。簡単な説明があります。ViewConfiguration.getDoubleTapTimeout()システム(ソースを参照)がシングルタップとダブルタップのどちらを使用するかを決定するのに 、ミリ秒単位の時間が正しいかどうかはわかりません。

編集: こちらをご覧ください: https ://github.com/NikolaDespotoski/DoubleTapListViewまたは https://github.com/NikolaDespotoski/DoubleTapListViewHandler

于 2012-01-06T22:27:27.070 に答える
4

GuestureDetecterはほとんどのデバイスでうまく機能します。ダブルクリックイベントで2回のクリック間の時間をカスタマイズする方法を知りたいのですが、それができませんでした。上記のコードを「Bughi」「DoubleClickListner」で更新し、シングルクリックで特定の遅延後にコードを実行するハンドラーを使用してタイマーを追加しました。その遅延の前にダブルクリックを実行すると、タイマーとシングルクリックタスクがキャンセルされ、実行されるだけです。タスクをダブルクリックします。コードは正常に機能していますダブルクリックリストナーとして使用するのに最適です。

  private Timer timer = null;  //at class level;
  private int DELAY   = 500;

  view.setOnClickListener(new DoubleClickListener() {

        @Override
        public void onSingleClick(View v) {

    final Handler  handler          = new Handler();
                final Runnable mRunnable        = new Runnable() {
                    public void run() {
                        processSingleClickEvent(v); //Do what ever u want on single click

                    }
                };

                TimerTask timertask = new TimerTask() {
                    @Override
                    public void run() {
                        handler.post(mRunnable);
                    }
                };
                timer   =   new Timer();
                timer.schedule(timertask, DELAY);       

        }

        @Override
        public void onDoubleClick(View v) {
                if(timer!=null)
                {
                 timer.cancel(); //Cancels Running Tasks or Waiting Tasks.
                 timer.purge();  //Frees Memory by erasing cancelled Tasks.
                }
              processDoubleClickEvent(v);//Do what ever u want on Double Click

        }
    });
于 2014-10-10T10:14:32.587 に答える
3
boolean nonDoubleClick = true, singleClick = false;
        private long firstClickTime = 0L;
        private final int DOUBLE_CLICK_TIMEOUT = 200;

        listview.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
                // TODO Auto-generated method stub
                Handler handler = new Handler();
                handler.postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        // TODO Auto-generated method stub
                        if (singleClick) {
                            Toast.makeText(getApplicationContext(), "Single Tap Detected", Toast.LENGTH_SHORT).show();
                        }
                        firstClickTime = 0L;
                        nonDoubleClick = true;
                        singleClick = false;
                    }
                }, 200);
                if (firstClickTime == 0) {
                    firstClickTime = SystemClock.elapsedRealtime();
                    nonDoubleClick = true;
                    singleClick = true;
                } else {
                    long deltaTime = SystemClock.elapsedRealtime() - firstClickTime;
                    firstClickTime = 0;
                    if (deltaTime < DOUBLE_CLICK_TIMEOUT) {
                        nonDoubleClick = false;
                        singleClick = false;
                        Toast.makeText(getApplicationContext(), "Double Tap Detected", Toast.LENGTH_SHORT).show();
                    }
                }

            }
        });
于 2015-10-27T15:21:20.260 に答える
3

ダブルタップシングルタップ

ダブルタップのみ

( Hannes Niederhausenの回答SimpleOnGestureListenerに示されているように)を使用して、ビューのダブルタップを検出するのは非常に簡単です。

private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return true;
    }
}

このためのロジックを再発明することの大きな利点はわかりません(bughiの答えのように)。

遅延のあるダブルタップとシングルタップ

を使用しSimpleOnGestureListenerて、シングルタップとダブルタップを相互に排他的なイベントとして区別することもできます。これを行うには、をオーバーライドするだけonSingleTapConfirmedです。これにより、ユーザーがダブルタップしていないことがシステムで確認されるまで(つまり、遅延> ViewConfiguration.getDoubleTapTimeout())、シングルタップコードの実行が遅延します。そのためのすべてのロジックを再発明する理由は間違いなくありません(これこれ、および他の回答で行われているように)。

private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return true;
    }
}

遅延のないダブルタップとシングルタップ

の潜在的な問題onSingleTapConfirmedは遅延です。顕著な遅延が受け入れられない場合があります。その場合は、に置き換えることができonSingleTapConfirmedますonSingleTapUp

private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        return true;
    }
}

ただし、ダブルタップがある場合は両方 onSingleTapUp が呼び出されることを理解する必要があります。onDoubleTap(これは基本的に、bughiの回答が行うことであり、一部のコメント投稿者が不満を言っていたことです。)遅延を使用するか、両方のメソッドを呼び出す必要があります。遅延のないシングルタップを行うと同時に、ユーザーがもう一度タップするかどうかを知ることはできません。

シングルタップの遅延が受け入れられない場合は、いくつかのオプションがあります。

  • onSingleTapUp両方を受け入れonDoubleTap、ダブルタップが要求されます。ロジックを適切に分割して、問題にならないようにします。これは基本的に、カスタムキーボードでCapsLockのダブルタップを実装したときに行ったことです。
  • ダブルタップは使用しないでください。ほとんどの場合、これは直感的なUIアクションではありません。Dave Webbが示唆しているように、長押しの方がおそらく良いでしょう。SimpleOnGestureListener:を使用して実装することもできます。

    private class GestureListener extends GestureDetector.SimpleOnGestureListener {
    
        @Override
        public boolean onDown(MotionEvent e) {
            return true;
        }
    
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return true;
        }
    
        @Override
        public void onLongPress(MotionEvent e) {
    
        }
    }
    
于 2018-02-17T19:00:33.810 に答える
2

私の解決策は、役に立つかもしれません。

long lastTouchUpTime = 0;
boolean isDoubleClick = false;

private void performDoubleClick() {
    long currentTime = System.currentTimeMillis();
    if(!isDoubleClick && currentTime - lastTouchUpTime < DOUBLE_CLICK_TIME_INTERVAL) {
        isDoubleClick = true;
        lastTouchUpTime = currentTime;
        Toast.makeText(context, "double click", Toast.LENGTH_SHORT).show();
    }
    else {
        lastTouchUpTime = currentTime;
        isDoubleClick = false;
    }
}
于 2015-09-02T08:19:10.350 に答える
2

即興のdhruviコード

public abstract class DoubleClickListener implements View.OnClickListener {

private static final long DOUBLE_CLICK_TIME_DELTA = 300;//milliseconds

long lastClickTime = 0;
boolean tap = true;

@Override
public void onClick(View v) {
    long clickTime = System.currentTimeMillis();
    if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){
        onDoubleClick(v);
        tap = false;
    } else
        tap = true;

    v.postDelayed(new Runnable() {
        @Override
        public void run() {
            if(tap)
                onSingleClick();
        }
    },DOUBLE_CLICK_TIME_DELTA);

    lastClickTime = clickTime;
}

public abstract void onDoubleClick(View v);

public abstract void onSingleClick();
}
于 2018-01-03T21:05:47.900 に答える
2

Kotlinを使用している場合は、次のように実行できます。

このコードをKotlinに変換するのに多くの時間を費やして、誰かの時間を節約できることを願っています

ジェスチャ検出器を作成します。

      val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
            override fun onDoubleTap(e: MotionEvent): Boolean {

                Toast.makeText(this@DemoActivity,"Double Tap",Toast.LENGTH_LONG).show()

                //Show or hide Ip address on double tap
                toggleIPaddressVisibility()

                return true;
            }

            override fun onLongPress(e: MotionEvent) {
                super.onLongPress(e);

                //rotate frame on long press
                toggleFrameRotation()

                Toast.makeText(this@DemoActivity,"LongClick",Toast.LENGTH_LONG).show()
            }

            override fun onDoubleTapEvent(e: MotionEvent): Boolean {
                return true
            }

            override fun onDown(e: MotionEvent): Boolean {
                return true
            }
        })

ビューのいずれかに割り当てます。

        IPAddress.setOnTouchListener { v, event ->
          return@setOnTouchListener  gestureDetector.onTouchEvent(event)
        }
于 2019-03-12T09:47:00.337 に答える
2

これは、アクションを実行する前に2番目のクリックがある場合に待機するソリューションです。

  int init = 0;
  myView.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {


            if (init == 0) {
                init++;
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {



                        if (init == 1) {
                            Log.d("hereGoes", "actionOne");
                        } else {
                            Log.d("hereGoes", "actionTwo");
                        }


                        init = 0;
                    }
                }, 250);
            } else {
                init++;
            }

        }
    });
于 2019-08-09T12:08:50.400 に答える
1

シングルクリックとダブルクリックの実現

public abstract class DoubleClickListener implements View.OnClickListener {

private static final long DOUBLE_CLICK_TIME_DELTA = 200;

private long lastClickTime = 0;

private View view;

private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
    @Override
    public void run() {
        onSingleClick(view);
    }
};

private void runTimer(){
    handler.removeCallbacks(runnable);
    handler.postDelayed(runnable,DOUBLE_CLICK_TIME_DELTA);
}

@Override
public void onClick(View view) {
    this.view = view;
    long clickTime = System.currentTimeMillis();
    if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){
        handler.removeCallbacks(runnable);
        lastClickTime = 0;
        onDoubleClick(view);
    } else {
        runTimer();
        lastClickTime = clickTime;
    }
}

public abstract void onSingleClick(View v);
public abstract void onDoubleClick(View v);

}

于 2016-02-24T13:45:55.567 に答える
1
public class MyView extends View {

GestureDetector gestureDetector;

public MyView(Context context, AttributeSet attrs) {
    super(context, attrs);
            // creating new gesture detector
    gestureDetector = new GestureDetector(context, new GestureListener());
}

// skipping measure calculation and drawing

    // delegate the event to the gesture detector
@Override
public boolean onTouchEvent(MotionEvent e) {
    return gestureDetector.onTouchEvent(e);
}


private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }
    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        float x = e.getX();
        float y = e.getY();

        Log.d("Double Tap", "Tapped at: (" + x + "," + y + ")");

        return true;
    }
}
}
于 2016-06-09T12:38:59.977 に答える
1

スレッド+インターフェイス=DoubleTapListener、AnyTapリスナーなど

この例では、スレッドを使用してDoubleTapリスナーを実装しました。ClickListenerの場合と同じように、任意のViewオブジェクトを使用してリスナーを追加できます。このアプローチを使用すると、あらゆる種類のクリックリスナーを簡単に実行できます。

yourButton.setOnClickListener(new DoubleTapListener(this));

1)私のListrenerクラス

public class DoubleTapListener  implements View.OnClickListener{

   private boolean isRunning= false;
   private int resetInTime =500;
   private int counter=0;
   private DoubleTapCallback listener;

   public DoubleTapListener(Context context){
       listener = (DoubleTapCallback)context;
       Log.d("Double Tap","New");
   }

   @Override
   public void onClick(View v) {

       if(isRunning){
          if(counter==1)
              listener.onDoubleClick(v);
       }

       counter++;

       if(!isRunning){
          isRunning=true;
          new Thread(new Runnable() {
             @Override
             public void run() {
                 try {
                    Thread.sleep(resetInTime);
                    isRunning = false;
                    counter=0;
                 } catch (InterruptedException e) {
                    e.printStackTrace();
                 }
             }
           }).start();
       }
   }
}

2)リスナーのコールバック

public interface DoubleTapCallback {

      public void onDoubleClick(View v);

}

3)アクティビティに実装する

public class MainActivity extends AppCompatActivity implements DoubleTapCallback{

private Button button;
private int counter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    button   = (Button)findViewById(R.id.button);      
    button.setOnClickListener(new DoubleTapListener(this));  // Set mt listener

}

@Override
public void onDoubleClick(View v) {
    counter++;
    textView.setText(counter+""); 
}

関連リンク:

あなたはここで完全に機能するコードを見ることができます

于 2019-01-26T15:41:27.600 に答える
0

copypastのbughi&Jayant Aroraによる解決策:

public abstract class DoubleClickListener implements View.OnClickListener {
private int position;
private Timer timer;

private static final long DOUBLE_CLICK_TIME_DELTA = 300;//milliseconds

long lastClickTime = 0;

public DoubleClickListener (int position) {
    this.position = position;
}

@Override
public void onClick(View v) {
    long clickTime = System.currentTimeMillis();
    if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA){
        if (timer != null) {
            timer.cancel(); //Cancels Running Tasks or Waiting Tasks.
            timer.purge();  //Frees Memory by erasing cancelled Tasks.
        }
        onDoubleClick(v, position);
    } else {
        final Handler handler = new Handler();
        final Runnable mRunnable = () -> {
            onSingleClick(v, position);
        };
        TimerTask timertask = new TimerTask() {
            @Override
            public void run() {
                handler.post(mRunnable);
            }
        };
        timer = new Timer();
        timer.schedule(timertask, DOUBLE_CLICK_TIME_DELTA);

    }
    lastClickTime = clickTime;
}

public abstract void onSingleClick(View v, int position);
public abstract void onDoubleClick(View v, int position);}
于 2016-06-16T11:26:09.603 に答える
0

同じ機能を実装するために使用した同等のC#コードであり、N個のタップを受け入れるようにカスタマイズすることもできます

public interface IOnTouchInterface
{
    void ViewTapped();
}

public class MultipleTouchGestureListener : Java.Lang.Object, View.IOnTouchListener
{
    int clickCount = 0;
    long startTime;
    static long MAX_DURATION = 500;
    public int NumberOfTaps { get; set; } = 7;

    readonly IOnTouchInterface interfc;

    public MultipleTouchGestureListener(IOnTouchInterface tch)
    {
        this.interfc = tch;
    }

    public bool OnTouch(View v, MotionEvent e)
    {
        switch (e.Action)
        {
            case MotionEventActions.Down:
                clickCount++;
                if(clickCount == 1)
                    startTime = Utility.CurrentTimeSince1970;
                break;
            case MotionEventActions.Up:
                var currentTime = Utility.CurrentTimeSince1970;
                long time = currentTime - startTime;
                if(time <= MAX_DURATION * NumberOfTaps)
                {
                    if (clickCount == NumberOfTaps)
                    {
                        this.interfc.ViewTapped();
                        clickCount = 0;
                    }
                }
                else
                {
                    clickCount = 0;
                }
                break;
        }
        return true;
    }
}

public static class Utility
{
    public static long CurrentTimeSince1970
    {
        get
        {
            DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
            DateTime dtNow = DateTime.Now;
            TimeSpan result = dtNow.Subtract(dt);
            long seconds = (long)result.TotalMilliseconds;
            return seconds;
        }
    }
}

現在、上記のコードは、ViewTappedイベントを発生させる前のタップ数として7を受け入れます。ただし、任意の数でカスタマイズできます

于 2018-01-30T04:08:06.483 に答える
0

kotlinコルーチンを使用して簡単なカスタムメソッドを実装しました(Javaの場合はスレッドを介して実行できます)。

var click = 0

view.setOnClickListener{
   click++
   clicksHandling()
}

fun clicksHandling() {
   if (click == 1) {
      launch {
        delay(300) // custom delay duration between clicks
        // if user didn't double tap then click counter still 1
        if (click == 1) {
          // single click handling
          runOnUiThread {
             // whatever you wanna do on UI thread
          }
        }

        click = 0 //reset counter , this will run no matter single / double tap
      }
   //double click handling
   if (click == 2) {
         // whatever on double click
   }
}
于 2018-12-11T09:24:10.780 に答える
0

GestureDetectorCompatクラスを使用してダブルタップを実装できます。このサンプルでは、​​textviewをダブルタップすると、ロジックを実行できます。

public class MainActivity extends AppCompatActivity {

GestureDetectorCompat gestureDetectorCompat;
TextView textElement;

@Override
protected void onCreate(Bundle savedInstanceState) { 
    .....
    textElement = findViewById(R.id.textElement);
    gestureDetectorCompat = new GestureDetectorCompat(this, new MyGesture());
    textElement.setOnTouchListener(onTouchListener);

}

 View.OnTouchListener onTouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        gestureDetectorCompat.onTouchEvent(event);
        return true;
    }
};
    class MyGesture extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent e) {
        // whatever on double click
        return true;
    }
}
于 2019-02-21T19:42:45.567 に答える
0

Kotlinでこれを行う簡単な方法:

button.setOnTouchListener(object : View.OnTouchListener{
    val gestureDetector = GestureDetector(object : GestureDetector.SimpleOnGestureListener(){
        override fun onDoubleTap(e: MotionEvent?): Boolean {
           //do something here
            return super.onDoubleTap(e)
        }
    })

    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
        //do something here
        gestureDetector.onTouchEvent(event)
        return true
    }
})
于 2020-07-16T16:38:46.590 に答える
0

ジェスチャタップのタイプを検出するには、これにインラインで何かを実装できます(ここprojectTextEditText):

projectText.setOnTouchListener(new View.OnTouchListener() {
    private GestureDetector gestureDetector = new GestureDetector(activity, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDoubleTap(MotionEvent e) {
            projectText.setInputType(InputType.TYPE_CLASS_TEXT);
            activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
            return super.onDoubleTap(e);
        }
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
                projectText.setInputType(InputType.TYPE_NULL); // disable soft input
                final int itemPosition = getLayoutPosition();
                if(!projects.get(itemPosition).getProjectId().equals("-1"))
                    listener.selectedClick(projects.get(itemPosition));

            return super.onSingleTapUp(e);
        }
    });

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        gestureDetector.onTouchEvent(event);
        return false; //true stops propagation of the event
    }
});
于 2020-11-08T22:32:51.793 に答える
0

これを処理するための簡単なライブラリを作成しました。また、2回以上のクリックを検出することもできます(すべてユーザーによって異なります)。ClickCounterクラスをインポートした後、これを使用してシングルクリックとマルチクリックを検出する方法は次のとおりです。

ClickCounter counter = new ClickCounter();


view.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        counter.addClick();  // submits click to be counted
    }
});

counter.setClickCountListener(new ClickCounter.ClickCountListener() {
    @Override
    public void onClickingCompleted(int clickCount) {
        rewardUserWithClicks(clickCount); // Thats All!!
    }
}); 
于 2020-12-15T09:35:18.520 に答える
0

Kotlinでは、これを試すことができます。

カードビューを使用してクリックしているように、

(例:ダブルクリックすると、好き嫌いを実行します。)

cardviewPostCard.setOnClickListener(object : DoubleClickListener() {
    override fun onDoubleClick(v: View?) {

        if (holder.toggleButtonLike.isChecked) {
            holder.toggleButtonLike.setChecked(false) //
        } else {
            holder.toggleButtonLike.setChecked(true)

        }
    }
})

これがDoubleClickListenerクラスです。

abstract class DoubleClickListener : View.OnClickListener {
    var lastClickTime: Long = 0
    override fun onClick(v: View?) {
        val clickTime = System.currentTimeMillis()
        if (clickTime - lastClickTime < DOUBLE_CLICK_TIME_DELTA) {
            onDoubleClick(v)
        }
        lastClickTime = clickTime
    }

    abstract fun onDoubleClick(v: View?)

    companion object {
        private const val DOUBLE_CLICK_TIME_DELTA: Long = 300 //milliseconds
    }
}
于 2021-01-07T10:19:27.627 に答える
0

私は元の答えのアプローチの単純さが好きでしたが

これが私のバージョンです

public abstract class OnDoubleClickListener implements View.OnClickListener {

    private static final int TIME_OUT = ViewConfiguration.getDoubleTapTimeout();
    private TapHandler tapHandler = new TapHandler();

    public abstract void onSingleClick(View v);
    public abstract void onDoubleClick(View v);

    @Override
    public void onClick(View v) {
        tapHandler.cancelSingleTap(v);
        if (tapHandler.isDoubleTap()){
            onDoubleClick(v);
        } else {
            tapHandler.performSingleTap(v);
        }
    }

    private class TapHandler implements Runnable {
        public boolean isDoubleTap() {
            final long tapTime = System.currentTimeMillis();
            boolean doubleTap = tapTime - lastTapTime < TIME_OUT;
            lastTapTime = tapTime;
            return doubleTap;
        }
        public void performSingleTap(View v) {
            view = v;
            v.postDelayed(this, TIME_OUT);
        }
        public void cancelSingleTap(View v) {
            view = null;
            v.removeCallbacks(this);
        }

        @Override
        public void run() {
            if (view != null) {
                onSingleClick(view);
            }
        }
        private View view;
        private long lastTapTime = 0;
    }
}

使用法はオリジナルと同じです

view.setOnClickListener(new OnDoubleClickListener() {

    @Override
    public void onSingleClick(View v) {

    }

    @Override
    public void onDoubleClick(View v) {

    }
});
于 2021-01-14T05:07:13.330 に答える