項目中需要一個刷新的按鈕,不願意再去循規守矩,想了想決定要弄一個可以移動的按鈕來替代之前的固定按鈕:
首先的問題就是怎麼讓控件可以移動呢?
移動的話肯定就是咱們給按鈕Button進行setOnTouchListener()監聽器,來控制他的落下,移動,擡起事件:
事件一: 落下 ACTION-DOWN
例:獲取當前的像素點的X值Y值;
事件二:移動 ACTION-MOVE
例:獲取咱們拖動按鈕帶來的位移量,動態增加記錄當前新的位置,對按鈕進行重繪,並且在位移時還要有控制邏輯不讓按鈕被我們移動出屏幕,詳情請看代碼.
事件三:擡起 ACTION-UP
例:擡起時這裏得有判斷,因爲平常的按鈕,也會有擡起事件,可能用詞不太恰當,但是意思是正確的,所以這邊得有判斷邏輯驗證此擡起事件是位移之後的擡起事件還是默認的擡起事件;
直接擼代碼給大家得了,程序員還是用代碼說話:
首先看佈局文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.administrator.demo_keyidong_button.MainActivity">
<Button
android:id="@+id/movebtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello_world" />
</RelativeLayout>
其次看界面代碼:
package com.example.administrator.demo_keyidong_button;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
private Button movebtn;//可拖動按鈕
private boolean clickormove = true; //點擊或拖動,點擊爲true,拖動爲false
private int downX, downY; //按下時的X,Y座標
private boolean hasMeasured = false; //ViewTree是否已被測量過,是爲true,否爲false
private View content; //界面的ViewTree
private int screenWidth,screenHeight; //ViewTree的寬和高
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);//獲取界面的ViewTree根節點View
DisplayMetrics dm = getResources().getDisplayMetrics();//獲取顯示屏屬性
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
ViewTreeObserver vto = content.getViewTreeObserver();//獲取ViewTree的監聽器
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
// TODO Auto-generated method stub
if(!hasMeasured)
{
screenHeight = content.getMeasuredHeight();//獲取ViewTree的高度
hasMeasured = true;//設置爲true,使其不再被測量。
}
return true;//如果返回false,界面將爲空。
}
});
movebtn = (Button) findViewById(R.id.movebtn);
movebtn.setOnTouchListener(new View.OnTouchListener() {//設置按鈕被觸摸的時間
int lastX, lastY; // 記錄移動的最後的位置
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int ea = event.getAction();//獲取事件類型
switch (ea) {
case MotionEvent.ACTION_DOWN: // 按下事件
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
downX = lastX;
downY = lastY;
break;
case MotionEvent.ACTION_MOVE: // 拖動事件
// 移動中動態設置位置
int dx = (int) event.getRawX() - lastX;//位移量X
int dy = (int) event.getRawY() - lastY;//位移量Y
int left = v.getLeft() + dx;
int top = v.getTop() + dy;
int right = v.getRight() + dx;
int bottom = v.getBottom() + dy;
//++限定按鈕被拖動的範圍
if (left < 0) {
left = 0;
right = left + v.getWidth();
}
if (right > screenWidth) {
right = screenWidth;
left = right - v.getWidth();
}
if (top < 0) {
top = 0;
bottom = top + v.getHeight();
}
if (bottom > screenHeight) {
bottom = screenHeight;
top = bottom - v.getHeight();
}
//--限定按鈕被拖動的範圍
v.layout(left, top, right, bottom);//按鈕重畫
// 記錄當前的位置
lastX = (int) event.getRawX();
lastY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP: // 彈起事件
//判斷是單擊事件或是拖動事件,位移量大於5則斷定爲拖動事件
if (Math.abs((int) (event.getRawX() - downX)) > 5
|| Math.abs((int) (event.getRawY() - downY)) > 5)
clickormove = false;
else
clickormove = true;
break;
}
return false;
}
});
movebtn.setOnClickListener(new View.OnClickListener() {//設置按鈕被點擊的監聽器
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (clickormove)
Toast.makeText(MainActivity.this, "hello,您觸發了默認的點擊擡起事件",
Toast.LENGTH_SHORT).show();
}
});
}
}
這個效果雖然簡陋,但是大家的智慧是無限的,後續的擴展優化還是靠大家自己去實現.
項目直達下載通道爲:簡單的可以移動的Button
如有問題請多指正,您的指正使我更我正確的前行.