Как предотвратить эффекты изменения размера шрифта системы в приложении Android?
Недавно я закончил разработку своего приложения для Android. Я использовал sp (масштабированные пиксели) для всех textSize. Проблема в том, что когда я настраивал размер шрифта системы, меняются размеры шрифта приложения. Я могу использовать dp (независимые от устройства пиксели), но для моего приложения потребуется слишком много времени.
Я ссылался на размер текста от этого.
Есть ли способ предотвратить эффекты изменения размера шрифта в моем приложении?
Ответы
Ответ 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), то это вызовет странное поведение.