android 字体宽高影响因素调研

笔者最近在做电子书开发,在开发过程中碰到一个比较抠细节的地方:对字体宽高进行计算,so:对影响字体宽高的因素进行了一波分析:

主要是对如下信息进行分析对比:文字(中英文标点符号,加粗,斜体,字体)

加粗和斜体为了保证所有系统都能运行都用的Typeface的常量进行控制。

字体主要是采用了四种:Sans、Serif、Mono、自定义(涉及到版权问题就不说了,自己放到asset文件夹下就可以了);

代码如下:

public class ShowTextViewextends View {

private PaintmPaint;

//    public String string = "ap卡了ξτβбпшㄎㄊěǔぬも┰┠№@↓";

    public Stringstring ="中国";

    public ShowTextView(Context context) {

super(context);

    }

public ShowTextView(Context context, AttributeSet attrs) {

super(context, attrs);

    }

public ShowTextView(Context context,AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

    }

public void setPaint(Paint paint){

this.mPaint = paint;

    }

@Override

    protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

        canvas.drawText(string, 0, 100, mPaint);

        canvas.drawLine(0, 100, 1000, 100, mPaint);

        Paint.FontMetrics m =mPaint.getFontMetrics();

        canvas.drawLine(0, 100 + m.ascent ,1000, 100 + m.ascent, mPaint);

        canvas.drawLine(0, 100 + m.descent ,1000, 100 + m.descent, mPaint);

    }

}

activity代码:

public class FontSizeActivityextends AppCompatActivity {

public static final StringTAG ="FontSizeActivity";

    @BindView(R.id.font_size_tv)

TextViewfontSizeTv;

    @BindView(R.id.bold_check_box)

CheckBoxboldCheckBox;

    @BindView(R.id.italic_check_box)

CheckBoxitalicCheckBox;

    @BindView(R.id.font_family_rg)

RadioGroupfontFamilyRg;

    @BindView(R.id.log_tv)

TextViewlogTv;

    @BindView(R.id.show_text_view)

ShowTextViewshowTextView;

    private boolean isBold =false;

    private boolean isItalic =false;

    private int fontSize =100;

    private PaintmPaint =new Paint();

    private Stringsigle_zh ="国";

    private Stringdouble_zh ="中国";

    private TypefacecurrentTypeface = Typeface.SANS_SERIF;

    private TypefacecustomTypeface;

    private CompoundButton.OnCheckedChangeListenercheckedChangeListener =new CompoundButton.OnCheckedChangeListener() {

@Override

        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {

switch (buttonView.getId()) {

case R.id.bold_check_box:

isBold = isChecked;

break;

                case R.id.italic_check_box:

isItalic = isChecked;

break;

            }

updateTypeface();

            measureStringSize();

        }

};

    @Override

    protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_font_size);

        ButterKnife.bind(this);

        ((CheckBox)findViewById(R.id.italic_check_box)).setOnCheckedChangeListener(checkedChangeListener);

        ((CheckBox)findViewById(R.id.bold_check_box)).setOnCheckedChangeListener

(checkedChangeListener);

        fontFamilyRg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

@Override

            public void onCheckedChanged(RadioGroup group, int checkedId) {

switch (checkedId) {

case R.id.rbtn_serif:

currentTypeface = Typeface.SERIF;

break;

                    case R.id.rbtn_sans:

currentTypeface = Typeface.SANS_SERIF;

break;

                    case R.id.rbtn_monospace:

currentTypeface = Typeface.MONOSPACE;

break;

                    case R.id.rbtn_custom:

if (customTypeface ==null) {

customTypeface = Typeface.createFromAsset(getAssets(), "goodNight.ttf");

                        }

currentTypeface =customTypeface;

break;

                }

updateTypeface();

                measureStringSize();

            }

});

        fontSizeTv.setText("" +fontSize);

        mPaint.setTextSize(fontSize);

        showTextView.setPaint(mPaint);

    }

private void updateTypeface() {

Typeface font;

        if (isBold) {

font = Typeface.create(currentTypeface, isItalic ? Typeface.BOLD_ITALIC : Typeface.BOLD);

        }else {

font = Typeface.create(currentTypeface, isItalic ? Typeface.ITALIC : Typeface.NORMAL);

        }

mPaint.setTypeface(font);

    }

@OnClick({R.id.font_size_big_btn, R.id.font_size_small_btn})

public void onViewClicked(View view) {

switch (view.getId()) {

case R.id.font_size_big_btn:

fontSize +=2;

break;

            case R.id.font_size_small_btn:

fontSize -=2;

break;

        }

fontSizeTv.setText("" +fontSize);

        mPaint.setTextSize(fontSize);

        measureStringSize();

    }

private void measureStringSize() {

showTextView.setPaint(mPaint);

        showTextView.invalidate();

        Paint.FontMetrics metrics =mPaint.getFontMetrics();

        String metricsStr = String.format("metrics = ascent: %f, bottom: %f,descent: %f, leading:%f, top: %f",

                metrics.ascent, metrics.bottom, metrics.descent, metrics.leading, metrics.top);

        Log.d(TAG, metricsStr);

        float sigleChineseW =mPaint.measureText(sigle_zh);

        float doubleChineseW =mPaint.measureText(double_zh);

        float thirdW =mPaint.measureText(showTextView.string);

        Log.i(TAG, "width: 1th: " + sigleChineseW +", 2th : " + doubleChineseW +", 3th : " + thirdW);

    }

}

经过调整可以得出以下结论:

1.字体的宽高与加粗、斜体无关;

2.如果不计算字间距的话,字符串的长度为每个字符长度之和

3.字符的高度是Paint.FontMetrics控制的,其与字体(Typeface),字体大小(fontsize)相关。字体大小(fontsize)改变,FontMetrics内的参数会按照比例变化。如果字体大小(fontsize)固定,改变字体(Typeface),会获得不同的参数。如果需要频繁获取字符高度,可以先将字体大小固定为100,获取不同的字体(Typeface)的FontMetrics参数,然后根据响应的参数与字体大小做比例换算。

4.字符的宽度与文字类型,字体大小相关。如果文字不改变,只改变字体大小(fontsize),字符宽度会成比例变化。改变不同的文字会对固定的字体大小(fontsize)的字符宽度产生不同的变化。

5.中文字是方块字(小学老师教的),所以你字体大小(fontsize)又多大,字符宽度就会是多大。

你可能感兴趣的:(android 字体宽高影响因素调研)