Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to detect double-tap?

I have a problem with implementing double tap. Well I implemented the onGestureListener and I had the gestureDetector, but I'm not sure where is the problem, here is my code:

 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;  } 

Oh, another question, if my ListView has an onItemClickListener, can android detect between single tap or double tap for it?

like image 857
alan Avatar asked Feb 07 '10 18:02

alan


People also ask

How to detect gestures in Android?

Detect gestures. Android provides the GestureDetector class for detecting common gestures. Some of the gestures it supports include onDown() , onLongPress() , onFling() , and so on. You can use GestureDetector in conjunction with the onTouchEvent() method described above.

What is Gesture in Android?

Android provides special types of touch screen events such as pinch , double tap, scrolls , long presses and flinch. These are all known as gestures. Android provides GestureDetector class to receive motion events and tell us that these events correspond to gestures or not.


2 Answers

You can use the GestureDetector. See the following code:

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;         }     } } 

You can override other methods of the listener to get single taps, flinges and so on.

like image 69
Hannes Niederhausen Avatar answered Oct 18 '22 03:10

Hannes Niederhausen


As a lightweight alternative to GestureDetector you can use this class

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); } 

Example:

    view.setOnClickListener(new DoubleClickListener() {          @Override         public void onSingleClick(View v) {          }          @Override         public void onDoubleClick(View v) {          }     }); 
like image 23
bughi Avatar answered Oct 18 '22 02:10

bughi