先上效果圖:
以下是我自定義的view(代碼中已經有了詳細解釋,直接拿來使用即可):
注意:自定義view好處就是自定義完成後直接就拿來使用,很方便,但是不好就是,裏面的onTouchEvent方法會把點擊,長按事件屏蔽,也就是我們不能.setOnClickListener了
注意:自定義view其他自定義的構造方法可以有,但默認的三個構造方法必須實現,不然可能會出現Custom view MySwitchBtn is not using the 2- or3-argument View constructors; XML attributes will not work 的錯誤。
參照博客:http://blog.csdn.net/xiaonadiandian/article/details/46379767
最後直接在xml中引用就行了
當然除了自定義view,通過重寫方法的方式,也可以直接在活動中直接監聽組件的onTouchEvent方法。
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
/**
* 步驟一:自定義可移動組件
* @author NewBies
* @date 2017/12/26
*/
public class VertexView extends android.support.v7.widget.AppCompatTextView{
private int startX;
private int startY;
private int endX;
private int endY;
private FrameLayout.LayoutParams layoutParams;
public VertexView(Context context) {
super(context);
}
public VertexView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VertexView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 步驟二:重寫onTouchEvent事件
* @param event
* @return
*/
@Override
public boolean onTouchEvent(MotionEvent event){
//步驟三:獲取手機觸摸點的橫座標和縱座標
endX = (int)event.getX();
endY = (int)event.getY();
//步驟四:獲取佈局參數實例,注意:xx.LayoutParams這裏的xx應該是該組件的父佈局類型
//注意:這句話必須在該組件已經添加到父佈局中才會起作用,所以這句話我沒有寫在構造函數中,而是寫在這裏
layoutParams = (FrameLayout.LayoutParams) this.getLayoutParams();
switch (event.getAction()){
//監聽按下去的事件,這個事件在每次拖動時,必定會執行,也只執行一次
case MotionEvent.ACTION_DOWN:
//將按下去的點記錄爲起始點
startX = endX;
startY = endY;
break;
//步驟五:監聽移動事件,該事件會在拖動時執行N次
case MotionEvent.ACTION_MOVE:
//計算移動的距離
int offsetX = endX - startX;
int offsetY = endY - startY;
//調用layout方法來重新放置它的位置
layoutParams.setMargins(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
//刷新
requestLayout();
break;
//監聽擡起事件,該事件同按下去的時間一樣,只執行一次
case MotionEvent.ACTION_UP:
break;
default:break;
}
//這裏應該返回true,這裏涉及到了android的事件攔截機制,大致意思是,我的事件是在哪裏處理,就在那裏的事件返回TRUE
return true;
}
}