Android悬浮窗、桌面宠物

1.悬浮窗权限(在AndroidManifest.xml中添加)

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

2.在MainActivity-onCreate()中申请开启悬浮窗权限

Settings.canDrawOverlays(MainActivity.this)

//判断是否能绘制在所有布局上,如果不能则打开Activity申请权限

//悬浮窗权限
if(!Settings.canDrawOverlays(MainActivity.this)){
    //判断是否能绘制在所有布局上
            Toast.makeText(MainActivity.this,"请授权悬浮窗",Toast.LENGTH_SHORT).show();
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName())), 2333);
}

在MainActivity中添加

protected void onActivityResult(int requestCode, int resultCode, Intent data)方法

用于接收权限申请情况,如果用户未授权需要再次申请

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==2333){
            if(!Settings.canDrawOverlays(MainActivity.this)){
                //未获取权限再次请求
                Toast.makeText(MainActivity.this,"请授权悬浮窗",Toast.LENGTH_SHORT).show();
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2333);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

3.创建悬浮窗的xml布局文件

    如:res/layout/itemlayout.xml

4.MainActivity中相关准备

  (1)容器

  (2)屏幕密度

  (3)屏幕尺寸

public class MainActivity extends AppCompatActivity {
    private MyService.MyBinder myBinder=null;
    static Context context;
    static float density;
    static int screenWidth;
    static int screenHeight;
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //悬浮窗权限
        if(!Settings.canDrawOverlays(MainActivity.this)){
            Toast.makeText(MainActivity.this,"请授权悬浮窗",Toast.LENGTH_SHORT).show();
            startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2333);
        }
        //获取屏幕密度
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        density=metrics.density;
        //获取屏幕大小
        DisplayMetrics metrics1=new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics1);
        screenWidth=metrics1.widthPixels;
        screenHeight=metrics1.heightPixels;
        //获取容器
        context=MainActivity.this;
        if(myBinder==null){
           //无绑定连接
           MyConnection myConnection=new MyConnection();
           Intent intent=new Intent(MainActivity.this,MyService.class);
           bindService(intent,myConnection,BIND_AUTO_CREATE);
        }
   }

   public class MyConnection implements ServiceConnection{
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            //连接-触发
            myBinder=(MyService.MyBinder) iBinder;
        }
        public void onServiceDisconnected(ComponentName componentName) {
            //断开连接-触发
            myBinder=null;
        }
    }

    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if(requestCode==2333){
            if(!Settings.canDrawOverlays(MainActivity.this)){
                //未获取权限再次请求
                Toast.makeText(MainActivity.this,"请授权悬浮窗",Toast.LENGTH_SHORT).show();
                startActivityForResult(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName())), 2333);
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
}

5.在服务中创建悬浮窗

依靠WindowManager创建并添加

服务销毁时一定要移除View

Service建议将内容代码添加在重写的onCreate()方法中,不建议添加在构造函数中。

本例写法不建议使用。

public class MyService extends Service {
    private WindowManager windowManager;
    private View view;
    private Context context;
    private float density;//屏幕密度

    public MyService(){
        context=MainActivity.context;
        density=MainActivity.density;
        int screenWidth=MainActivity.screenWidth;
        int screenHeight=MainActivity.screenHeight;

        //1.获取WindowManager
        windowManager= (WindowManager)context.getSystemService(WINDOW_SERVICE);
        //2.充气View
        view= LayoutInflater.from(context).inflate(R.layout.itemlayout,null);
        //3.WindowManager布局参数
        WindowManager.LayoutParams layoutParams=new WindowManager.LayoutParams();
        
        //判断版本   设置类型为悬浮窗使其可覆盖所有应用且不受限于当前Activity
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        layoutParams.format = PixelFormat.RGBA_8888;//设置颜色存储方式
        //设置不可触碰(触碰后传递给下一层)| 不用获焦点(使周围空白处操作不受影响)
        layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        layoutParams.gravity = Gravity.LEFT | Gravity.TOP;//起始位置(重力)
        //单位px 即100dp转成px +0.5f是为了四舍五入时不出0     虚拟像素(dp)*屏幕密度(density)=实际像素(px)
        layoutParams.width=(int) (100*density+0.5f);
        layoutParams.height=(int)(100*density+0.5f);
        layoutParams.x=(int) ((screenWidth-100*density)/2);
        layoutParams.y=(int) ((screenHeight-100*density)/2);

        //添加View
        windowManager.addView(view,layoutParams);
          
        //为view添加监听(用于拖拽)
        view.setOnTouchListener(new View.OnTouchListener() {
            private int x,y;
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        x = (int) motionEvent.getRawX();
                        y = (int)motionEvent.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int nowX = (int) motionEvent.getRawX();
                        int nowY = (int) motionEvent.getRawY();
                        int movedX = nowX - x;
                        int movedY = nowY - y;
                        x = nowX;
                        y = nowY;
                        layoutParams.x = layoutParams.x + movedX;
                        layoutParams.y = layoutParams.y + movedY;

                        // ***更新悬浮窗控件布局***
                        windowManager.updateViewLayout(view, layoutParams);
                        break;
                    default:
                        break;
                }
                return true;//返回了ture,则代表touch事件已处理用户的该次行为,不需要其他事件处理器进行处理,就不再将事件进行传递。如果返回了false,则代表未处理,需要将事件传递出去。
            }
        });
    }

    public void onDestroy() {
        //服务销毁时一定要移除View
        windowManager.removeView(view);
        super.onDestroy();
    }



    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    
    public class MyBinder extends Binder {

    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android桌面悬浮是一种在Android手机或平板电脑的桌面上显示的浮动口。它可以在其他应用程序之上显示,并且可以在用户使用其他应用程序时保持可见。悬浮可以用来显示通知、快捷操作、实时信息等等,为用户提供更方便的操作和查看方式。 要实现Android桌面悬浮,你可以使用Android的WindowManager类。首先,你需要在你的应用程序中声明SYSTEM_ALERT_WINDOW权限,以便能够在其他应用程序之上显示悬浮。然后,你可以使用WindowManager来创建和管理悬浮。 以下是一个简单的示例代码,演示如何创建一个简单的悬浮: ```java // 获取WindowManager对象 WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 创建一个悬浮口布局参数 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); // 设置悬浮口类型为系统级别的口 layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; // 设置悬浮口的宽高 layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; // 设置悬浮口的位置 layoutParams.gravity = Gravity.TOP | Gravity.LEFT; layoutParams.x = 100; layoutParams.y = 100; // 创建一个ImageView作为悬浮口的内容 ImageView imageView = new ImageView(this); imageView.setImageResource(R.drawable.icon); // 将ImageView添加到悬浮口中 windowManager.addView(imageView, layoutParams); ``` 以上代码创建了一个包含一个图标的悬浮口,并将其添加到屏幕上。你可以根据自己的需求修改悬浮口的内容和样式。记得在不需要悬浮口时,调用`windowManager.removeView(imageView)`来移除悬浮口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在下嗷呜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值