Android 可拖動的懸浮按鈕
阿新 • • 發佈:2018-12-20
這是控制元件的主程式碼,在你的專案裡面,新建一個同名的類,把程式碼直接複製進去就能用了。另外,這個類裡面引用了工具類的一些程式碼。工具類在這個主類的原始碼下面也有貼出,直接把工具類的相關程式碼,複製到你自己的工具類裡就行了,有問題可以加我QQ諮詢:326257241。
/**
* @ClassName: FloatDragView
* @Description: 可拖動的懸浮按鈕
* @Author: 阿榮
* @Date:2016/3/18
*/
public class FloatDragView {
private Activity context; // 上下文
private ImageView mImageView; // 可拖動按鈕
private static int mScreenWidth = -1; //螢幕的寬度
private static int mScreenHeight = -1; //螢幕的高度
private int relativeMoveX; // 控制元件相對螢幕左上角移動的位置X
private int relativeMoveY; // 控制元件相對螢幕左上角移動的位置Y
private boolean isIntercept = false; // 是否截斷touch事件
private int startDownX; // 按下時的位置控制元件相對螢幕左上角的位置X
private int startDownY; // 按下時的位置控制元件距離螢幕左上角的位置Y
private static int[] lastPosition; // 用於記錄上一次的位置(座標0對應x,座標1對應y)
/**
* @param context 上下文
* @param mViewContainer 可拖動按鈕要存放的對應的Layout
* @param clickListener 可拖動按鈕的點選事件
*/
public static ImageView addFloatDragView(Activity context , RelativeLayout mViewContainer,
View.OnClickListener clickListener) {
FloatDragView floatDragView = new FloatDragView(context);
ImageView imageView = floatDragView.getFloatDragView(clickListener);
mViewContainer.addView(imageView);
return imageView;
}
// 初始化例項
private FloatDragView(Activity context) {
setScreenHW(context);
this.context = context;
lastPosition = new int[]{0,0};
}
// 獲取可拖動按鈕的例項
private ImageView getFloatDragView(View.OnClickListener clickListener) {
if (mImageView != null) {
return mImageView;
} else {
mImageView = new ImageView(context);
mImageView.setClickable(true);
mImageView.setFocusable(true);
mImageView.setImageResource(R.drawable.analyze_btn_selector);
setFloatDragViewParams(mImageView);
mImageView.setOnClickListener(clickListener);
setFloatDragViewTouch(mImageView);
return mImageView;
}
}
// 設定可拖動按鈕的位置引數
private void setFloatDragViewParams(View floatDragView) {
// 記錄最後圖片在窗體的位置
int moveX = lastPosition[0];
int moveY = lastPosition[1];
if (0 != moveX || 0 != moveY) {// 移動後的位置
// 每次移動都要設定其layout,不然由於父佈局可能巢狀listView,當父佈局發生改變沖毀(如下拉重新整理時)則移動的view會回到原來的位置
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lpFeedback.setMargins(moveX, moveY, 0, 0);
floatDragView.setLayoutParams(lpFeedback);
} else {// 初始位置
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lpFeedback.setMargins(0, 0, 20, 218);
lpFeedback.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
lpFeedback.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
floatDragView.setLayoutParams(lpFeedback);
}
}
// 可拖動按鈕的touch事件
private void setFloatDragViewTouch(final ImageView floatDragView) {
floatDragView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(final View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
isIntercept = false;
startDownX = relativeMoveX = (int) event.getRawX();
startDownY = relativeMoveY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int dx = (int) event.getRawX() - relativeMoveX;
int dy = (int) event.getRawY() - relativeMoveY;
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 > mScreenWidth) {
right = mScreenWidth;
left = right - v.getWidth();
}
if (top < 0) {
top = 0;
bottom = top + v.getHeight();
}
if (bottom > mScreenHeight) {
bottom = mScreenHeight;
top = bottom - v.getHeight();
}
v.layout(left, top, right, bottom);
relativeMoveX = (int) event.getRawX();
relativeMoveY = (int) event.getRawY();
break;
case MotionEvent.ACTION_UP:
int lastMoveDx = Math.abs((int) event.getRawX() - startDownX);
int lastMoveDy = Math.abs((int) event.getRawY() - startDownY);
if (5 < lastMoveDx || 5 < lastMoveDy) {// 防止點選的時候稍微有點移動點選事件被攔截了
isIntercept = true;
} else {
isIntercept = false;
}
// 每次移動都要設定其layout,不然由於父佈局可能巢狀listview,
// 當父佈局發生改變沖毀(如下拉重新整理時)則移動的view會回到原來的位置
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lpFeedback.setMargins(v.getLeft(), v.getTop(), 0, 0);
v.setLayoutParams(lpFeedback);
// preferenceUtil.saveInt("moveX", v.getLeft());
// preferenceUtil.saveInt("moveY", v.getTop());
// 設定靠近邊沿的
setImageViewNearEdge(v);
break;
}
return isIntercept;
}
});
}
// 將拖動按鈕移動到邊沿
private void setImageViewNearEdge(final View v) {
if (v.getLeft() < ((Utils.getScreenSize(context).x) / 2)) {
// 設定位移動畫 向左移動控制元件位置
final TranslateAnimation animation = new TranslateAnimation(0, -v.getLeft(), 0, 0);
animation.setDuration(300);// 設定動畫持續時間
animation.setRepeatCount(0);// 設定重複次數
animation.setFillAfter(true);
animation.setRepeatMode(Animation.ABSOLUTE);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation arg0) {
// TODO: 2017/3/1
}
@Override
public void onAnimationRepeat(Animation arg0) {
// TODO: 2017/3/1
}
@Override
public void onAnimationEnd(Animation arg0) {
v.clearAnimation();
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lpFeedback.setMargins(0, v.getTop(), 0, 0);
v.setLayoutParams(lpFeedback);
v.postInvalidateOnAnimation();
lastPosition[0] = 0;
lastPosition[1] = v.getTop();
}
});
v.startAnimation(animation);
} else {
final TranslateAnimation animation = new TranslateAnimation(0, (Utils.getScreenSize(context).x
- v.getLeft() - v.getWidth()), 0, 0);
animation.setDuration(300);// 設定動畫持續時間
animation.setRepeatCount(0);// 設定重複次數
animation.setRepeatMode(Animation.ABSOLUTE);
animation.setFillAfter(true);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation arg0) {
// TODO: 2017/3/1
}
@Override
public void onAnimationRepeat(Animation arg0) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation arg0) {
v.clearAnimation();
RelativeLayout.LayoutParams lpFeedback = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
lpFeedback.setMargins(Utils.getScreenSize(context).x - v.getWidth(), v.getTop(), 0, 0);
v.setLayoutParams(lpFeedback);
v.postInvalidateOnAnimation();
lastPosition[0] =Utils.getScreenSize(context).x - v.getWidth();
lastPosition[1] = v.getTop();
}
});
v.startAnimation(animation);
}
}
// 計算螢幕的實際高寬
private void setScreenHW(Activity context) {
if (mScreenHeight < 0) {
// 減去狀態列高度,否則挨著底部移動,導致圖示變小
Point screen = Utils.getScreenSize(context);
mScreenWidth = screen.x;
mScreenHeight = screen.y - Utils.getStatusBarHeight(context);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
以下是工具類的程式碼
public class Utils {
// 狀態列高度
private static int statusBarHeight = 0;
// 螢幕畫素點
private static final Point screenSize = new Point();
// 獲取螢幕畫素點
public static Point getScreenSize(Activity context) {
if (context == null) {
return screenSize;
}
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
if (wm != null) {
DisplayMetrics mDisplayMetrics = new DisplayMetrics();
Display diplay = wm.getDefaultDisplay();
if (diplay != null) {
diplay.getMetrics(mDisplayMetrics);
int W = mDisplayMetrics.widthPixels;
int H = mDisplayMetrics.heightPixels;
if (W * H > 0 && (W > screenSize.x || H > screenSize.y)) {
screenSize.set(W, H);
}
}
}
return screenSize;
}
// 獲取狀態列高度
public static int getStatusBarHeight(Context context) {
if (statusBarHeight <= 0) {
Rect frame = new Rect();
((Activity) context).getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
statusBarHeight = frame.top;
}
if (statusBarHeight <= 0) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
int x = Integer.parseInt(field.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(x);
} catch (Exception e1) {
e1.printStackTrace();
}
}
return statusBarHeight;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
使用方法
mRootView 就是要出現懸浮按鈕的介面的根view。就是setContentView的View。
FloatDragView.addFloatDragView(this, mRootView, new View.OnClickListener() {
@Override
public void onClick(View view) {
// 點選事件
}
});