You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android端不旋转设备旋转WebView至横屏的实现与报错修复

问题原因

该崩溃由Android高版本API限制导致:从API 28(Android 9.0)开始,系统对Canvas裁剪操作做了严格限制,仅允许使用INTERSECT和DIFFERENCE两种Region.Op参数,你代码中调用clipRect时传入的Region.Op.REPLACE属于被禁用类型,直接触发IllegalArgumentException崩溃。
你参考的旧方案本身也存在固有缺陷:仅对绘制画布做了旋转处理,没有同步适配触摸事件坐标映射、视图宽高测量逻辑,即使绕过崩溃问题,也会出现触摸位置错位、页面内容拉伸变形、交互失效等问题。

正确实现方案

不需要重写draw方法手动操作Canvas,直接基于View原生旋转能力实现,全程无需修改Activity屏幕方向配置,设备保持竖屏状态即可让WebView单独横屏显示,兼容Android 9.0及以上版本。

1. 自定义支持横屏旋转的WebView

重写测量、布局、触摸事件相关方法,解决旋转后的尺寸适配、坐标映射问题:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.webkit.WebView;

public class LandscapeWebView extends WebView {
    // 顺时针横屏传90,逆时针横屏传-90
    private static final int LANDSCAPE_ROTATION = 90;

    public LandscapeWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // 初始化时直接设置旋转角度
        setRotation(LANDSCAPE_ROTATION);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 旋转后宽高互换,交换测量参数
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        // 回写互换后的测量尺寸
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        // 传递互换后的尺寸给父类
        super.onSizeChanged(h, w, oldh, oldw);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 转换触摸坐标,适配旋转后的视图坐标系
        if (LANDSCAPE_ROTATION == 90) {
            event.setLocation(event.getY(), getWidth() - event.getX());
        } else {
            event.setLocation(getHeight() - event.getY(), event.getX());
        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 按旋转后的尺寸完成布局
        super.onLayout(changed, l, t, l + getMeasuredWidth(), t + getMeasuredHeight());
    }
}

2. 布局文件配置

布局中WebView宽高直接匹配父容器即可,不要使用wrap_content避免测量异常:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.替换为你自己的包名.LandscapeWebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

3. Activity中初始化WebView

Activity不需要配置横屏属性,保持默认竖屏即可,按常规逻辑初始化WebView:

import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.webkit.WebSettings;
import android.webkit.WebViewClient;

public class WebViewActivity extends AppCompatActivity {
    private LandscapeWebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        webView = findViewById(R.id.webView);

        // 常规WebView配置
        WebSettings settings = webView.getSettings();
        settings.setJavaScriptEnabled(true);
        settings.setDomStorageEnabled(true);
        settings.setAllowFileAccess(true);
        webView.setWebViewClient(new WebViewClient());
        // 加载目标页面
        webView.loadUrl("你要加载的页面地址");
    }

    @Override
    protected void onDestroy() {
        // 销毁WebView避免内存泄漏
        if (webView != null) {
            webView.destroy();
        }
        super.onDestroy();
    }
}

注意事项

  • 如果需要切换横竖屏方向,只需要修改LANDSCAPE_ROTATION的取值,触摸坐标转换逻辑已经做了适配
  • 该方案支持WebView所有原生能力,包括视频全屏播放、表单输入、页面滚动、JS交互等,无需额外适配
  • 如果WebView外层套了可滚动容器(比如ScrollView),需要把滚动容器也做同样的旋转适配,否则会出现滚动冲突

内容的提问来源于stack exchange,提问作者Poorvaja

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 14:06:23