本文介绍3种字体大小自适应设备的方法。第1种方法是建立针对不同屏幕分辨率的values目录,然后在相应的values下建立dimens.xml文件,并修改其中的值,这种方法比较繁琐,同时要建立多个value文件;第2种方法是使用Google新发布的3个属性autoSizeMaxTextSize、autoSizeMinTextSize、autoSizeTextType,但是这3个属性支持的最小SdkVersion(minSdkVersion)是26,SdkVersion小于26的不能用;第3种方法是在使用控件时,先计算设备的分辨率,然后,计算控件中相应文字的长度,最后设置字体大小。
常见的手机或平板的分辨率有480x320、640x480、800x480、800x600、1024x768、1280x720、1280x800、1920x1080、1920x1280等等。
针对不同的屏幕分辨率建立不同的values目录名称,例如:values-480x320、values-640x480、values-800x480、values-800x600、values-1024x768、values-1280x720、values-1280x800、values-1920x1080、values-1920x1280等。
注意1:目录中的“x”是小写英文字母,不是乘号。
注意2:上述的目录设置只能适配竖屏,适配横屏会混乱,例如:屏幕分辨率是800x480,设备竖屏时能适配到values-800x480目下的dimens.xml,如果设备横屏的时候适配的可能是values-480x320目录下的dimens.xml。如果适配横屏需要将目录名称的分辨率反过来写,例如:屏幕分辨率是800x480,做屏幕适配时需要将values目录写成values-480x800。
注意3:如果没有建立与设备分辨率相应对应的values目录,系统会自动适配到已经建立的小于设备分辨率的values目录,例如:设备分辨率是800x500,则系统会自动适配到values-800x480。
(1)布局xml
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".TestActivity">
android:layout_height="wrap_content"
android:textSize="@dimen/text_large"
android:text="河南大学"/>
values-1024x768目录下的dimens.xml
分辨率是1024x768设备的运行结果如下:
(注意:设备横屏和竖屏时自适应的字体大小可能不同)
设备竖屏 设备横屏
values-1280x720目录下的dimens.xml
分辨率是1280x720设备的运行结果如下:
设备竖屏 设备横屏
Google的新属性如下:
android:autoSizeMaxTextSize="60sp"
android:autoSizeMinTextSize="6dp"
android:autoSizeTextType="uniform"
注意:他们需要配合android:maxLines="1"一起使用,并且上面三个属性只能兼容SdkVersion=26以上的版本。
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".TestActivity">
android:layout_height="wrap_content"
android:textSize="40sp"
android:maxLines="1"
android:autoSizeMaxTextSize="60sp"
android:autoSizeMinTextSize="6dp"
android:autoSizeTextType="uniform"
android:text="河南大学"/>
android:layout_height="wrap_content"
android:textSize="40sp"
android:maxLines="1"
android:autoSizeMaxTextSize="60sp"
android:autoSizeMinTextSize="6dp"
android:autoSizeTextType="uniform"
android:text="河南大学是百年老校!1912年在古城开封清代贡院旧址建校!"/>
(1)SdkVersion大于26的设备运行结果
设备竖屏 设备横屏
(2)SdkVersion=25的设备运行结果(不能自适应了)
设备竖屏 设备横屏
根据控件的宽度,重新计算字体的大小。首先需要获得控件的宽度和文本内容,然后,循环计算字体大小,直到文本内容完全适应控件的宽度。
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".TestActivity">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="40sp"
android:maxLines="1"
android:text="河南大学"/>
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextPaint;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class TestActivity extends AppCompatActivity {
private Button button = null;
private TextView textView = null;
private EditText editText = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
this.button = findViewById(R.id.test_button);
this.textView = findViewById(R.id.test_text_view);
this.editText = findViewById(R.id.test_edit_text);
this.initEvent();
}
/**
* 初始化事件
*/
private void initEvent(){
this.editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
// 监听EditText的长度变化
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
resetViewTextSize(editText,editText.getWidth(),editText.getText().toString().trim());
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
// Activity渲染结束后,回调onWindowFocusChanged方法,此时控件的width和height不再是0。
// 注意:控件的width和height在onCreate()、onStart()和onResume()中获得的值都是0。
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
this.resetViewTextSize(button,button.getWidth(),button.getText().toString().trim());
this.resetViewTextSize(textView,textView.getWidth(),textView.getText().toString().trim());
}
/**
* 重置控件中字体的大小
* @param view view可以使EditText、Button、CheckBox、RadioButton,因为他们都继承
* @param maxWidth
* @param text
*/
private void resetViewTextSize(TextView view, int maxWidth, String text) {
// 获得控件的真实长度,去除控件的内部间距
int realWidth = maxWidth - view.getPaddingRight() - view.getPaddingLeft();
// 如果控件的长度小于等于0
if (realWidth <= 0) {
return;
}
// 查找合适的text长度
TextPaint textPaint = new TextPaint(view.getPaint());
float autoSize = textPaint.getTextSize();
while (textPaint.measureText(text) > realWidth) {
autoSize--;
textPaint.setTextSize(autoSize);
}
// 字体大小最好使用px,因为上述使用getWidth获得的值是px,也可以使用COMPLEX_UNIT_SP是sp,但是需要转换。
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, autoSize);
}
}
设备竖屏 设备横屏