亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android?WindowManger實(shí)現(xiàn)桌面懸浮窗功能

 更新時(shí)間:2023年04月28日 14:15:23   作者:_小馬快跑  
這篇文章主要介紹了Android?WindowManger實(shí)現(xiàn)桌面懸浮窗功能,他們基本都是在Activity之上顯示的,如果想實(shí)現(xiàn)在桌面顯示的懸浮窗效果,需要用到WindowManager來(lái)實(shí)現(xiàn)了,需要的朋友可以參考下

如果想實(shí)現(xiàn)一個(gè)在桌面顯示的懸浮窗,用DialogPopupWindow、Toast等已經(jīng)不能實(shí)現(xiàn)了,他們基本都是在Activity之上顯示的,如果想實(shí)現(xiàn)在桌面顯示的懸浮窗效果,需要用到WindowManager來(lái)實(shí)現(xiàn)了。

效果圖

使用WindowManager實(shí)現(xiàn)

  • 添加一個(gè)懸浮窗:
        sys_view = new SmallWindowView(mContext);
        sys_view.setText("50%");
        sys_view.setOnTouchListener(this);
        windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        int screenWidth = 0, screenHeight = 0;
        if (windowManager != null) {
            //獲取屏幕的寬和高
            Point point = new Point();
            windowManager.getDefaultDisplay().getSize(point);
            screenWidth = point.x;
            screenHeight = point.y;
            layoutParams = new WindowManager.LayoutParams();
//            layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
//            layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
            layoutParams.width = 200;
            layoutParams.height = 200;
            //設(shè)置type
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                //26及以上必須使用TYPE_APPLICATION_OVERLAY   @deprecated TYPE_PHONE
                layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
            } else {
                layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
            }
            //設(shè)置flags
            layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
            layoutParams.gravity = Gravity.START | Gravity.TOP;
            //背景設(shè)置成透明
            layoutParams.format = PixelFormat.TRANSPARENT;
            layoutParams.x = screenWidth;
            layoutParams.y = screenHeight / 2;
            //將View添加到屏幕上
            windowManager.addView(sys_view, layoutParams);
        }
  • 更新懸浮窗位置:
windowManager.updateViewLayout(sys_view, layoutParams);
  • 關(guān)閉懸浮窗:
windowManager.removeView(sys_view);

通過(guò)上面的代碼就可以實(shí)現(xiàn)一個(gè)桌面懸浮窗功能了。

注意:在6.0以上,需要在Manifest.xml中聲明 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />權(quán)限并且在開(kāi)啟懸浮窗時(shí)動(dòng)態(tài)判斷權(quán)限,如果沒(méi)有此權(quán)限需要跳到設(shè)置頁(yè)面去設(shè)置,看下官方文檔的說(shuō)明:

SYSTEM_ALERT_WINDOW

分析

1、添加懸浮窗: 通過(guò)Context.getSystemService(Context.WINDOW_SERVICE)獲得一個(gè)WindowManager(以下簡(jiǎn)稱(chēng)VM), VM是外界訪問(wèn)Window的入口,ActivityDialog、Toast等其視圖都是依附在Window之上的,WindowView的直接管理者,VM繼承自ViewManager,其添加、刷新、刪除方法也是來(lái)自ViewManager:

public interface ViewManager
{   public void addView(View view, ViewGroup.LayoutParams params);
    public void updateViewLayout(View view, ViewGroup.LayoutParams params);
    public void removeView(View view);
}

VM有一個(gè)靜態(tài)內(nèi)部類(lèi)WindowManager.LayoutParams ,Window的各個(gè)屬性在這個(gè)內(nèi)部類(lèi)中設(shè)置:

  • LayoutParams.TYPE 如果TargetSdkVersion<26 ,那么可以直接使用LayoutParams.TYPE_PHONE或者LayoutParams.TYPE_SYSTEM_ALERT,在TargetSdkVersion>=26時(shí),TYPE_PHONETYPE_SYSTEM_ALERT都已經(jīng)廢棄了,需要使用TYPE_APPLICATION_OVERLAY來(lái)標(biāo)識(shí)TYPE
  • LayoutParams.FLAGS FLAGS表示Window的屬性,通過(guò)FLAGS可以控制Window的顯示特性,常用的幾個(gè)特性: LayoutParams.FLAG_NOT_TOUCH_MODAL : 使用了此標(biāo)識(shí),可以將點(diǎn)擊事件傳遞到懸浮窗以外的區(qū)域,反之其他區(qū)域的Window將接收不到事件。 LayoutParams.FLAG_NOT_FOCUSABLE : 表示懸浮窗Window不需要獲取焦點(diǎn),也不需要獲取各種輸入事件,事件會(huì)直接傳遞給下層的具有焦點(diǎn)的Window LayoutParams.FLAG_SHOW_WHEN_LOCKED : 此模式可以讓Window顯示在鎖屏的界面上
  • LayoutParams.FORMAT 懸浮窗Window的背景格式,一般設(shè)置成PixelFormat.TRANSPARENT透明即可
  • LayoutParams.X & LayoutParams.Y 懸浮窗Window在屏幕上的坐標(biāo)值,可以根據(jù)X&Y的值來(lái)刷新Window在屏幕上的位置
  • LayoutParams.Width & LayoutParams.Height 懸浮窗Window的寬度和高度

2、更新懸浮窗位置: 在ViewOnTouchEvent中或OnTouch中更新layoutParams.xlayoutParams.y的值并通過(guò)windowManager.updateViewLayout()重新設(shè)置懸浮窗Window在屏幕中的位置,如下:

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int mInScreenX = (int) event.getRawX();
        int mInScreenY = (int) event.getRawY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastX = (int) event.getRawX();
                mLastY = (int) event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                layoutParams.x += mInScreenX - mLastX;
                layoutParams.y += mInScreenY - mLastY;
                mLastX = mInScreenX;
                mLastY = mInScreenY;
                windowManager.updateViewLayout(sys_view, layoutParams);
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

3、刪除懸浮窗: 刪除比較簡(jiǎn)單,直接調(diào)用windowManager.removeView(view)viewWindow中刪除即可。

問(wèn)題

6.0以上使用時(shí),需要?jiǎng)討B(tài)申請(qǐng)?jiān)搼腋〈皺?quán)限,如下:

//判斷有沒(méi)有懸浮窗權(quán)限,沒(méi)有去申請(qǐng)
if(!Settings.canDrawOverlays(context)){
     Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:" + context.getPackageName()));
     context.startActivityForResult(intent, REQUEST_CODE);
}
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_CODE:
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return;
                if (!WindowUtil.canOverDraw(this)) {
                    toast("懸浮窗權(quán)限未開(kāi)啟,請(qǐng)?jiān)谠O(shè)置中手動(dòng)打開(kāi)");
                    return;
                }
                WindowController.getInstance().showThumbWindow();
                break;
        }
    }

通過(guò)Settings.canDrawOverlays(context)判斷是否有懸浮窗權(quán)限,如果沒(méi)有,跳轉(zhuǎn)到設(shè)置頁(yè)面去設(shè)置,并在onActivityResult ()中得到申請(qǐng)結(jié)果,看似很完美,但在實(shí)際測(cè)試中,發(fā)現(xiàn)在8.0以上的手機(jī)上有問(wèn)題,即使在設(shè)置中同意了權(quán)限,8.0的手機(jī)Settings.canDrawOverlays(context)總是返回false,不過(guò)在關(guān)閉頁(yè)面重新調(diào)用此方法時(shí),又返回的true,感覺(jué)是有一定的延遲,google了一下,發(fā)現(xiàn)別人同樣遇到了這個(gè)問(wèn)題,貌似已經(jīng)給google提交了bug單,可以看此博客: http://paskov.vmsoft-bg.com/settings-candrawoverlays-allays-returns-false-on-android-o/ ,不過(guò)博客中的解決方法用我的8.0手機(jī)(HUAWEI MATE10)依然不起作用,暫時(shí)還沒(méi)深入研究,有解決此問(wèn)題的還希望不吝賜教。

以上例子的源碼地址:https://github.com/crazyqiang

參考

【1】developer.android.com/reference/a…

到此這篇關(guān)于Android WindowManger實(shí)現(xiàn)桌面懸浮窗功能的文章就介紹到這了,更多相關(guān)Android桌面懸浮窗內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論