onConfigurationChanged 代替重建
-
- 0. **定义与基本用途**
- 1. **具体使用场景 - 屏幕方向改变**
- 2. **具体使用场景 - 键盘可用性改变**
- 3. **具体使用场景 - 语言设置变更**
- 4. **具体使用场景 - 屏幕密度变化**
- 5. **具体使用场景 - 字体大小改变**
- 6. **具体使用场景 - 屏幕尺寸变化(多窗口模式等)**
- 7. **具体使用场景 - 设备主题变化**
- 8. **具体使用场景 - 传感器配置改变(部分情况)**
- 9. **具体使用场景 - 触摸屏模式改变(极少见)**
- 10. **具体使用场景 - 音频输出设备改变**
- 11. **具体使用场景 - 辅助功能设置改变**
- 12. **具体使用场景 - 模拟位置设置改变**
- 13. **具体使用场景 - 系统显示模式改变(如夜间模式、护眼模式)**
- 14. **具体使用场景 - 应用安装/卸载外部插件或组件**
- 16. **具体使用场景 - 系统更新后配置变化**
- 17. **具体使用场景 - 虚拟内存设置改变**
- 18. **具体使用场景 - 设备存储空间状态改变**
- 19. **具体使用场景 - 设备电源模式改变**
- 20. **具体使用场景 - 多用户配置切换(设备支持多用户)**
- 21. **具体使用场景 - 布局方向切换**
- 22. **具体使用场景 - 屏幕布局相关配置变化(复合场景)**
- 23. **具体使用场景 - 设备的导航方式切换**
- 23. **具体使用场景 - 设备颜色模式相关的配置变化**
- 24. **具体使用场景 - 移动网络国家码相关的配置变化**
- 25. **具体使用场景 - 移动网络运营商变化**
- 一般场景下使用需要配置
- 参考地址
0. 定义与基本用途
onConfigurationChanged()
是Android中的一个生命周期方法。它在Activity(活动)中使用,用于处理设备配置发生改变的情况。当设备的配置发生变化,如屏幕方向的旋转(从竖屏变为横屏或者反之)、键盘可用性的改变、语言设置的变更等,系统默认会销毁并重新创建Activity。- 但是,如果在Activity中重写了
onConfigurationChanged()
方法,就可以在配置改变时避免Activity的重建,而是在原有Activity实例中处理配置变化。
1. 具体使用场景 - 屏幕方向改变
当用户将设备从竖屏旋转到横屏,或者从横屏旋转到竖屏时,系统会检测到屏幕方向的配置变化。在这种情况下,onConfigurationChanged
方法会被调用,使得开发者可以在该方法中对布局进行重新调整,以适应新的屏幕方向。例如,对于一个新闻阅读应用,竖屏时文章内容可能以单列形式显示,而在横屏时可以将文章内容和相关图片以双列形式更好地呈现。
- 在AndroidManifest.xml文件中配置
- 首先,需要在AndroidManifest.xml文件中的相应Activity标签中添加
android:configChanges
属性。如果只想在屏幕方向改变时自己处理配置变化,而不重建Activity,可以添加android:configChanges = "orientation"
。 - 例如,对于一个简单的Activity定义如下:
<activity android:name=".MainActivity" android:configChanges="orientation"> <intent - filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent - filter> </activity>
- 首先,需要在AndroidManifest.xml文件中的相应Activity标签中添加
- 在Activity类中重写onConfigurationChanged方法
- 在Activity类中重写
onConfigurationChanged
方法来处理屏幕方向改变后的逻辑。以下是一个简单的示例代码:
import android.content.res.Configuration; import android.os.Bundle; import android.app.Activity; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // 检查屏幕方向是否改变 if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { // 在这里处理横屏模式下的布局调整 } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { // 在这里处理竖屏模式下的布局调整 } } }
- 在上述代码中,当屏幕方向改变时,
onConfigurationChanged
方法会被调用。通过检查newConfig.orientation
的值,可以确定是横屏还是竖屏模式,然后在对应的分支中进行布局调整等操作。
- 在Activity类中重写
2. 具体使用场景 - 键盘可用性改变
包括软键盘和外接键盘。当软键盘弹出或收起时,或者外接键盘插入或拔出时,系统会认为这是一种配置变化。例如,在一个聊天应用中,当软键盘弹出时,消息列表可能会被压缩,输入框和发送按钮会调整到合适的位置,方便用户进行输入操作。当外接键盘插入后,应用可能会隐藏软键盘相关的界面元素,并重新布局文本输入区域,以更好地利用外接键盘进行输入。
- 在AndroidManifest.xml文件中设置
- 要防止Activity在键盘可用性改变时重建,需要在AndroidManifest.xml文件中的Activity标签内设置
android:configChanges
属性。当只想处理键盘可用性改变(软键盘弹出或收起、外接键盘插入或拔出)时,可以添加android:configChanges="keyboardHidden|keyboard"
。 - keyboard 属性有用的但是没查到单独用途
- 示例代码如下:
<activity android:name=".YourActivityName" android:configChanges="keyboardHidden"> <intent - filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent - filter> </activity>
- 要防止Activity在键盘可用性改变时重建,需要在AndroidManifest.xml文件中的Activity标签内设置
- 在Activity类中重写onConfigurationChanged方法
- 同时,需要在Activity类中重写
onConfigurationChanged
方法来处理键盘可用性改变后的操作。例如:
import android.content.res.Configuration; import android.os.Bundle; import android.app.Activity; public class YourActivityName extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout_name); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { // 键盘现在可见,执行相关操作,如调整布局 // 例如,重新排列视图元素,为键盘腾出空间 } else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) { // 键盘现在隐藏,执行相应操作 // 比如,恢复视图元素的原始布局 } } }
- 在上述代码中,通过检查
newConfig.keyboardHidden
的值来判断键盘是隐藏还是可见。Configuration.KEYBOARDHIDDEN_NO
表示键盘可见,Configuration.KEYBOARDHIDDEN_YES
表示键盘隐藏。根据键盘的状态,可以在对应的条件分支中调整视图布局或执行其他相关操作。
- 同时,需要在Activity类中重写
3. 具体使用场景 - 语言设置变更
当用户在设备的系统设置中更改语言后,应用需要更新界面上的文字显示来匹配新的语言环境。此时onConfigurationChanged
方法会被调用,开发者可以在这个方法中重新加载相应语言的字符串资源,确保应用的菜单、按钮标签、提示信息等文字内容能够以正确的语言呈现给用户。例如,一个国际化的电商应用,当语言从英语切换到法语后,商品名称、价格标签、购物流程中的提示文字等都需要在onConfigurationChanged
方法的处理下更新为法语。
- 在AndroidManifest.xml中配置
- 要阻止Activity在语言设置变更时重建,需要在对应的Activity标签内的
android:configChanges
属性中添加locale
。例如:
<activity android:name=".YourActivityName" android:configChanges="locale"> <intent - filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent - filter> </activity>
- 要阻止Activity在语言设置变更时重建,需要在对应的Activity标签内的
- 在Activity类中重写onConfigurationChanged方法
- 接着,在Activity类中重写
onConfigurationChanged
方法来处理语言变更后的操作。可以在这个方法中重新加载语言相关的资源,以更新界面上的文字显示。以下是一个简单的示例:
import android.content.res.Configuration; import android.os.Bundle; import android.app.Activity; import android.content.res.Resources; import java.util.Locale; public class YourActivityName extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout_name); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.locale!= null) { // 语言设置已改变 Locale locale = newConfig.locale; Resources resources = getResources(); Configuration configuration = resources.getConfiguration(); configuration.setLocale(locale); resources.updateConfiguration(configuration, resources.getDisplayMetrics()); // 重新加载布局,使文字以新语言显示 setContentView(R.layout.your_layout_name); } } }
- 在上述代码中,首先获取新的语言设置(
Locale
)。然后,通过getResources()
获取Resources
对象,再获取当前的Configuration
对象。接着,将新的语言设置应用到Configuration
对象中,并使用updateConfiguration
方法更新资源配置。最后,重新加载布局,这样界面上的文字就会以新的语言显示。
- 接着,在Activity类中重写
4. 具体使用场景 - 屏幕密度变化
用户可能会在设备设置中手动调整屏幕分辨率,这会导致屏幕密度改变。另外,当设备连接到不同的外部显示器时,屏幕密度也可能发生变化。在这种情况下,onConfigurationChanged
方法可以被用于重新调整图像资源的加载和显示方式、布局尺寸的缩放等。例如,对于一个图标密集型的应用,当屏幕密度变高时,可以在onConfigurationChanged
方法中加载更高分辨率的图标,以保证图标在高密度屏幕上的清晰度。
- 在AndroidManifest.xml中进行配置
- 要防止Activity在屏幕密度变化时重建,需要在AndroidManifest.xml文件中的Activity标签内设置
android:configChanges
属性。对于屏幕密度变化,需要添加density
。 - 示例代码如下:
<activity android:name=".YourActivityName" android:configChanges="density"> <intent - filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent - filter> </activity>
- 要防止Activity在屏幕密度变化时重建,需要在AndroidManifest.xml文件中的Activity标签内设置
- 在Activity类中重写onConfigurationChanged方法
- 在Activity类中重写
onConfigurationChanged
方法来处理屏幕密度变化后的操作。可以在这个方法中调整与屏幕密度相关的资源加载和布局。例如,处理图像资源的加载方式,以适应新的屏幕密度。
import android.content.res.Configuration; import android.os.Bundle; import android.app.Activity; public class YourActivityName extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout_name); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.densityDpi!= 0) { // 屏幕密度已改变,根据新的密度DPI进行操作 int newDensityDpi = newConfig.densityDpi; // 例如,重新加载合适分辨率的图像资源 // 假设你有根据不同密度存储图像的逻辑 // 可以在这里调用相关方法来加载正确的图像 } } }
- 在上述代码中,通过检查
newConfig.densityDpi
的值来确定屏幕密度是否改变。如果屏幕密度改变了(newConfig.densityDpi
不为0),可以获取新的屏幕密度值(newDensityDpi
),并根据这个值来调整资源加载。例如,如果有针对不同屏幕密度的图像资源文件夹(如drawable - ldpi
、drawable - mdpi
、drawable - hdpi
等),可以在这里编写逻辑来加载适合新屏幕密度的图像。
- 在Activity类中重写
5. 具体使用场景 - 字体大小改变
许多Android设备允许用户调整系统字体大小。当用户改变字体缩放比例后,系统会触发配置变化,调用onConfigurationChanged
方法。在这个方法中,开发者可以对文本相关的视图进行调整,如重新计算文本的大小、行间距、边距等。例如,在一个电子书应用中,当用户增大字体缩放比例后,onConfigurationChanged
方法可以调整每页显示的文字数量和排版方式,以确保文字仍然能够清晰可读。
- 在AndroidManifest.xml文件中配置
- 首先,在AndroidManifest.xml中对应的Activity标签里添加
android:configChanges
属性。为了防止Activity在字体大小改变时重建,需要添加fontScale
。示例如下:
<activity android:name=".YourActivityName" android:configChanges="fontScale"> <intent - filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent - filter> </activity>
- 首先,在AndroidManifest.xml中对应的Activity标签里添加
- 在Activity类中重写onConfigurationChanged方法
- 接着,在Activity类中重写
onConfigurationChanged
方法来处理字体大小改变后的情况。主要是对文本相关的视图进行调整,比如重新计算文本大小、行间距等。
import android.content.res.Configuration; import android.os.Bundle; import android.app.Activity; import android.util.TypedValue; import android.view.View; import android.widget.TextView; public class YourActivityName extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_layout_name); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (newConfig.fontScale!= 1.0f) { // 字体缩放比例发生改变 float newFontScale = newConfig.fontScale; // 遍历所有的TextView并调整文本大小 View rootView = findViewById(android.R.id.content); adjustTextViewFontSize(rootView, newFontScale); } } private void adjustTextViewFontSize(View view, float fontScale) { if (view instanceof TextView) { TextView textView = (TextView) view; float originalTextSize = textView.getTextSize(); float newTextSize = originalTextSize * fontScale; textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, newTextSize); } else if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) { View childView = viewGroup.getChildAt(i); adjustTextViewFontSize(childView, fontScale); } } } }
- 接着,在Activity类中重写