1 Android 控制手机横屏或者竖屏的方法

1.1 配置 AndroidManifest.xml

以横屏模式为例:

在 Android 开发中,如果想让应用或某个特定的 Activity 在运行时以横屏模式显示,可以通过修改 Activity 的 AndroidManifest.xml 文件中的配置来实现。

下面是如何在 AndroidManifest.xml 中为特定的 Activity 设置横屏模式的步骤:

  • 打开 Android 项目,并找到 AndroidManifest.xml 文件。
  • 找到你想要设置为横屏模式的 <activity> 标签。
  • 在这个 <activity> 标签内部,添加 android:screenOrientation 属性,并将其值设置为 landscape。

例如:

<activity android:name=".MyActivity">  
    <!-- 其他配置 -->  
    android:screenOrientation="landscape"  
</activity>

在这个例子中,MyActivity 是想要设置为横屏模式的 Activity 的名字。

注意:这种方法会强制 Activity 始终保持横屏模式,无论设备的物理方向如何。

如果向修改为竖屏模式,则 AndroidManifest.xml 文件的修改为:

<activity android:name=".MyActivity">  
    <!-- 其他配置 -->  
    android:screenOrientation="portrait"  
</activity>

1.2 运行时动态地改变屏幕方向

如果需要在运行时动态地改变屏幕方向,则可以在 Activity 或 Fragment 的代码中调用如下代码。

横屏模式:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

竖屏模式:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

2 提供 js 调用 Android 方法

(1)创建 JavaScriptInterface 类

首先,需要创建一个 Java 类,实现 WebView.JavascriptInterface 接口。这个类将作为 JavaScript 和 Android 原生代码之间的桥梁。

import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

public class WebAppInterface {
    Context mContext;

    /** Instantiate the interface and set the context */
    WebAppInterface(Context c) {
        mContext = c;
    }

    // 设置横屏或者竖屏
    @JavascriptInterface
    public void setScreenOrientation(String orientation) {
        if(orientation.equals("landscape")){
            ((Activity)mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        } else if (orientation.equals("portrait")) {
            ((Activity)mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        }
    }
}

注意,@JavascriptInterface 注解是必须的,该注解允许 Android 识别哪些方法可以被 JavaScript 调用。

(2)在 WebView 中启用 JavaScript 并添加接口

然后,在 Activity 或 Fragment 中,需要初始化 WebView,启用 JavaScript,并将创建的 JavaScriptInterface 实例添加到 WebView 中。

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

public class MainActivity extends AppCompatActivity {
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        webView = findViewById(R.id.webview);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.addJavascriptInterface(new WebAppInterface(this), "Android");

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });

        // 加载一个HTML页面,或者直接使用webView.loadDataWithBaseURL()加载包含JavaScript的字符串
        webView.loadUrl("file:///android_asset/my_page.html");
    }
}

这里,addJavascriptInterface 方法的第一个参数是 JavaScriptInterface 的实例,第二个参数是 JavaScript 中用来访问这个接口的对象名(这里使用了 “Android”)。

(3)在 HTML 中调用 Android 设置屏幕方向的方法

在 HTML 页面中,即可以使用 JavaScript 来调用 Android 方法。

<!DOCTYPE html>
<html>
<head>
    <title>WebView JavaScript Interface Example</title>
    <script type="text/javascript">
        function setScreenOrientationLandscape() {
            // 调用Android方法
            Android.setScreenOrientation('landscape');
        }
        function setScreenOrientationPortrait() {
            // 调用Android方法
            Android.setScreenOrientation('portrait');
        }
    </script>
</head>
<body>
    <h1>WebView JavaScript Interface Example</h1>
    <button onclick="setScreenOrientationLandscape()">横屏</button>
    <button onclick="setScreenOrientationPortrait()">竖屏</button>
</body>
</html>

在这个例子中,当用户点击不同屏幕模式的按钮时, setScreenOrientation 函数会被调用,它使用 Android 端定义的 setScreenOrientation 方法。

3 防止切换屏幕方向时 webview 重新加载 url

当设备的屏幕方向发生变化时,Android 系统会默认销毁当前的 Activity 实例,并重新创建一个新的实例,这一过程中会再次调用 Activity 的 onCreate 方法。这种机制导致了一个问题:当屏幕方向切换时,WebView 会重新加载主页,从而丢失了用户当前正在浏览的页面。

网上有很多资料提到通过添加 android:configChanges=“orientation|keyboardHidden” 属性到 AndroidManifest.xml 中的 Activity 标签,并覆盖 onConfigurationChanged 方法来处理屏幕方向或键盘可见性的变化。然而,经过测试发现,这种方法在 Android SDK 版本小于 13(即 Android 3.2 之前的版本)时有效,对于更高版本的 SDK 则不再起作用。

这是因为在 Android 3.2(API 级别 13)及以后的版本中,Android 系统对屏幕方向变化的处理方式发生了变化。即便在AndroidManifest.xml 中指定了 android:configChanges 属性,系统仍然可能会销毁并重新创建 Activity 实例,尤其是在涉及到复杂 UI 或者资源重新加载的情况下。因此,仅仅依赖 onConfigurationChanged 方法可能无法完全解决屏幕方向变化时 Activity 状态保存和恢复的问题。

有效的解决步骤如下:

(1)在 AndroidManifest.xml 的 activity 中添加:

android:configChanges="orientation|screenSize"

详细的 AndroidManifest.xml 如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.My"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:configChanges="orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

(2)在 MainActivity.java 中添加:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // 如果需要在此处处理屏幕切换的逻辑,可以在此处添加代码
    // 例如,可以通过newConfig.orientation来判断当前是横屏还是竖屏
}
04-21 17:44