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

场景描述:
界面上有一个浮动按钮,可以用手指拖动,点击该按钮触发事件,我这里是启动扫描,留了一个空实现。

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;// 悬浮球 所需成员变量

			@Override
			public 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);//不要调用这个,WindowLeaked
			view = 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;
	}

	@Override
	public 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;
		}

	}

	@Override
	public 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
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值