项目中需要一个刷新的按钮,不愿意再去循规守矩,想了想决定要弄一个可以移动的按钮来替代之前的固定按钮:
首先的问题就是怎么让控件可以移动呢?
移动的话肯定就是咱们给按钮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
如有问题请多指正,您的指正使我更我正确的前行.