Android: How to detect double-tap?
我实现双击时遇到问题。 我实现了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | 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; } |
哦,另一个问题,如果我的
您可以使用GestureDetector。请参阅以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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; } } } |
您可以覆盖侦听器的其他方法以获得单击,flinges等。
作为GestureDetector的轻量级替代品,您可以使用此类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); } |
例:
1 2 3 4 5 6 7 8 9 10 11 12 | view.setOnClickListener(new DoubleClickListener() { @Override public void onSingleClick(View v) { } @Override public void onDoubleClick(View v) { } }); |
你为什么不使用长按?或者你已经在使用其他东西?双击长按的优点:
- 长按是UI指南中的推荐交互,Double Touch不是。
- 这是用户期望的;用户可能找不到Double Touch操作,因为他们不会去寻找它
- 它已在API中处理。
- 实施双击将影响单次触摸的处理,因为您必须等待,以便在处理之前查看每个Single Touch是否变为双触摸。
将"Bu??ghi""DoubleClickListner"和"Jayant Arora"计时器合并在一个包含的类中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | 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); } |
并可以称为:
1 2 3 4 5 6 7 8 9 10 11 12 | view.setOnClickListener(new DoubleClickListener() { @Override public void onSingleClick(View v) { } @Override public void onDoubleClick(View v) { } }); |
如果您不想进入自定义视图,则可以使用以下方法。
例如ImageView的
1 2 3 4 5 6 7 8 | // class level GestureDetector gestureDetector; boolean tapped; ImageView imageView; // inside onCreate of Activity or Fragment gestureDetector = new GestureDetector(context,new GestureListener()); |
// ------------------------------------------------ --------------------------------
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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
1 2 3 4 5 6 7 8 9 | imageView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub return gestureDetector.onTouchEvent(event); } }); |
这是我的解决方案,它使用默认的
给出了简要说明。我不确定系统(参见
编辑:
在这里看到:
https://github.com/NikolaDespotoski/DoubleTapListView或
https://github.com/NikolaDespotoski/DoubleTapListViewHandler
GuestureDetecter适用于大多数设备,我想知道如何在双击事件上自定义两次点击之间的时间,我无法做到这一点。我通过"Bughi""DoubleClickListner"更新了上面的代码,使用处理程序添加了一个计时器,该处理程序在单击一次特定延迟后执行代码,如果在该延迟之前执行双击,则取消计时器和单击任务并仅执行双击任务。
代码工作正常使用它作为双击列表器非常完美:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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 } }); |
双击和单击
仅限双击
使用
1 2 3 4 5 6 7 8 9 10 11 12 | private class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onDoubleTap(MotionEvent e) { return true; } } |
我无法看到重新发明逻辑的巨大优势(如bughi的回答)。
双击和单击延迟
您还可以使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } } |
双击和单击,无延迟
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 进行双击。只需适当地划分你的逻辑,这样就无所谓了。这基本上就是我在自定义键盘上实现双击以进行大写锁定时所做的。 -
不要使用双击。对于大多数事情来说,这不是一个直观的UI动作。正如Dave Webb所暗示的那样,长时间的推出可能会更好。您也可以使用
SimpleOnGestureListener 实现它:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17private 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) {
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | 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(); } } } }); |
即兴的dhruvi代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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(); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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; } } } |
我的解决方案可能会有所帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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; } } |
实现单击和双击
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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); |
}
这是一个解决方案,在执行任何操作之前等待第二个clic
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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++; } } }); |
我用来实现相同功能的等效C#代码,甚至可以自定义接受N个Taps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 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; } } } |
目前,上面的代码在提升View Tapped事件之前接受7作为点击数。
但它可以用任何数字定制
我已经使用kotlin协同程序实现了一个简单的自定义方法(对于java可以通过线程完成)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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 } } |
Thread + Interface = DoubleTapListener,AnyTap监听器等
在这个例子中,我已经使用Thread实现了DoubleTap Listener。
您可以像使用任何ClickListener一样将侦听器添加到任何View对象。
使用此方法,您可以轻松实现任何类型的单击侦听器。
yourButton.setOnClickListener(new DoubleTapListener(this));
1)我的Listrener课程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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)监听器回调
1 2 3 4 | public interface DoubleTapCallback { public void onDoubleClick(View v); } |
3)在您的活动中实施
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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+""); } |
相关链接:
你可以在这里看到完整的工作代码
您可以使用
在这个示例中,当双击textview时,您可以执行您的逻辑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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; } } |
如果您正在使用Kotlin,那么您可以这样做:
我花了很多时间将这些代码转换为Kotlin,希望能节省一些人的时间
创建手势检测器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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 } }) |
分配给您的任何视图:
1 2 3 | IPAddress.setOnTouchListener { v, event -> return@setOnTouchListener gestureDetector.onTouchEvent(event) } |
解决方案由bughi&amp; Jayant Arora for copypast:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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);} |