美文网首页
悬浮窗适配

悬浮窗适配

作者: 有点健忘 | 来源:发表于2018-08-15 14:34 被阅读14次

    简单记录下悬浮窗的显示,各种适配就不管了,下边帖子有介绍,可以参考
    https://www.jianshu.com/p/2229d4a12269

    下边是点击按钮,弹出一个悬浮窗,默认显示在右边中间,可以手指触摸移动位置。
    ShowFloatingWindow().showView()

    import android.app.AppOpsManager
    import android.content.Context
    import android.graphics.Point
    import android.os.Binder
    import android.os.Build
    import android.provider.Settings
    import android.view.*
    import com.charliesong.demo0327.R
    import android.view.Gravity
    import android.widget.OverScroller
    import android.widget.Toast
    import android.content.Intent
    import android.net.Uri
    import android.support.annotation.RequiresApi
    import com.charliesong.demo0327.base.MyApplication
    
    
    class ShowFloatingWindow(){
    
       private var context:Context= MyApplication.getInstance()
        private  var windowManager:WindowManager= MyApplication.getInstance().getSystemService(Context.WINDOW_SERVICE) as WindowManager
        companion object {
            var showView:View?=null
        }
        var params=WindowManager.LayoutParams()
        val point=Point()//记录手指down的时候params的 x和y值
        //权限检查,不检查的话会崩掉的。
        private fun checkPermission():Boolean{
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                return Settings.canDrawOverlays(context);
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                //AppOpsManager添加于API 19
                return checkOps();
            } else {
                //4.4以下一般都可以直接添加悬浮窗
                return true;
            }
        }
        @RequiresApi(Build.VERSION_CODES.KITKAT)
        private  fun  checkOps():Boolean {
            try {
                val obj = context.getSystemService(Context.APP_OPS_SERVICE);
                if (obj == null) {
                    return false;
                }
                val localClass = obj.javaClass
                val method = localClass.getMethod("checkOp", Integer.TYPE,Integer.TYPE, String::class.java);
                if (method == null) {
                    return false;
                }
                val m = method.invoke(obj, 24,Binder.getCallingUid(),context.getPackageName()) as Int
                //4.4至6.0之间的非国产手机,例如samsung,sony一般都可以直接添加悬浮窗
                return m == AppOpsManager.MODE_ALLOWED ;
            } catch ( e:Exception) {
                e.printStackTrace()
            }
            return false;
        }
    
        private fun applyCommonPermission(context: Context) {
            try {
                val clazz = Settings::class.java
                val field = clazz.getDeclaredField("ACTION_MANAGE_OVERLAY_PERMISSION")
                val intent = Intent(field.get(null).toString())
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                intent.data = Uri.parse("package:" + context.packageName)
                context.startActivity(intent)
            } catch (e: Exception) {
                Toast.makeText(context, "进入设置页面失败,请手动设置", Toast.LENGTH_LONG).show()
            }
    
        }
    
        fun showView(){
            if(!checkPermission()){
                applyCommonPermission(context)
                return
            }
            showView?.apply {
                if(this.parent!=null)
                    windowManager.removeViewImmediate(showView)
            }
            showView=LayoutInflater.from(context).inflate(R.layout.floating_view,null).apply {
                findViewById<View>(R.id.btn_close).setOnClickListener {
                  windowManager.removeView(showView)
                    showView=null
                }
                handleTouch(this)
            }
    
            var tp=WindowManager.LayoutParams.TYPE_TOAST
            if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
                tp=WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            }
             params=WindowManager.LayoutParams().apply {
                x=110
                y=0
                flags=WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                gravity= Gravity.END or Gravity.CENTER;
                width=WindowManager.LayoutParams.WRAP_CONTENT
                height=WindowManager.LayoutParams.WRAP_CONTENT
                type=tp
            }
    
            windowManager.addView(showView,params)
    
        }
    
    
        private fun handleTouch(view: View){
            val listener=object :GestureDetector.SimpleOnGestureListener(){
                override fun onScroll(e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float): Boolean {
    //                println("=======onScroll=========$distanceX===$distanceY=======${params.y}===${e1.rawX}==${e2.rawX}")
                    params.x=point.x+(e1.rawX-e2.rawX).toInt()
                    params.y=point.y-(e1.rawY-e2.rawY).toInt()
                    windowManager.updateViewLayout(view,params)
                    return true
                }
    
                override fun onDown(e: MotionEvent?): Boolean {
                    point.x=params.x
                    point.y=params.y
                    return super.onDown(e)
                }
                override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
                    val overScroller=OverScroller(view.context)
                    overScroller.fling(e2.rawX.toInt(),e2.rawY.toInt(),velocityX.toInt(),velocityY.toInt(),-10000,10000,-10000,10000)
                    overScroller.abortAnimation()
                    params.x=point.x+(e1.rawX-overScroller.currX).toInt()
                    params.y=point.y-(e1.rawY-overScroller.currY).toInt()
                    windowManager.updateViewLayout(view,params)
                    return super.onFling(e1, e2, velocityX, velocityY)
                }
            }
            val guesture=GestureDetector(context,listener)
            view.setOnTouchListener { v, event ->
                guesture.onTouchEvent(event)
                return@setOnTouchListener true
            }
        }
    }
    

    悬浮窗的添加,删除,修改就3个方法

        public void addView(View view, ViewGroup.LayoutParams params);
        public void updateViewLayout(View view, ViewGroup.LayoutParams params);
        public void removeView(View view);
    

    相关文章

      网友评论

          本文标题:悬浮窗适配

          本文链接:https://www.haomeiwen.com/subject/tjuvbftx.html