Android onConfigurationChanged 基础配置

onConfigurationChanged 代替重建

0. 定义与基本用途

  • onConfigurationChanged()是Android中的一个生命周期方法。它在Activity(活动)中使用,用于处理设备配置发生改变的情况。当设备的配置发生变化,如屏幕方向的旋转(从竖屏变为横屏或者反之)、键盘可用性的改变、语言设置的变更等,系统默认会销毁并重新创建Activity。
  • 但是,如果在Activity中重写了onConfigurationChanged()方法,就可以在配置改变时避免Activity的重建,而是在原有Activity实例中处理配置变化。

1. 具体使用场景 - 屏幕方向改变

当用户将设备从竖屏旋转到横屏,或者从横屏旋转到竖屏时,系统会检测到屏幕方向的配置变化。在这种情况下,onConfigurationChanged方法会被调用,使得开发者可以在该方法中对布局进行重新调整,以适应新的屏幕方向。例如,对于一个新闻阅读应用,竖屏时文章内容可能以单列形式显示,而在横屏时可以将文章内容和相关图片以双列形式更好地呈现。

  1. 在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>
    
  2. 在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的值,可以确定是横屏还是竖屏模式,然后在对应的分支中进行布局调整等操作。

2. 具体使用场景 - 键盘可用性改变

包括软键盘和外接键盘。当软键盘弹出或收起时,或者外接键盘插入或拔出时,系统会认为这是一种配置变化。例如,在一个聊天应用中,当软键盘弹出时,消息列表可能会被压缩,输入框和发送按钮会调整到合适的位置,方便用户进行输入操作。当外接键盘插入后,应用可能会隐藏软键盘相关的界面元素,并重新布局文本输入区域,以更好地利用外接键盘进行输入。

  1. 在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>
    
  2. 在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表示键盘隐藏。根据键盘的状态,可以在对应的条件分支中调整视图布局或执行其他相关操作。

3. 具体使用场景 - 语言设置变更

当用户在设备的系统设置中更改语言后,应用需要更新界面上的文字显示来匹配新的语言环境。此时onConfigurationChanged方法会被调用,开发者可以在这个方法中重新加载相应语言的字符串资源,确保应用的菜单、按钮标签、提示信息等文字内容能够以正确的语言呈现给用户。例如,一个国际化的电商应用,当语言从英语切换到法语后,商品名称、价格标签、购物流程中的提示文字等都需要在onConfigurationChanged方法的处理下更新为法语。

  1. 在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>
    
  2. 在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方法更新资源配置。最后,重新加载布局,这样界面上的文字就会以新的语言显示。

4. 具体使用场景 - 屏幕密度变化

用户可能会在设备设置中手动调整屏幕分辨率,这会导致屏幕密度改变。另外,当设备连接到不同的外部显示器时,屏幕密度也可能发生变化。在这种情况下,onConfigurationChanged方法可以被用于重新调整图像资源的加载和显示方式、布局尺寸的缩放等。例如,对于一个图标密集型的应用,当屏幕密度变高时,可以在onConfigurationChanged方法中加载更高分辨率的图标,以保证图标在高密度屏幕上的清晰度。

  1. 在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>
    
  2. 在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 - ldpidrawable - mdpidrawable - hdpi等),可以在这里编写逻辑来加载适合新屏幕密度的图像。

5. 具体使用场景 - 字体大小改变

许多Android设备允许用户调整系统字体大小。当用户改变字体缩放比例后,系统会触发配置变化,调用onConfigurationChanged方法。在这个方法中,开发者可以对文本相关的视图进行调整,如重新计算文本的大小、行间距、边距等。例如,在一个电子书应用中,当用户增大字体缩放比例后,onConfigurationChanged方法可以调整每页显示的文字数量和排版方式,以确保文字仍然能够清晰可读。

  1. 在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>
    
  2. 在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);
                }
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周周都刷火焰猫头鹰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值