OpenClaw(安卓开源的多指触控手势库)适配刘海屏需要注意以下几点

openclaw openclaw中文博客 1

获取刘海屏安全区域

// 获取刘海屏安全区域(Android P+)
private fun getDisplayCutoutInsets(): Rect {
    val insets = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        window.decorView.rootWindowInsets?.displayCutout?.safeInsets
    } else {
        null
    }
    return insets ?: Rect(0, 0, 0, 0)
}
// 获取状态栏高度
private fun getStatusBarHeight(): Int {
    var result = 0
    val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
    if (resourceId > 0) {
        result = resources.getDimensionPixelSize(resourceId)
    }
    return result
}

OpenClaw 适配刘海屏的解决方案

调整触摸区域

public class NotchAwareClawView extends View {
    private OpenClaw openClaw;
    private int notchHeight;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化OpenClaw
        openClaw = new OpenClaw(this);
        // 获取刘海高度
        notchHeight = getStatusBarHeight();
        // 设置触摸监听
        openClaw.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                // 调整触摸事件的Y坐标,避开刘海区域
                MotionEvent adjustedEvent = MotionEvent.obtain(event);
                float rawY = event.getRawY();
                if (rawY < notchHeight) {
                    // 将刘海区域的触摸映射到有效区域
                    adjustedEvent.setLocation(event.getX(), notchHeight);
                }
                return openClaw.onTouch(v, adjustedEvent);
            }
        });
    }
}

使用WindowInsetsListener(推荐)

// Android 11+ 使用WindowInsets API
ViewCompat.setOnApplyWindowInsetsListener(window.decorView) { view, windowInsets ->
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        val insets = windowInsets.getInsets(WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout())
        // 设置OpenClaw的有效区域
        val clawView = findViewById<View>(R.id.claw_view)
        clawView.setPadding(
            clawView.paddingLeft + insets.left,
            clawView.paddingTop + insets.top,
            clawView.paddingRight + insets.right,
            clawView.paddingBottom + insets.bottom
        )
        // 设置OpenClaw的触摸边界
        openClaw.setTouchableArea(
            insets.left.toFloat(),
            insets.top.toFloat(),
            (screenWidth - insets.right).toFloat(),
            (screenHeight - insets.bottom).toFloat()
        );
    }
    windowInsets
}

配置OpenClaw的手势识别区域

public class NotchAdaptedClaw extends OpenClaw {
    private Rect safeArea;
    public NotchAdaptedClaw(Context context) {
        super(context);
        calculateSafeArea();
    }
    private void calculateSafeArea() {
        // 计算安全区域(避开刘海)
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        int statusBarHeight = getStatusBarHeight();
        int navBarHeight = getNavigationBarHeight();
        safeArea = new Rect(
            0,
            statusBarHeight,
            metrics.widthPixels,
            metrics.heightPixels - navBarHeight
        );
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 过滤掉刘海区域的触摸事件
        if (event.getY() < safeArea.top) {
            return false; // 忽略刘海区域的触摸
        }
        return super.onTouchEvent(event);
    }
    @Override
    public boolean isPointInTouchableArea(float x, float y) {
        // 重写触摸区域判断
        return safeArea.contains((int) x, (int) y);
    }
}

刘海屏全屏适配

// Activity中启用全屏并处理刘海
private void setupFullScreenWithNotch() {
    // 启用全屏
    window.decorView.systemUiVisibility = (
        View.SYSTEM_UI_FLAG_FULLSCREEN |
        View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
        View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
    )
    // 允许内容延伸到刘海区域(Android P+)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        val layoutParams = window.attributes
        layoutParams.layoutInDisplayCutoutMode = 
            WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
        window.attributes = layoutParams
    }
    // 为OpenClaw设置边距
    val clawLayout = findViewById<FrameLayout>(R.id.claw_layout)
    clawLayout.setOnApplyWindowInsetsListener { view, insets ->
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val cutout = insets.displayCutout
            if (cutout != null) {
                val safeInsets = cutout.safeInsets
                // 调整OpenClaw的布局边距
                view.setPadding(
                    safeInsets.left,
                    safeInsets.top,
                    safeInsets.right,
                    safeInsets.bottom
                )
                // 更新OpenClaw的触摸边界
                openClaw.updateTouchBoundary(
                    safeInsets.left,
                    safeInsets.top,
                    view.width - safeInsets.right,
                    view.height - safeInsets.bottom
                )
            }
        }
        insets
    }
}

厂商特定适配

// 检查是否为特定厂商的刘海屏
public static boolean isNotchDevice(Context context) {
    // 小米
    if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {
        return Settings.Global.getInt(context.getContentResolver(),
            "force_black", 0) == 1;
    }
    // 华为
    if (Build.MANUFACTURER.equalsIgnoreCase("HUAWEI")) {
        try {
            ClassLoader cl = context.getClassLoader();
            Class HwNotchSizeUtil = cl.loadClass("com.huawei.android.util.HwNotchSizeUtil");
            Method get = HwNotchSizeUtil.getMethod("hasNotchInScreen");
            return (boolean) get.invoke(HwNotchSizeUtil);
        } catch (Exception e) {
            return false;
        }
    }
    // OPPO
    if (Build.MANUFACTURER.equalsIgnoreCase("OPPO")) {
        return context.getPackageManager().hasSystemFeature("com.oppo.feature.screen.heteromorphism");
    }
    // VIVO
    if (Build.MANUFACTURER.equalsIgnoreCase("VIVO")) {
        try {
            ClassLoader cl = context.getClassLoader();
            Class ftFeature = cl.loadClass("android.util.FtFeature");
            Method get = ftFeature.getMethod("isFeatureSupport", int.class);
            return (boolean) get.invoke(ftFeature, 0x00000020);
        } catch (Exception e) {
            return false;
        }
    }
    return false;
}

配置建议

  1. 测试不同设备:在不同厂商的刘海屏设备上测试
  2. 动态适配:使用WindowInsets API进行动态适配
  3. 向后兼容:为Android P以下版本提供fallback方案
  4. 手势边界:确保手势识别区域避开刘海区域
  5. 用户体验:考虑刘海对多指操作的影响,适当调整手势灵敏度

这些方法可以确保OpenClaw在各种刘海屏设备上都能正常工作,提供良好的用户体验。

OpenClaw(安卓开源的多指触控手势库)适配刘海屏需要注意以下几点-第1张图片-OpenClaw 中文版 - 真正能做事的 AI

抱歉,评论功能暂时关闭!