1 Android 控制手机横屏或者竖屏的方法
1.1 配置 AndroidManifest.xml
以横屏模式为例:
在 Android 开发中,如果想让应用或某个特定的 Activity 在运行时以横屏模式显示,可以通过修改 Activity 的 AndroidManifest.xml 文件中的配置来实现。
下面是如何在 AndroidManifest.xml 中为特定的 Activity 设置横屏模式的步骤:
- 打开 Android 项目,并找到 AndroidManifest.xml 文件。
- 找到你想要设置为横屏模式的 <activity> 标签。
- 在这个 <activity> 标签内部,添加 android:screenOrientation 属性,并将其值设置为 landscape。
例如:
xml
<activity android:name=".MyActivity">
<!-- 其他配置 -->
android:screenOrientation="landscape"
</activity>
在这个例子中,MyActivity 是想要设置为横屏模式的 Activity 的名字。
注意:这种方法会强制 Activity 始终保持横屏模式,无论设备的物理方向如何。
如果向修改为竖屏模式,则 AndroidManifest.xml 文件的修改为:
xml
<activity android:name=".MyActivity">
<!-- 其他配置 -->
android:screenOrientation="portrait"
</activity>
1.2 运行时动态地改变屏幕方向
如果需要在运行时动态地改变屏幕方向,则可以在 Activity 或 Fragment 的代码中调用如下代码。
横屏模式:
java
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
竖屏模式:
java
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
2 提供 js 调用 Android 方法
(1)创建 JavaScriptInterface 类
首先,需要创建一个 Java 类,实现 WebView.JavascriptInterface 接口。这个类将作为 JavaScript 和 Android 原生代码之间的桥梁。
java
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 中。
java
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 方法。
html
<!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 中添加:
xml
android:configChanges="orientation|screenSize"
详细的 AndroidManifest.xml 如下:
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 中添加:
java
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 如果需要在此处处理屏幕切换的逻辑,可以在此处添加代码
// 例如,可以通过newConfig.orientation来判断当前是横屏还是竖屏
}