自定義View的onTouch
在專案開發的過程中,使用到了ImageView控制元件,要做選中狀態,很自然的想到了selector方式,可就是這麼一個簡單的東西,足足折騰了我兩三個小時。
問題
- selector選中狀態莫名失效,對此網上有些對應的解決方法是,將selector中true的狀態放在第一位置;
- 我想做longclick或者doubleclick都很麻煩
- imageview無法響應onTouch事件,必須要先在xml中設定clickable = true,或者 return true ,但即便是這樣,也難以獲取cancel事件。
人的生命是有限的,不想把太多時間浪費在上面莫名其妙的問題上,所以,擼起袖子自己幹,寫了一個簡單的onTouch封裝類。
程式碼如下:
public class HJCXOnTouchListener implements View.OnTouchListener { private final int longTime = 1000;//長按事件定為1000ms private boolean isUpOut = false;//是否是在控制元件之外抬起 private boolean hasResponseLongClickEvent = false;//是否響應了長按事件 private OnHJCXOnTouchListener onHJCXOnTouchListener; private long clickTime = 0; public HJCXOnTouchListener(OnHJCXOnTouchListener onHJCXOnTouchListener) { this.onHJCXOnTouchListener = onHJCXOnTouchListener; } @Override public boolean onTouch(View v, MotionEvent event) { float x = event.getRawX(); float y = event.getRawY(); if (event.getAction() == MotionEvent.ACTION_DOWN){ clickTime = System.currentTimeMillis(); isUpOut = false; hasResponseLongClickEvent = false; onHJCXOnTouchListener.onHJCXOnTouchListener(OnHJCXOnTouchListener.CLICK); } if (event.getAction() == MotionEvent.ACTION_MOVE){ if (isInside(v,x,y)){ isUpOut = false; }else{ isUpOut = true; } if (System.currentTimeMillis() - clickTime > longTime && !hasResponseLongClickEvent && !isUpOut){ hasResponseLongClickEvent = true; onHJCXOnTouchListener.onHJCXOnTouchListener(OnHJCXOnTouchListener.LONG_CLICK); } } if (event.getAction() == MotionEvent.ACTION_UP){ if (isUpOut){ onHJCXOnTouchListener.onHJCXOnTouchListener(OnHJCXOnTouchListener.CANCEL); }else{ if (!hasResponseLongClickEvent)//longclick響應後,不再響應UP事件 onHJCXOnTouchListener.onHJCXOnTouchListener(OnHJCXOnTouchListener.UP); } } return true; } boolean isInside(View view, float x, float y) { if (view == null) { return false; } //獲取控制元件在螢幕的位置 int[] location = new int[2]; view.getLocationOnScreen(location); //控制元件相對於螢幕的x與y座標 int xScreen = location[0]; int yScreen = location[1]; Rect rect = new Rect(xScreen, yScreen, xScreen + view.getWidth(), yScreen + view.getHeight()); return rect.contains((int) x, (int) y); } public interface OnHJCXOnTouchListener{ //點選 int CLICK = 0; //抬起 int UP = 1; //長按 int LONG_CLICK = 2; //取消 int CANCEL = 3; void onHJCXOnTouchListener(int type); }
如上,用的都是一些基本的方法,比較生僻的方法估計就是isInside方法了,用於判斷cancel事件(手指移出控制元件範圍)。
呼叫方式如下
view.setOnTouchListener(new HJCXOnTouchListener(new HJCXOnTouchListener.OnHJCXOnTouchListener() { @Override public void onHJCXOnTouchListener(int type) { switch (type){ case HJCXOnTouchListener.OnHJCXOnTouchListener.CLICK: // break; case HJCXOnTouchListener.OnHJCXOnTouchListener.UP: // break; case HJCXOnTouchListener.OnHJCXOnTouchListener.LONG_CLICK: // break; case HJCXOnTouchListener.OnHJCXOnTouchListener.CANCEL: // break; } } }));
好了,以上就是我的這次自定義OnTouch事件,如有不足之處,還望多多指教。