Android仿IOS AssistiveTouch(悬浮框的运用)

前言

前面开源了一篇关于“MVP+RxJava+Retrofit+okhttp实现视频+新闻客户端”的项目阐述了Android项目从零到上线的全过程,反响还不错。最近把以前做的一个仿ios AssistiveTouch(悬浮框的运用)的项目整理了一下。

项目主要功能模块

《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);//添加窗口

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这个辅助服务,基本可以满足自动抢红包的功能,但是有些逻辑需要优化,比如,拆完一个红包后,必须手动点击返回键,才能进行下一次自动抢红包。感谢CodeBoy微信抢红包外挂的作者:英文名:Leon 个人博客:http://www.happycodeboy.com Email:codeboy2013@gmail.com。github上面有详细的教程,想了解的可以自己去github。

其它

其它功能模块就不做详细介绍了,需要了解的可以去github:仿ios AssistiveTouch(悬浮框的运用),别忘了star支持下作者

本文作者:Rance935本文出处:Android仿IOS AssistiveTouch(悬浮框的运用)转载请在开头注明作者详细信息和本文出处
欢迎关注我的微信公众号和QQ群,分享Android 开发和互联网内容
Android技术分享:群号534813930
微信号:androidparks
公众号:AndroidParks

《Android仿IOS AssistiveTouch(悬浮框的运用)》

    原文作者:Rance935
    原文地址: https://www.jianshu.com/p/e5611a252a40
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞