Подтвердить что ты не робот

Как предотвратить эффекты изменения размера шрифта системы в приложении Android?

Недавно я закончил разработку своего приложения для Android. Я использовал sp (масштабированные пиксели) для всех textSize. Проблема в том, что когда я настраивал размер шрифта системы, меняются размеры шрифта приложения. Я могу использовать dp (независимые от устройства пиксели), но для моего приложения потребуется слишком много времени.

Я ссылался на размер текста от этого.

Есть ли способ предотвратить эффекты изменения размера шрифта в моем приложении?

4b9b3361

Ответ 1

Если вам требуется, чтобы ваш текст оставался одного и того же размера, вам нужно будет использовать dp.

Чтобы процитировать документацию:

An sp является одним и тем же базовым блоком, но масштабируется с помощью предпочтительного текстового размера пользователя (его независимый от масштаба пиксель), поэтому вы должны использовать этот блок измерения при определении размера текста ( но никогда не для размеров макета).

Акцент на мой.

Итак, вы видите ожидаемое поведение для использования sp в качестве единиц измерения для размера текста.

Я не понимаю, что вы имеете в виду, когда используете dp слишком долго, чтобы поддерживать ваше приложение. Насколько я могу судить, это будет ровно столько же усилий? (возможно, меньше, хотя это, вероятно, сделает его менее пригодным для пользователей с плохим зрением)

Ответ 2

Недавно я столкнулся с этой проблемой. Наш пользовательский интерфейс плохо масштабировался на телефонах с ограниченным размером экрана и сменил весь пользовательский интерфейс на случай, когда пользователь установил свои параметры доступности на "Огромный", казалось глупым.

Я нашел этот question в StackOverflow наиболее полезным.

В моем BaseActivity (класс Activity, из которого все мои действия распространяются), я добавил следующий код

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 = (float) 1.30;
        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);
    }
}

И назвал его сразу после моего super.onCreate() таким образом

adjustFontScale(getResources().getConfiguration());

Что делает этот код, так это определить, задает ли пользовательский шрифт шкалу шрифтов в настройках доступности значение больше 1.30f (1.30f является "большим" в примечании 5, но, вероятно, немного отличается от устройства к устройству). Если пользователь установил слишком большой шрифт ( "Extra Large", "Huge"...), мы масштабируем приложение только до "Large".

Это позволяет вашему приложению масштабироваться в соответствии с предпочтениями пользователя (до степени), не искажая ваш пользовательский интерфейс. Надеюсь, это поможет другим. Удачи!

Другие советы

Если вы хотите, чтобы определенные макеты масштабировались с помощью ваших шрифтов (скажем... a RelativeLayout, которые вы используете в качестве фона для ваших шрифтов), вы можете установить их ширину/высоту с помощью sp вместо классического dp. Когда пользователь изменяет свой размер шрифта, макет будет соответствующим образом изменяться с помощью шрифтов в вашем приложении. Хороший небольшой трюк.

Ответ 3

Ни один из предыдущих ответов не работал для меня, на Android 8.1 (API 27). Вот что сработало: Добавьте следующий код в свою деятельность:

Код Котлина:

override fun attachBaseContext(newBase: Context?) {
    super.attachBaseContext(newBase)
    val newOverride = Configuration(newBase?.resources?.configuration)
    newOverride.fontScale = 1.0f
    applyOverrideConfiguration(newOverride)
}

Java-код:

@Override
protected void attachBaseContext(Context newBase) {
    super.attachBaseContext(newBase);
    final Configuration override = new Configuration(newBase.getResources().getConfiguration());
    override.fontScale = 1.0f;
    applyOverrideConfiguration(override);
}

Вам не нужно менять свой AndroidManifest.xml.

Ответ 4

Как мы это делаем. В классе Application переопределить класс onConfigurationChanged() как это. Если вы хотите различное поведение для разных действий - переопределите onConfigurationChanged() в действии.

Не забудьте добавить тег манифеста android: configChanges = "fontScale" , так как вы сами изменяете эту конфигурацию.

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    // In some cases modifying newConfig leads to unexpected behavior,
    // so it better to edit new instance.
    Configuration configuration = new Configuration(newConfig);
    SystemUtils.adjustFontScale(getApplicationContext(), configuration);
}

В некотором вспомогательном классе мы имеем метод adjustFontScale().

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);
    }
}

ПРЕДУПРЕЖДЕНИЕ!. Это полностью игнорирует пользовательские настройки шкалы специальных возможностей и предотвратит масштабирование шрифтов вашего приложения!

Ответ 5

Вот как вы это сделаете в 2018 году (Xamarin.Android/C# - такой же подход на других языках):

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);
    }
}

Все, что вам нужно, это переопределить метод активности attachBaseContext и обновить там конфигурацию.

getBaseContext(). getResources(). updateConfiguration() устарела, хотя существует множество примеров с этим методом. Если вы используете этот подход помимо предупреждения IDE, вы можете обнаружить, что некоторые части вашего приложения не масштабируются.

Ответ 6

Есть другой способ предотвратить проблему макета приложения/проблему шрифта от изменения размера шрифта установки. Ты можешь попробовать

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

newConfiguration.fontScale = 1.0f;
applyOverrideConfiguration(newConfiguration);

где newBase из функции attachBaseContext. Вам нужно переопределить этот обратный вызов в вашей деятельности.

Но побочным эффектом является то, что если вы хотите использовать анимацию (objectanimator/valueanimator), то это вызовет странное поведение.