一:
原理就是響應(yīng)控件的Touch事件,在Touch事件中對(duì)移動(dòng)進(jìn)行處理,如果沒(méi)效果那你試著在布局文件中設(shè)置控件的 android:clickable="true"。
當(dāng)然,大部分人都是直接想要解決方案,這里直接貼代碼,后面會(huì)有一些說(shuō)明。
-
1.首先在 你的 Activity 實(shí)現(xiàn) OnTouchListener 接口 ,并重寫(xiě)onTouch 方法
implements OnTouchListener
-
2.activity中定義幾個(gè)變量先
private int screenWidth, screenHeight;
private int lastX, lastY,moveDownX;
private ImageView mTestIV; -
3.在A(yíng)ctivity 的 onCreate方法中
mTestIV=(ImageView) findViewById(R.id.iv_test); mTestIV.setOnTouchListener(this); Display dis = this.getWindowManager().getDefaultDisplay(); screenWidth = dis.getWidth(); screenHeight = dis.getHeight(); -
4.重寫(xiě)onTouch內(nèi)部方法
@Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); moveDownX= (int) event.getRawX(); } if (event.getAction() == MotionEvent.ACTION_MOVE){ int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; int top = v.getTop() + dy; int left = v.getLeft() + dx; if (top <= 0) { top = 0; } if (top >= screenHeight - mTestIV.getHeight()) { top = screenHeight - mTestIV.getHeight(); } if (left >= screenWidth - mTestIV.getWidth()) { left = screenWidth - mTestIV.getWidth(); } if (left <= 0) { left = 0; } v.layout(left, top, left + mTestIV.getWidth(), top + mTestIV.getHeight()); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); } if (event.getAction() == MotionEvent.ACTION_UP) { int tempDX = (int) event.getRawX() - moveDownX; if (Math.abs(tempDX) < 6) { // do your things return false;// 距離較小,當(dāng)作click事件來(lái)處理 } } return true;// 返回true,不執(zhí)行click事件 }
以上為全部代碼。
二:
現(xiàn)在我們來(lái)分析下實(shí)現(xiàn)步驟:
一:我們開(kāi)始要實(shí)現(xiàn)控件拖動(dòng)效果
原理比較簡(jiǎn)單:
- 1.在按下的時(shí)候(MotionEvent.ACTION_DOWN),開(kāi)始記錄當(dāng)前按下位置的坐標(biāo)值;
- 2.然后在手指移動(dòng)控件的時(shí)候(MotionEvent.ACTION_MOVE),不斷計(jì)算當(dāng)前的位置的坐標(biāo)并重繪控件的位置
這里說(shuō)明下 一些知識(shí)點(diǎn):
視圖的left , top , right , bottom 的值是針對(duì)其父視圖的相對(duì)位置,left相當(dāng)于X軸值, top相當(dāng)于Y軸值(原點(diǎn)為該widget 的父控件的左上角的點(diǎn))
getX是獲取以widget左上角為坐標(biāo)原點(diǎn)計(jì)算的X軸坐標(biāo)值
getRawX 獲取的是以屏幕左上角為坐標(biāo)原點(diǎn)計(jì)算的X軸坐標(biāo)值
做完以上步驟,可以實(shí)現(xiàn)正常的拖動(dòng),但這時(shí)候會(huì)發(fā)現(xiàn),你拖動(dòng)抬起手指后會(huì)執(zhí)行onClick事件。
現(xiàn)在分析下這件事出現(xiàn)的原因:
在A(yíng)ndroid中,對(duì)一個(gè)View同時(shí)調(diào)用OnTouch事件和OnClick事件時(shí),導(dǎo)致事件沖突。
比如onClick事件打算執(zhí)行A動(dòng)作,OnTouch事件打算執(zhí)行B動(dòng)作,但是在實(shí)際使用時(shí)會(huì)發(fā)現(xiàn),當(dāng)調(diào)用OnTouch時(shí),有可能會(huì)同時(shí)執(zhí)行A,B兩個(gè)動(dòng)作,這是因?yàn)镺nClick事件本身就是在OnTouch事件中發(fā)生的;
在onTouch事件中,如果返回true,就不會(huì)執(zhí)行onClick,返回false,就同時(shí)執(zhí)行onClick方法,要想把OnTouch和onClick事件完全的區(qū)分??赡苓^(guò)下列方法,解決該沖突問(wèn)題:
就是在 OnTouch中的MotionEvent.ACTION_DOWN 時(shí),記錄下點(diǎn)(X1,Y1),在 MotionEvent.ACTION_UP 時(shí),記錄下點(diǎn)(X2,Y2),然后比對(duì) 倆點(diǎn)之間的距離,如果小于一個(gè)較小數(shù)值(比如6),就認(rèn)為是Click事件,onTouch中返回false,如果距離較大,可以當(dāng)作onTouch事件去處理,返回true: