android 可移動懸浮框的實現
阿新 • • 發佈:2018-12-27
整個Android的視窗機制是基於一個叫做 WindowManager,這個介面可以新增view到螢幕,也可以從螢幕刪除view。它面向的物件一端是螢幕,另一端就是View,直接忽略我們以前的Activity或者Dialog之類的東東。其實我們的Activity或者Diolog底層的實現也是通過WindowManager,這個 WindowManager是全域性的,整個系統就是這個唯一的東東。它是顯示View的最底層了。
WindowManager主要用來管理視窗的一些狀態、屬性、view增加、刪除、更新、視窗順序、訊息收集和處理等。通過Context.getSystemService(Context.WINDOW_SERVICE)的方式可以獲得WindowManager的例項.
WindowManager繼承自ViewManager,裡面涉及到視窗管理的三個重要方法,分別是:
* addView();
* updateViewLayout();
* removeView();
效果圖如下:
可以移動的懸浮框實現程式碼如下:
[java] view plaincopyprint?- publicclass WindowManageDemoActivity extends Activity {
- private WindowManager mWindowManager;
-
private WindowManager.LayoutParams param;
- private FloatView mLayout;
- /** Called when the activity is first created. */
- @Override
- publicvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- showView();
- }
- privatevoid showView(){
-
mLayout=new
- mLayout.setBackgroundResource(R.drawable.faceback_head);
- //獲取WindowManager
- mWindowManager=(WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
- //設定LayoutParams(全域性變數)相關引數
- param = ((MyApplication)getApplication()).getMywmParams();
- param.type=WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 系統提示型別,重要
- param.format=1;
- param.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 不能搶佔聚焦點
- param.flags = param.flags | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
- param.flags = param.flags | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; // 排版不受限制
- param.alpha = 1.0f;
- param.gravity=Gravity.LEFT|Gravity.TOP; //調整懸浮視窗至左上角
- //以螢幕左上角為原點,設定x、y初始值
- param.x=0;
- param.y=0;
- //設定懸浮視窗長寬資料
- param.width=140;
- param.height=140;
- //顯示myFloatView影象
- mWindowManager.addView(mLayout, param);
- }
- @Override
- publicvoid onDestroy(){
- super.onDestroy();
- //在程式退出(Activity銷燬)時銷燬懸浮視窗
- mWindowManager.removeView(mLayout);
- }
- }
- publicclass FloatView extends View {
- privatefloat mTouchStartX;
- privatefloat mTouchStartY;
- privatefloat x;
- privatefloat y;
- private WindowManager wm=(WindowManager)getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
- private WindowManager.LayoutParams wmParams = ((MyApplication)getContext().getApplicationContext()).getMywmParams();
- public FloatView(Context context) {
- super(context);
- // TODO Auto-generated constructor stub
- }
- @Override
- publicboolean onTouchEvent(MotionEvent event) {
- //獲取相對螢幕的座標,即以螢幕左上角為原點
- x = event.getRawX();
- y = event.getRawY()-25; //25是系統狀態列的高度
- Log.i("currP", "currX"+x+"====currY"+y);
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- //獲取相對View的座標,即以此View左上角為原點
- mTouchStartX = event.getX();
- mTouchStartY = event.getY();
- Log.i("startP", "startX"+mTouchStartX+"====startY"+mTouchStartY);
- break;
- case MotionEvent.ACTION_MOVE:
- updateViewPosition();
- break;
- case MotionEvent.ACTION_UP:
- updateViewPosition();
- mTouchStartX=mTouchStartY=0;
- break;
- }
- returntrue;
- }
- privatevoid updateViewPosition(){
- //更新浮動視窗位置引數
- wmParams.x=(int)( x-mTouchStartX);
- wmParams.y=(int) (y-mTouchStartY);
- wm.updateViewLayout(this, wmParams);
- }
- }
- publicclass MyApplication extends Application {
- /**
- * 建立全域性變數
- * 全域性變數一般都比較傾向於建立一個單獨的資料類檔案,並使用static靜態變數
- *
- * 這裡使用了在Application中新增資料的方法實現全域性變數
- * 注意在AndroidManifest.xml中的Application節點新增android:name=".MyApplication"屬性
- *
- */
- private WindowManager.LayoutParams wmParams=new WindowManager.LayoutParams();
- public WindowManager.LayoutParams getMywmParams(){
- return wmParams;
- }
- }