使用WindowManager创建可拖动的悬浮按钮

来源:互联网 发布:中国新歌声网络直播权 编辑:程序博客网 时间:2024/03/29 03:18
场景描述:
界面上有一个浮动按钮,可以用手指拖动,点击该按钮触发事件,我这里是启动扫描,留了一个空实现。
private WindowManager wm;private View view;// 浮动按钮/** * 添加悬浮View * @param paddingBottom 悬浮View与屏幕底部的距离 */protected void createFloatView(int paddingBottom) {int w = 200;// 大小wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);view = getLayoutInflater().inflate(R.layout.floatview, null);final WindowManager.LayoutParams params = new WindowManager.LayoutParams();params.type = LayoutParams.TYPE_BASE_APPLICATION;// 所有程序窗口的“基地”窗口,其他应用程序窗口都显示在它上面。params.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL| LayoutParams.FLAG_NOT_FOCUSABLE;params.format = PixelFormat.TRANSLUCENT;// 不设置这个弹出框的透明遮罩显示为黑色params.width = w;params.height = w;params.gravity = Gravity.TOP | Gravity.LEFT;int screenWidth = getResources().getDisplayMetrics().widthPixels;int screenHeight = getResources().getDisplayMetrics().heightPixels;params.x = screenWidth - w;params.y = screenHeight - w - paddingBottom;view.setBackgroundColor(Color.TRANSPARENT);view.setVisibility(View.VISIBLE);view.setOnTouchListener(new OnTouchListener() {// 触屏监听float lastX, lastY;int oldOffsetX, oldOffsetY;int tag = 0;// 悬浮球 所需成员变量@Overridepublic boolean onTouch(View v, MotionEvent event) {final int action = event.getAction();float x = event.getX();float y = event.getY();if (tag == 0) {oldOffsetX = params.x; // 偏移量oldOffsetY = params.y; // 偏移量}if (action == MotionEvent.ACTION_DOWN) {lastX = x;lastY = y;} else if (action == MotionEvent.ACTION_MOVE) {params.x += (int) (x - lastX) / 3; // 减小偏移量,防止过度抖动params.y += (int) (y - lastY) / 3; // 减小偏移量,防止过度抖动tag = 1;wm.updateViewLayout(view, params);} else if (action == MotionEvent.ACTION_UP) {int newOffsetX = params.x;int newOffsetY = params.y;// 只要按钮一动位置不是很大,就认为是点击事件if (Math.abs(oldOffsetX - newOffsetX) <= 20&& Math.abs(oldOffsetY - newOffsetY) <= 20) {onFloatViewClick();} else {tag = 0;}}return true;}});wm.addView(view, params);}/** * 点击浮动按钮触发事件,需要override该方法 */protected void onFloatViewClick() {}/** * 将悬浮View从WindowManager中移除,需要与createFloatView()成对出现 */protected void removeFloatView() {if (wm != null && view != null) {wm.removeViewImmediate(view);//wm.removeView(view);//不要调用这个,WindowLeakedview = null;wm = null;}}/** * 隐藏悬浮View */protected void hideFloatView() {if (wm != null && view != null&&view.isShown()) {view.setVisibility(View.GONE);}}/** * 显示悬浮View */protected void showFloatView(){if (wm != null && view != null&&!view.isShown()) {view.setVisibility(View.VISIBLE);}}



http://blog.csdn.net/manymore13
import com.mobovip.bgr.R;import android.content.Context;import android.graphics.PixelFormat;import android.graphics.Rect;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.util.Log;import android.view.Gravity;import android.view.MotionEvent;import android.view.WindowManager;import android.view.WindowManager.LayoutParams;import android.widget.ImageView;/** * @author manymore13 * @Blog <a *       href="http://blog.csdn.net/manymore13">http://blog.csdn.net/manymore13 *       </a> * @version 1.0 floatView = new FloatView(this); // 创建窗体 *          floatView.setOnClickListener(this); // *          设置事件,你需要实现FloatView里的onclick接口 floatView.show(); // 显示该窗体 *          floatView.hide(); // 隐藏窗体 */public class FloatView extends ImageView {private Context c;private float mTouchX;private float mTouchY;private float x;private float y;private int startX;private int startY;private int imgId = R.drawable.ic_launcher;private int controlledSpace = 20;private int screenWidth;private int screenHeight;boolean isShow = false;private OnClickListener mClickListener;private WindowManager windowManager;private WindowManager.LayoutParams windowManagerParams = new WindowManager.LayoutParams();public FloatView(Context context, AttributeSet attrs) {super(context, attrs);}public FloatView(Context c) {super(c);initView(c);}// 初始化窗体public void initView(Context c) {windowManager = (WindowManager) c.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);DisplayMetrics dm=getResources().getDisplayMetrics();screenWidth = dm.widthPixels;screenHeight = dm.heightPixels;this.setImageResource(imgId);windowManagerParams.type = LayoutParams.TYPE_PHONE;windowManagerParams.format = PixelFormat.RGBA_8888; // 背景透明windowManagerParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL| LayoutParams.FLAG_NOT_FOCUSABLE;// 调整悬浮窗口至左上角,便于调整坐标windowManagerParams.gravity = Gravity.LEFT | Gravity.TOP;// 以屏幕左上角为原点,设置x、y初始值windowManagerParams.x = 0;windowManagerParams.y = screenHeight>>1;// 设置悬浮窗口长宽数据windowManagerParams.width = LayoutParams.WRAP_CONTENT;windowManagerParams.height = LayoutParams.WRAP_CONTENT;}public void setImgResource(int id) {imgId = id;}@Overridepublic boolean onTouchEvent(MotionEvent event) {x = event.getRawX();y = event.getRawY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {mTouchX = event.getX();mTouchY = event.getY();startX = (int) event.getRawX();startY = (int) event.getRawY();break;}case MotionEvent.ACTION_MOVE: {updateViewPosition();break;}case MotionEvent.ACTION_UP: {if (Math.abs(x - startX) < controlledSpace&& Math.abs(y - startY) < controlledSpace) {if (mClickListener != null) {mClickListener.onClick(this);}}//Log.i("tag", "x=" + x + " startX+" + startX + " y=" + y//+ " startY=" + startY);if (x <= screenWidth / 2) {x = 0;} else {x = screenWidth;}updateViewPosition();break;}}return super.onTouchEvent(event);}// 隐藏该窗体public void hide() {if (isShow) {windowManager.removeView(this);isShow = false;}}// 显示该窗体public void show() {if (isShow == false) {windowManager.addView(this, windowManagerParams);isShow = true;}}@Overridepublic void setOnClickListener(OnClickListener l) {this.mClickListener = l;}private void updateViewPosition() {// 更新浮动窗口位置参数windowManagerParams.x = (int) (x - mTouchX);windowManagerParams.y = (int) (y - mTouchY);windowManager.updateViewLayout(this, windowManagerParams); // 刷新显示}}




一个Android布局可以拖动排序子控件:RearrangeableLayout
https://github.com/rajasharan/RearrangeableLayout
0 0
原创粉丝点击