首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Activity 懸浮顯示:Dialog 主題與 WindowManager 兩種實現方案

     編輯:程式設計綜合問答

需求分析

實現一個 Activity 以**懸浮窗/對話框形式**覆蓋在另一個 Activity 之上,保持底層 Activity 可見(可選模態/非模態)。

方案一:Dialog 主題(最簡單、標準)

1. Manifest 設置主題


<activity 
    android:name=".FloatActivity"
    android:theme="@android:style/Theme.Dialog" 
    <!-- 或 Theme.Holo.Dialog, Theme.Material.Light.Dialog -->
    android:excludeFromRecents="true" 
/>

2. 代碼動態調整尺寸/位置


public class FloatActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_float);
        
        // 設置寬高比例或固定值
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int width = (int)(dm.widthPixels * 0.8);
        int height = (int)(dm.heightPixels * 0.6);
        getWindow().setLayout(width, height);
        
        // 可選:設置背景透明、圓角
        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
    }
}

3. 調用方式


// 在主 Activity 中
Intent intent = new Intent(this, FloatActivity.class);
startActivity(intent); // 像啟動普通 Activity 一樣

方案二:WindowManager 系統級懸浮窗(需權限、真正獨立)

適用於**跨應用、桌面懸浮球、全局覆蓋**場景。

1. 權限聲明


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

2. Service 中添加 View


public class FloatWindowService extends Service {
    private WindowManager wm;
    private View floatView;
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        floatView = LayoutInflater.from(this).inflate(R.layout.float_layout, null);
        
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            // Android 8.0+ 必須用 TYPE_APPLICATION_OVERLAY
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.O 
                ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
                : WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
            PixelFormat.TRANSLUCENT
        );
        params.gravity = Gravity.START | Gravity.TOP;
        params.x = 100; params.y = 100;
        
        wm.addView(floatView, params);
        return START_STICKY;
    }
    
    @Override
    public void onDestroy() {
        if (floatView != null) wm.removeView(floatView);
        super.onDestroy();
    }
}

3. 運行時權限申請 (Android 6.0+)


if (!Settings.canDrawOverlays(this)) {
    Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                               Uri.parse("package:" + getPackageName()));
    startActivityForResult(intent, REQUEST_CODE);
}

方案對比選型

維度Dialog 主題 ActivityWindowManager 懸浮窗
實現難度極低高(權限、生命周期、觸摸分發)
作用域應用內全局(桌面/其他App上)
生命周期標準 ActivityService 管理,需手動控制
適用場景對話框、底部彈窗、表單頁懸浮球、錄屏控制、全局客服
權限需求無SYSTEM_ALERT_WINDOW(高危)

進階技巧:Activity 半透明背景 + 模態控制


// 主題繼承
<style name="Theme.Translucent" parent="Theme.AppCompat.Light.Dialog.Alert">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowCloseOnTouchOutside">false</item> <!-- 模態 -->
</style>

總結

**應用內懸浮首選 `Theme.Dialog` Activity**,零權限、標準生命周期、易維護。**跨應用/桌面懸浮必須用 `WindowManager` + Service**,但需處理權限申請、版本適配、觸摸事件分發等複雜問題。根據業務場景選型。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved