android 360懸浮框實現原理

通過WindowManageraddView()方法,並設置WindowManager.LayoutParams的相關屬性,就可以往WindowManager中加入所需要的View,而根據WindowManager.LayoutParams屬性不同,也就能實現不同的效果。比如創建系統頂級窗口,實現懸浮窗口效果。如果需要將ViewWindowManager中移除,只需要調用removeView()即可。

下面以一個簡單的例子來解釋一下如何實現懸浮窗口效果。

首先,得到WindoeManager對象:
        WindowManager wManager = getApplicationContext().getSystemService( Context. WINDOW_ SERVICE);

其次,得到WindowManager.LayoutParams對象,爲後續設置相關參數做準備:
        private WindowManager.LayoutParams wmParams=new WindowManager.LayoutParams();

接着,設置相關的窗口布局參數,要實現懸浮窗口效果,主要需要設置的參數有:
        wmParams.type = LayoutParams.TYPE_PHONE; // 設置window type
        wmParams.format = PixelFormat.RGBA_8888; // 設置圖片格式,效果爲背景透明

        /*
        * 下面的flags屬性的效果形同鎖定。 懸浮窗不可觸摸,不接受任何事件,同時不影響後面的事件響應。
        */
        wmParams.flags=LayoutParams.FLAG_NOT_TOUCH_MODAL |
        LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCHABLE;

wmParams.gravity = Gravity.RIGHT| Gravity. CENTER_VERTICAL; // 調整懸浮窗口至右側中間
         // 以屏幕左上角爲原點,設置xy初始值
         wmParams.x = 0;
        wmParams.y = 0;

// 設置懸浮窗口長寬數據
        wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;;
         wmParams.height =WindowManager.LayoutParams.WRAP_CONTENT;;

然後,就可以將需要加到懸浮窗口中的View加入到窗口中了:
        if(view.getParent==null)//如果view沒有被加入到某個父組件中,則加入WindowManager
        wManager.addView(view,wmParams);

其中,view爲需要放到懸浮窗口中的視圖組件。

如果要將其從WindowManager中移除,則可以執行以下語句:
        if(view.getParent()!=null)
        wManager.removeView(view);

最後,還有需要注意的是,如果要用懸浮窗口,需要在AndroidManifest.xml中加入如下的權限:
        <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

  @Override

  public void onStart(Intent intent, int startId) { 

  super.onStart(intent, startId); 

  //通過WindowManager將浮動的窗口添加到屏幕 

  mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 

  mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 

  mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

  mView = (ViewGroup) mInflater.inflate(R.layout.float_window, null); 

  mView.setOnTouchListener(this); 

  mView.setVisibility(View.GONE); 

  mTextView = (TextView) mView.findViewById(R.id.text); 

  mLayoutParams = new WindowManager.LayoutParams(); 

  mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 

  mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 

  mLayoutParams.alpha = (float) 0.99; 

  mLayoutParams.gravity =  Gravity.LEFT | Gravity.TOP; 

  mLayoutParams.x = 10; 

  mLayoutParams.y = 10; 

  mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 

  //使用此類型要額外添加一個權限 

  mLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE; 

  mWindowManager.addView(mView, mLayoutParams); 

  listenActivity(); 

}

  private void listenActivity(){ 

  new Thread(){ 

  public void run(){ 

  List<RunningTaskInfo> taskInfos; 

  //判斷程序是否處於桌面 

  //木有找到比較好的監聽方法,所以用了一個最笨的方法 

  //因爲對相應要求不高,所以每100毫秒檢查一次 

  //有好方法的請留言,不勝感謝 

  try { 

  while(true){ 

  sleep(100); 

  taskInfos = mActivityManager.getRunningTasks (1); 

  if(taskInfos.get(0).topActivity.getPackageName().equals("com.android.launcher") ){ 

  mHandler.sendEmptyMessage(View.VISIBLE); 

  }else{ 

  mHandler.sendEmptyMessage(View.GONE); 

  

  

  } catch (InterruptedException e) { 

  e.printStackTrace(); 

  

  

  }.start(); 

  

  @Override

  public void onDestroy() { 

  mWindowManager.removeView(mView); 

  super.onDestroy(); 

  

  @Override

  public boolean onTouch(View v, MotionEvent event) { 

  switch (event.getAction()){ 

  //此處實現在桌面的拖動 

  case MotionEvent.ACTION_DOWN: 

  xOffset = (int) event.getRawX(); 

  yOffset = (int) event.getRawY(); 

  x = mLayoutParams.x; 

  y = mLayoutParams.y; 

  startTime = System.currentTimeMillis(); 

  break; 

  case MotionEvent.ACTION_MOVE: 

  if ( System.currentTimeMillis() - startTime < 1000 )break; 

  mLayoutParams.x = x + (int) event.getRawX() - xOffset; 

  mLayoutParams.y = y + (int) event.getRawY() - yOffset; 

  mWindowManager.updateViewLayout(mView, mLayoutParams); 

  break; 

  case MotionEvent.ACTION_UP: 

  if (robotMsg%2 == 0){ 

  mTextView.setText("Hello Boy!"); 

  }else{ 

  mTextView.setText("Hello Gril!!"); 

  

  robotMsg ++; 

  break; 

  

  return true; 

  }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章