how to prevent system font-size changing effects to android application?

后端 未结 8 2125
执笔经年
执笔经年 2020-11-27 03:49

I recently finished developing my android application. I used sp (Scaled pixels) for all textSize. The problem is when i adjusted the system font-size, my application\'s fon

相关标签:
8条回答
  • 2020-11-27 04:01

    There's another way to prevent app layout issue / font issue from the setting font size change. You can try

    // ignore the font scale here
    final Configuration newConfiguration = new Configuration(
        newBase.getResources().getConfiguration()
    );
    
    newConfiguration.fontScale = 1.0f;
    applyOverrideConfiguration(newConfiguration);
    

    where newBase is from attachBaseContext function. You need to override this callback in your Activity.

    But, the side effect is that if you wanna use animation (objectanimator/valueanimator), then it will cause the weird behavior.

    0 讨论(0)
  • 2020-11-27 04:04

    you can force to text size of your app using base activity Configuration, make all activities inherent base activity. 1.0f will force the app font size to normal ignoring system settings.

    public  void adjustFontScale( Configuration configuration,float scale) {
    
    configuration.fontScale = scale;
    DisplayMetrics metrics = getResources().getDisplayMetrics();
    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    wm.getDefaultDisplay().getMetrics(metrics);
    metrics.scaledDensity = configuration.fontScale * metrics.density;
    getBaseContext().getResources().updateConfiguration(configuration, metrics);
    
    }
    
    @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         adjustFontScale( getResources().getConfiguration(),1.0f);
    }
    
    0 讨论(0)
  • 2020-11-27 04:05

    If you require your text to remain the same size, you'll have to use dp.

    To quote the documentation:

    An sp is the same base unit, but is scaled by the user's preferred text size (it’s a scale-independent pixel), so you should use this measurement unit when defining text size (but never for layout sizes).

    Emphasis mine.

    So you're seeing the expected behaviour for using sp as your units for text size.

    I don't understand what you mean about using dp taking too long to maintain your app - as far as I can tell, it'll exactly be the same amount of effort? (perhaps less, though it'll likely make it less usable for users with poor eyesight)

    0 讨论(0)
  • 2020-11-27 04:05

    That's how we do it. In Application class override onConfigurationChanged() like this. If you want different behavior for different activities - override onConfigurationChanged() in Activity.

    Don't forget to add manifest tag android:configChanges="fontScale" since you are hadnling this configuration change yourself.

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    
        // In some cases modifying newConfig leads to unexpected behavior,
        // so it's better to edit new instance.
        Configuration configuration = new Configuration(newConfig);
        SystemUtils.adjustFontScale(getApplicationContext(), configuration);
    }
    

    In some helper class we have adjustFontScale() method.

    public static void adjustFontScale(Context context, Configuration configuration) {
        if (configuration.fontScale != 1) {
            configuration.fontScale = 1;
            DisplayMetrics metrics = context.getResources().getDisplayMetrics();
            WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            wm.getDefaultDisplay().getMetrics(metrics);
            metrics.scaledDensity = configuration.fontScale * metrics.density;
            context.getResources().updateConfiguration(configuration, metrics);
        }
    }
    

    WARNING! That will totally ignore Accessibility Font Scale user settings and will prevent your App fonts scaling!

    0 讨论(0)
  • 2020-11-27 04:09

    That's how you do it in 2018 (Xamarin.Android/C# - same approach in other languages):

    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle bundle)
        {
    ...
        }
    
        protected override void AttachBaseContext(Context @base)
        {
            var configuration = new Configuration(@base.Resources.Configuration);
    
            configuration.FontScale = 1f;
            var config =  Application.Context.CreateConfigurationContext(configuration);
    
            base.AttachBaseContext(config);
        }
    }
    

    All you need is override attachBaseContext method of activity and update config there.

    getBaseContext().getResources().updateConfiguration() is deprecated though there're numerous examples with this method. If you use this approach besides the IDE warning you might find some parts of your app not scaled.

    0 讨论(0)
  • 2020-11-27 04:21

    I recently ran into this problem as well. Our UI didn't scale well on phones with limited screen dimensions and changing the entire UI on the off chance a user set's their Accessibility Options to "Huge" seemed silly.

    I found this question on StackOverflow to be most helpful.

    What I did was put the following code below in my BaseActivity (an Activity class that all my activities extend from)

    public void adjustFontScale(Configuration configuration) {
        if (configuration.fontScale > 1.30) {
            LogUtil.log(LogUtil.WARN, TAG, "fontScale=" + configuration.fontScale); //Custom Log class, you can use Log.w
            LogUtil.log(LogUtil.WARN, TAG, "font too big. scale down..."); //Custom Log class, you can use Log.w
            configuration.fontScale = 1.30f;
            DisplayMetrics metrics = getResources().getDisplayMetrics();
            WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
            wm.getDefaultDisplay().getMetrics(metrics);
            metrics.scaledDensity = configuration.fontScale * metrics.density;
            getBaseContext().getResources().updateConfiguration(configuration, metrics);
        }
    }
    

    And called it right after my super.onCreate() like so

    adjustFontScale(getResources().getConfiguration());
    

    What this code does is identify if the user set their font scale in Accessibility Settings to something greater than 1.30f (1.30f is "Large" on The Note 5, but probably varies a bit from device-to-device). If the user set their font too large ("Extra Large", "Huge"...), we scale the application only to "Large".

    This allows your app to scale to a user's preferences (to a degree) without distorting your UI. Hopefully this will help others. Good luck scaling!

    Other Tips

    If you want certain layouts to scale with your fonts (say...a RelativeLayout that you use as a backdrop against your fonts), you can set their width/height with sp instead of the classic dp. When a user changes their font size, the layout will change accordingly with the fonts in your application. Nice little trick.

    0 讨论(0)
提交回复
热议问题