23人参与 • 2025-09-28 • Android
当设备的配置(configuration) 发生变化时,android 系统会触发 configuration change 事件。
| 变更类型 | 示例 |
|---|---|
orientation | 屏幕旋转(竖屏 ↔ 横屏) |
screenlayout | 屏幕尺寸/密度变化(如折叠屏展开) |
keyboardhidden | 软键盘弹出/隐藏 |
fontscale | 系统字体大小调整 |
locale | 系统语言切换 |
uimode | 夜间模式开启/关闭 |
⚠️ 默认行为:系统会销毁并重建 activity(调用
ondestroy()→oncreate()),以便加载适配新配置的资源。
activity a (竖屏)
↓ 用户旋转屏幕
onpause() → onstop() → ondestroy()
↓ 系统重建
oncreate() → onstart() → onresume()
→ activity a (横屏)oncreate() 中初始化的数据可能丢失。setcontentview()、数据库查询、网络请求。如果选择接受默认重建行为,必须确保关键数据不丢失。
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());
}
}✅ 适用场景:轻量级状态(如文本框内容、滚动位置)。
❌ 不适用:大数据、文件句柄、网络连接。
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。
<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:软键盘显示/隐藏
@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();
}
}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),让系统自动加载合适的布局。
res/
├── layout/
│ └── activity_main.xml # 竖屏布局
└── layout-land/
└── activity_main.xml # 横屏布局<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<!-- 左侧列表 -->
<fragment
android:id="@+id/fragment_list"
android:name="com.example.newslistfragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<!-- 右侧详情 -->
<framelayout
android:id="@+id/detail_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</linearlayout>✅ 优势:完全解耦,ui 设计自由度高,适合平板或大屏设备。
// 在 onconfigurationchanged 中判断
if (newconfig.keyboardhidden == configuration.keyboardhidden_no) {
// 软键盘弹出
} else if (newconfig.keyboardhidden == configuration.keyboardhidden_yes) {
// 软键盘隐藏
}<!-- 支持多窗口 -->
<activity
android:name=".mainactivity"
android:resizeableactivity="true"
android:supportspictureinpicture="true"
android:configchanges="orientation|screensize|smallestscreensize">
</activity>@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屏幕变更事件内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论