Android仿IOS AssistiveTouch(懸浮框的運用)

yama0823 8年前發布 | 14K 次閱讀 安卓開發 Android開發 移動開發

前言

前面開源了一篇關于“MVP+RxJava+Retrofit+okhttp實現視頻+新聞客戶端”的項目闡述了 Android項目從零到上線的全過程 ,反響還不錯。最近把以前做的一個 仿ios AssistiveTouch(懸浮框的運用) 的項目整理了一下。

項目主要功能模塊

主要功能

如圖所示:

1、系統設置(回到主頁、一鍵鎖屏、手電筒)

2、工具助手(自動搶紅包、應用管理、小火箭垃圾清理)

3、WindowManager懸浮框

WindowManager懸浮框

本文主要介紹WindowManager懸浮框的運用。浮動窗大家應該都不陌生,360、應用寶之類的小浮動窗口運用的就是WindowManager懸浮框。

原理

1、懸浮框的顯示:通過getSystemService(Context.WINDOW_SERVICE)得到WindowManager,調用WindowManager的addview(View view, WindowManager.LayoutParams mLayoutParams)進行顯示

//獲取WindowManager
wManager = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
mParams = new WindowManager.LayoutParams(); 
//適配小米、魅族等手機需要懸浮框權限的問題,可繞過授權
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT)
{    wmParams.type = LayoutParams.TYPE_PHONE;
} else {
wmParams.type = LayoutParams.TYPE_TOAST; } // 支持透明 //mParams.format = PixelFormat.RGBA_8888; mParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 焦點 mParams.width = 490; //窗口的寬和高 mParams.height = 160; mParams.x = 0; //窗口位置的偏移量 mParams.y = 0; /**

  • 這里的flags也很關鍵 *代碼實際是wmParams.flags |= FLAG_NOT_FOCUSABLE;
  • 40的由來是wmParams的默認屬性(32)+ FLAG_NOT_FOCUSABLE(8) */ mParams.flags=40; //窗口的透明度mParams.alpha = 0.1f; myView = new MyView(this); wManager.addView(myView, mParams);//添加窗口</code></pre>

    2、懸浮框的移動:監聽view的OnTouchListener通過WindowManager的updateViewLayout(Context mContext, WindowManager.LayoutParams mLayoutParams)修改mLayoutParams的mLayoutParams.x和mLayoutParams.y從而更新浮動窗的位置

    private OnTouchListener mTouchListener = new OnTouchListener() {    
    float lastX, lastY;    int paramX, paramY;    
    public boolean onTouch(View v, MotionEvent event) {       
      final int action = event.getAction();        
      float x = event.getRawX();        
      float y = event.getRawY();       
      if (mTag == 0) {            
         mOldOffsetX = mViewEventMParams.x; // 偏移量            
         mOldOffsetY = mViewEventMParams.y; // 偏移量        
      }        
      switch (action) {            
         case MotionEvent.ACTION_DOWN:                
              motionActionDownEvent(x, y);                
         break;            
         case MotionEvent.ACTION_MOVE:                
              motionActionMoveEvent(x, y);                
         break;            
         case MotionEvent.ACTION_UP:                
              motionActionUpEvent(x, y);                
         break;            
         default:                
         break;        
         }        
         return true;    
    }    
    private void motionActionDownEvent(float x, float y) {        
      lastX = x;        
      lastY = y;        
      paramX = mViewEventMParams.x;        
      paramY = mViewEventMParams.y;    
    }    
    private void motionActionMoveEvent(float x, float y) {        
      int dx = (int) (x - lastX);       
      int dy = (int) (y - lastY);        
      mViewEventMParams.x = paramX + dx;       
      mViewEventMParams.y = paramY + dy;       
      mTag = 1;        
     // 更新懸浮窗位置        
    mWManager.updateViewLayout(mTouchView, mViewEventMParams);   
    }    
    private void motionActionUpEvent(float x, float y) {        
      int newOffsetX = mViewEventMParams.x;       
      int newOffsetY = mViewEventMParams.y;        
      if (mOldOffsetX == newOffsetX && mOldOffsetY == newOffsetY) {            
      updateSettingTableView();            
      mPopuWin = new PopupWindow(mSettingTable, LayoutParams.WRAP_CONTENT,        
      LayoutParams.WRAP_CONTENT);            
      mPopuWin.setTouchInterceptor(new OnTouchListener() {                
         public boolean onTouch(View v, MotionEvent event) {                    
             if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {                        
                  hideSettingTable();                        
         return true;                   
            }                    
      return false;                
      }            
    });           
    mPopuWin.setBackgroundDrawable(new BitmapDrawable());            
    mPopuWin.setTouchable(true);            
    mPopuWin.setFocusable(true);            
    mPopuWin.setOutsideTouchable(true);            
    mPopuWin.setContentView(mSettingTable);            
    if (Math.abs(mOldOffsetX) > midX) {                
      if (mOldOffsetX > 0) {                    
         mOldOffsetX = midX;                
      } else {                    
         mOldOffsetX = -midX;               
      }            
    }            
    if (Math.abs(mOldOffsetY) > midY) {                
      if (mOldOffsetY > 0) {                    
         mOldOffsetY = midY;                
      } else {                    
         mOldOffsetY = -midY;                
      }            
    }            
    mPopuWin.setAnimationStyle(R.style.AnimationPreview);            
    mPopuWin.setFocusable(true);            
    mPopuWin.update();            
    mPopuWin.showAtLocation(mTouchView, Gravity.CENTER, -mOldOffsetX, -mOldOffsetY);            
    // TODO              
    mIconImageView.setBackgroundDrawable(getResources().getDrawable(R.drawable.transparent));              
    catchSettingTableDismiss();        
    } else {           
      mTag = 0;       
    }    
    }};

    3、懸浮框的刪除:調用WindowManager的removeView(View view)

    自動搶紅包

    原理就是根據關鍵字找到相應的View, 然后自動點擊。主要是用到AccessibilityService這個輔助服務,基本可以滿足自動搶紅包的功能,但是有些邏輯需要優化,比如,拆完一個紅包后,必須手動點擊返回鍵,才能進行下一次自動搶紅包。

     

     

     

 本文由用戶 yama0823 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!