Android开发教程之屏幕变更事件实用指南
平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“Android开发教程之屏幕变更事件”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
目录
- 一、什么是屏幕变更事件?
- 常用的设置变更类型
- 二、默认行为:Activity 重建
- 生命周期流程
- 问题与挑战
- 三、方案一:允许重建 + 正确保存状态
- 1. 采用 onSaveInstanceState() 保存临时状态
- 2. 采用 ViewModel 保留复杂数据
- 四、方案二:阻止重建 + 手动处理变更
- 1. 声明要自行处理的设置变更
- 2. 重写 onConfigurationChanged() 方法
- 3. 动态调整 UI 示例
- 五、为不同屏幕提供专属布局
- 1. 新建横屏专用布局
- 2. 横屏布局示例(layout-land/activity_main.xml)
- 六、高级技巧与最佳实践
- 1. 软键盘弹出/隐藏
- 2. 折叠屏与多窗口兼容
- 3. 采用 Jetpack Compose 实现响应式 UI
- 七、常用问题与避坑指南
- 八、结语
一、什么是屏幕变更事件?
当设备的设置(Configuration) 结合项目来看,发生变化时,Android 系统会触发 Configuration Change 事件。
常用的设置变更类型
| 变更类型 | 示例 |
|---|---|
orientation | 屏幕旋转(竖屏 ↔ 横屏) |
screenLayout | 屏幕尺寸/密度变化(如折叠屏展开) |
keyboardHidden | 软键盘弹出/隐藏 |
fontScale | 系统字体大小调整 |
locale | 系统语言切换 |
uiMode | 夜间模式开启/关闭 |
默认行为:系统会销毁并重建 Activity(调用
onDestroy()→onCreate()),以便加载适配新设置的资源。
二、默认行为:Activity 重建
生命周期流程
Activity A (竖屏)
↓ 用户旋转屏幕
onPause() → onStop() → onDestroy()
↓ 系统重建
onCreate() → onStart() → onResume()
→ Activity A (横屏)
问题与挑战
- 状态丢失:
onCreate()中初始化的数据可能丢失。 - 性能损耗:重复执行
setContentView()、数据库查询、网络请求。 - 用户体验差:页面闪退或重新加载。
三、方案一:允许重建 + 正确保存状态
若选择接受默认重建行为,必须确保关键数据不丢失。
1. 采用 onSaveInstanceState() 保存临时状态
public class MainActivity extends AppCompatActivity {
private String userInput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = findViewById(R.id.edit_text);
// 恢复保存的状态
if (savedInstanceState != null) {
userInput = savedInstanceState.getString("USER_INPUT");
editText.setText(userInput);
}
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// 保存用户输入
EditText editText = findViewById(R.id.edit_text);
outState.putString("USER_INPUT", editText.getText().toString());
}
}
适用场景:轻量级状态(如文本框内容、滚动位置)。
不适用:大数据、文件句柄、网络连接。
2. 采用 ViewModel 保留复杂数据
public class MainViewModel extends ViewModel {
private MutableLiveData<List<String>> dataList = new MutableLiveData<>();
public LiveData<List<String>> getDataList() {
return dataList;
}
public void loadData() {
// 模拟耗时加载
new Handler().postDelayed(() -> {
List<String> data = Arrays.asList("Item 1", "Item 2", "Item 3");
dataList.setValue(data);
}, 2000);
}
}
// 在 Activity 中使用
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
viewModel.getDataList().observe(this, list -> {
// 更新 UI,即使 Activity 重建,数据依然存在
adapter.submitList(list);
});
优势:生命周期独立于 Activity,设置变更时不销毁。
四、方案二:阻止重建 + 手动处理变更
借助在 AndroidManifest.xml 中声明 android:configChanges,可阻止系统自动重建 Activity。
1. 声明要自行处理的设置变更
<activity
android:name=".MainActivity"
android:exported="true"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
关键属性说明:
orientation:屏幕方向变更(横/竖屏)screenSize:屏幕尺寸变化(API 13+,常与 orientation 同时采用)keyboardHidden:软键盘显示/隐藏
2. 重写 onConfigurationChanged() 方法
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 判断当前屏幕方向
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "已切换到横屏", Toast.LENGTH_SHORT).show();
// 动态调整 UI
adjustForLandscape();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Toast.makeText(this, "已切换到竖屏", Toast.LENGTH_SHORT).show();
adjustForPortrait();
}
}
3. 动态调整 UI 示例
private void adjustForLandscape() {
// 横屏下隐藏某些 View
findViewById(R.id.ad_banner).setVisibility(View.GONE);
// 调整 RecyclerView 布局管理器
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
}
private void adjustForPortrait() {
// 竖屏下显示广告
findViewById(R.id.ad_banner).setVisibility(View.VISIBLE);
// 恢复线性布局
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
优点:避免 Activity 重建,提升性能。
缺点:需手动处理所有 UI 变化,代码复杂度增加。
五、为不同屏幕提供专属布局
最优雅的适配方式是采用 资源限定符(Resource Qualifiers),让系统自动加载合适的布局。
1. 新建横屏专用布局
res/
├── layout/
│ └── activity_main.xml # 竖屏布局
└── layout-land/
└── activity_main.xml # 横屏布局
2. 横屏布局示例(layout-land/activity_main.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="horizontal">
<!-- 左侧列表 -->
<fragment
android:id="@+id/fragment_list"
android:name="com.example.NewsListFragment"
android:layout_
android:layout_
android:layout_weight="1" />
<!-- 右侧详情 -->
<FrameLayout
android:id="@+id/detail_container"
android:layout_
android:layout_
android:layout_weight="2" />
</LinearLayout>
优势:完全解耦,UI 设计自由度高,适合平板或大屏设备。
六、高级技巧与最佳实践
1. 软键盘弹出/隐藏
// 在 onConfigurationChanged 中判断
if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) {
// 软键盘弹出
} else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
// 软键盘隐藏
}
2. 折叠屏与多窗口兼容
<!-- 支持多窗口 -->
<activity
android:name=".MainActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges="orientation|screenSize|smallestScreenSize">
</activity>
3. 采用 Jetpack Compose 实现响应式 UI
@Composable
fun ResponsiveLayout() {
val configuration = LocalConfiguration.current
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
if (isLandscape) {
Row { /* 横屏布局 */ }
} else {
Column { /* 竖屏布局 */ }
}
}
七、常用问题与避坑指南
android:configChanges 不生效?确保同时声明
orientation和screenSize(API 13+)。横屏布局未加载?检查文件夹命名是否正确(
layout-land),且无拼写错误。ViewModel 数据在重建后丢失?确保采用
ViewModelProvider(this)而非ViewModelProvider(requireActivity())。动画在旋转后中断?将动画逻辑放在
ViewModel或采用onRetainNonConfigurationInstance()。
八、结语
到此这篇关于Android开发教程之屏幕变更事件的文章就介绍到这了,更多相关Android屏幕变更事件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!
您可能感兴趣的文章:
- Android实现屏幕旋转方法总结
- android 屏幕亮度调节方法详解
- Android调节屏幕亮度实现代码
- android拿到屏幕高度和宽度的实现方法
-
09.07
Android通过Dialog实现方式全屏的示例代码实用指南
-
09.07
Android开发(Kotlin) ViewModel基本用法示例完整指南
-
09.07
解决GitHub SSH连接超时问题及分析实用指南
-
09.07
Android开发教程之屏幕变更事件实用指南
-
09.07
从零开始讲解Android Studio打包WebView应用教程(附签名配置)实用指南
-
09.07
DBeaver导入csv到数据库的简单步骤记录实用指南
-
- Android开发教程之屏幕变更事件实用指南
- 09.07
-
-
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏