Android中使用WindowManager在介面佈局上新增浮動視窗
阿新 • • 發佈:2019-02-01
如果大家看過一些遊戲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")); } }