我最近完成了我的Android应用程序的开发。我对所有textSize使用了sp(Scaled pixels)。问题是当我调整系统字体大小时,我的应用程序的字体大小正在改变。我可以使用dp(设备无关像素),但维护我的应用程序需要很长时间。
我引用了this的文字大小。
有没有办法阻止系统字体大小更改效果到我的应用程序?
答案 0 :(得分:39)
如果您要求文字保持相同的尺寸,则必须使用dp
。
sp
是相同的基本单位,但是按用户的首选文字大小(它是与比例无关的像素)进行缩放,因此在定义文字时应使用此测量单位大小(但绝不是布局大小)。
强调我的。
因此,您会看到使用sp
作为文字大小单位的预期行为。
我不明白你使用dp花费太长时间来维护你的应用程序是什么意思 - 据我所知,这将是完全相同的努力量? (也许更少,但它可能会使眼睛不好的用户不太可用)
答案 1 :(得分:39)
我最近遇到了这个问题。我们的用户界面在屏幕尺寸有限的手机上无法很好地扩展,并且在用户将其可访问性选项设置为“巨大”的情况下更改整个用户界面似乎很愚蠢。
我发现StackOverflow上的这个question最有帮助。
我所做的是将下面的代码放在我的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(注释5上的1.30f为“大”,但可能会因设备而异。)。如果用户将其字体设置得太大(“超大”,“巨大”......),我们只将应用程序缩放为“大”。
这允许您的应用扩展到用户的偏好(在一定程度上),而不会扭曲您的UI。希望这会有助于其他人。祝你好运!
其他提示
如果您希望某些布局可以使用您的字体进行缩放(比如... RelativeLayout
,您将其用作字体的背景),则可以使用sp而不是经典dp设置其宽度/高度。当用户更改其字体大小时,布局将根据应用程序中的字体进行相应更改。不错的小技巧。
答案 2 :(得分:3)
我们就是这样做的。 在应用类中,覆盖 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's 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);
}
}
警告!这将完全忽略辅助功能字体比例用户设置,并会阻止您的App字体缩放!
答案 3 :(得分:1)
这就是您在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警告之外使用此方法,则可能会发现应用程序的某些部分无法缩放。
答案 4 :(得分:0)
还有另一种方法可以防止设置字体大小更改时出现应用布局问题/字体问题。 你可以尝试
// ignore the font scale here
final Configuration newConfiguration = new Configuration(
newBase.getResources().getConfiguration()
);
newConfiguration.fontScale = 1.0f;
applyOverrideConfiguration(newConfiguration);
其中newBase来自attachBaseContext函数。 您需要在Activity中覆盖此回调。
但是,副作用是,如果你想使用动画(objectanimator / valueanimator),那么它将导致奇怪的行为。
答案 5 :(得分:0)
在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
。
答案 6 :(得分:0)
您可以使用基本活动配置强制应用程序的文本大小,使所有活动固有于基本活动。 1.0f将强制将应用字体大小设置为正常大小,而忽略系统设置。
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);
}
答案 7 :(得分:0)
我认为使用dp
是最好的方法,但是在某些情况下,您可能希望使用字体样式,但是该样式使用的是sp
,则可以将sp
转换为{ {1}}的作者:
dp
因此您可以使用样式中的fun TextView.getSizeInSp() = textSize / context.resources.displayMetrics.scaleDensity
fun TextView.convertToDpSize() = setTextSize(TypedValue.COMPLEX_UNIT_DIP, getSizeInSp())
值,而无需使用动态字体大小,也无需对字体大小进行硬编码