1. 程式人生 > >Android中使用WindowManager在介面佈局上新增浮動視窗

Android中使用WindowManager在介面佈局上新增浮動視窗

如果大家看過一些遊戲sdk中的功能,現在大多都有懸浮視窗這個功能。如360,uc等等。。

這裡不需要定義service,只需要這隻WindowsManager中的LayoutParams就可以達到這個懸浮框可以繫結介面的功能。

話不多說,先上程式碼:

public class FloatBox extends BasicView {
	LinearLayout mFloatLayout;
	FloatButton floatView;
	String TAG = "FloatBox";
	WindowManager.LayoutParams windowParams;
	WindowManager mWindowManager;
	float mStartX = 0;
	float mStartY = 0;

	public FloatBox(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
	}

	public FloatBox(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	public FloatBox(Context context, String str) {
		super(context, str);
		// TODO Auto-generated constructor stub
	}

	public FloatBox(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void init(Context context) {
		// TODO Auto-generated method stub
		initWindowBox(context);
	}
	

	private void initViewBox(Context context){
		mFloatLayout = new LinearLayout(context);
		LinearLayout.LayoutParams mFloatLayoutLP = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		mFloatLayout.setLayoutParams(mFloatLayoutLP);
		mFloatLayout.setOrientation(LinearLayout.VERTICAL);
		floatView = new FloatButton(context);
		LinearLayout.LayoutParams floatViewLp = new LinearLayout.LayoutParams(
				MetricUtil.getDip(context, 50), MetricUtil.getDip(context, 50));
		floatView.setLayoutParams(floatViewLp);
		mFloatLayout.addView(floatView);
	}
	/**
	 * 用windowManager來新增box
	 * @param context
	 */
	private void initWindowBox(Context context){
		windowParams = new WindowManager.LayoutParams();
		mWindowManager = (WindowManager) context
				.getSystemService(context.WINDOW_SERVICE);
		// 設定window type 這裡使用的type是1000 - 2000之間的,需要繫結token
		// 如果使用2000以上的型別的話,一般適用於桌面上的懸浮窗.
		windowParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
		windowParams.format = PixelFormat.RGBA_8888;
		windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
		windowParams.gravity = Gravity.LEFT | Gravity.TOP;
		// 以螢幕左上角為原點,設定x、y初始值,相對於gravity
		windowParams.x = 0;
		windowParams.y = 0;
		// 長寬設定
		windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
		windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

		mFloatLayout = new LinearLayout(context);
		LinearLayout.LayoutParams mFloatLayoutLP = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		mFloatLayout.setLayoutParams(mFloatLayoutLP);
		mFloatLayout.setOrientation(LinearLayout.VERTICAL);
		
		// 繫結token
		windowParams.token = mFloatLayout.getWindowToken();
		// 新增layout
		mWindowManager.addView(mFloatLayout, windowParams);
		floatView = new FloatButton(context);
		LinearLayout.LayoutParams floatViewLp = new LinearLayout.LayoutParams(
				MetricUtil.getDip(context, 50), MetricUtil.getDip(context, 50));
		floatView.setLayoutParams(floatViewLp);
		mFloatLayout.addView(floatView);
		mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
				View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
				.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
		Log.i(TAG, "Width/2--->" + floatView.getMeasuredWidth() / 2);
		Log.i(TAG, "Height/2--->" + floatView.getMeasuredHeight() / 2);

		floatView.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				System.out.println("onTouch ");
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					
					break;
				case MotionEvent.ACTION_MOVE:
					//加一個值,更方便點選
					if(Math.abs(event.getRawX() - mStartX) > 30){
						mStartX = event.getRawX();	
					}
					if(Math.abs(event.getRawY() - mStartY) > 30){
						mStartY = event.getRawY();
					}
					updatePosition();
					break;
				case MotionEvent.ACTION_UP:
					
					break;
				default:
					break;
				}
//				if(event.getAction() == MotionEvent.ACTION_MOVE){
//			
//				Log.i(TAG, "event.getRawX()--->" + event.getRawX());
//				Log.i(TAG, "event.getRawX()--->" + event.getRawY());
//				mStartX = event.getRawX();
//				mStartY = event.getRawY();
//				}else if(event.getAction() == MotionEvent.ACTION_UP){
//					return true;
//				}
				return false;
			}
		});
		final Context mcontext = context;
		floatView.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Toast.makeText(mcontext, "floatView onclick", 1000).show();
				return;
			}
		});
	}
	
	
	private void updatePosition(){
		windowParams.x = (int) (mStartX - floatView
				.getMeasuredWidth() / 2);
		windowParams.y = (int) (mStartY - floatView
				.getMeasuredHeight() / 2);
		// refresh
		Log.i(TAG, "x--->" + windowParams.x);
		Log.i(TAG, "y--->" + windowParams.y);
		mWindowManager.updateViewLayout(mFloatLayout, windowParams);
	}

	public void showBox() {
		mFloatLayout.setVisibility(View.VISIBLE);
	}

	public void hideBox() {
		mFloatLayout.setVisibility(View.GONE);
	}

	public void removeBox() {
		mWindowManager.removeView(mFloatLayout);
	}

}


然後,以下是自定義button的程式碼:
public class FloatButton extends Button {

	public FloatButton(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		init();
	}

	public FloatButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		init();
	}

	public FloatButton(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		init();
	}

	private void init() {
		Decorator.setStateImage(this,
				ResourceLoader.getBitmapDrawable("appicon_normal.png"),
				ResourceLoader.getBitmapDrawable("appicon_hover.png"),
				ResourceLoader.getBitmapDrawable("appicon_normal.png"));
	}
}