自定義可拖拽的view
阿新 • • 發佈:2019-01-25
簡介幾個方法
在我們要做這麼一個自定義view時得先把下面幾個方法搞清楚,不然你是弄不出來的,先前我只是看了網上簡單介紹沒有真正搞懂他們,就做的一直有些小問題。其實方法很簡單,但必須真正理解。
MotionEvent:
getRawX(); //你觸控的x座標,相對於螢幕的位置,這裡是相對整個螢幕的,與後面說的"可用"螢幕有區別。
getX(); //你第一個手指觸控的x座標,相對於你觸控的控制元件本身而言的。如果你兩個手指下去,想獲取第二的觸控位置就呼叫get(1),後面依次類推,這個先了解一下,我弄那個兩個手勢控制縮小放大才用到。
View:
getTop();//獲取此view相對於父view的位置,如果"沒有父view"就是相對於"可用"螢幕而言,這裡是關鍵,其餘三個位置雷同。
setFrame();//裡面有四個引數,說法類似getTop(),後面程式碼裡有再次提到。
可拖拽的View程式碼
直接上程式碼自己看,需要註解的都寫明瞭,邏輯也比較簡單清晰。
package com.xiong.tucao;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.ImageView;
public class DragTextView extends ImageView{
//相對於父控制元件的觸控位置,用於處理拖拽
private float xDown,yDown,xUp,yUp;
private int extra;
public DragTextView(Context context) {
this(context, null, 0);
}
public DragTextView(Context context, AttributeSet attrs) {
this (context, attrs, 0);
}
public DragTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
dm = new DisplayMetrics();//獲取螢幕寬高,處理越界的時候用到
Activity activity = (Activity) context; activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
}
//重寫觸控的方法
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_DOWN:
onTouchDown(event);
break;
case MotionEvent.ACTION_MOVE:
onTouchMove(event);
break;
case MotionEvent.ACTION_UP:
isOver();
break;
}
return true;
}
/** 按下 **/
private void onTouchDown(MotionEvent event){
xDown = event.getX();
yDown = event.getY();
xUp = event.getRawX();
yUp = event.getRawY();
extra = (int) (yUp - yDown - getTop());
}
/** 拖拽 **/
private void onTouchMove(MotionEvent event) {
int left, right, top, bottom;
top = (int) (yUp - yDown) - extra;
bottom = top + getHeight();
left = (int) (xUp - xDown);
right = left + getWidth();
//Top position, relative to parent這是該方法其中top引數的官方解釋,反正我是被誤導了,我不知道這個父親到底是怎樣定義的
// 我目前的理解是它的所有引數位置是相對於該view放置的那個xml佈局的位置,那個xml佈局最外面的那個layout才是父view。
//為什麼要說的這麼繞,就是它的位置不是相對螢幕的,因為你的應用可能有tab佔了位置,那塊位置就不能算。如果理解了這些話就能知道為什麼會有extra了。
this.setFrame(left, top, right, bottom);
xUp = event.getRawX();
yUp = event.getRawY();
}
/**
* 拖拽時判斷是否越界
*/
private void isOver() {
int width = this.getWidth()/3;
int height = this.getHeight()/3;
int left = getLeft(),right=getRight(),top=getTop(),bottom=getBottom();
//針對整個可用螢幕的越界,必須還能看到控制元件的1/3
if (this.getBottom() < height){
bottom = height;
top = bottom - getHeight();
}
if (this.getRight() < width){
right = width;
left = right - getWidth();
}
if (this.getTop() > dm.heightPixels - extra - height){
top = dm.heightPixels - extra - height;
bottom = top + getHeight();
}
if (this.getLeft() > dm.widthPixels - width){
left = dm.widthPixels - width;
right = left + getWidth();
}
if (this.getBottom() < height || this.getLeft() < - width || this.getRight() > dm.widthPixels - width || this.getTop() > dm.heightPixels - extra - height) {
setFrame(left, top, right, bottom);
}
}
}
是不是很簡單呢,最後就是使用它了,你以前的ImageView怎麼用的那它就怎麼用。若對某些話不理解,自己列印下它們的值就一清二楚了。