300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > TextView设置字重(自定义自重)

TextView设置字重(自定义自重)

时间:2023-02-04 18:22:17

相关推荐

TextView设置字重(自定义自重)

TextView自定义加粗

1、目的2、三种加粗方法3、第三种方式额外问题以及解决方案3.1实现细节

1、目的

android提供的几种加粗方法不满足我司ui设计的字体字重

2、三种加粗方法

设置TextView的textStyle为Bold,这种方式的textView很粗

xml:android:textStyle="bold"

代码:paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));

代码设置FakeBoldText,这种方式加粗过的比较接近medium效果

paint.setFakeBoldText(true)

如果以上都不满足ui小姐姐,我们还可以换种思路,TextView的加粗其实本质就是画笔paint的粗细,我们可以通过设置画笔的宽度来满足需求

paint.setStrokeWidth(8f);paint.setStyle(Paint.Style.FILL_AND_STROKE);

(设置Style为FILL_AND_STROKE的目的是:如果字体过大,填充模式为STROKE的话就会出现字画之间的漏洞,设置FILL不会有效果,如图)

STOKE模式:

FIll模式:

3、第三种方式额外问题以及解决方案

问题:

1、每个TextView都这样设置的话,重复代码太多

2、字重之间没有一个衡量单位标准

3、字号大小不同需要设置不同的StrokeWidth,如果不设置,小字号看起来很粗,大字号看起来没效果

解决方案:

1、继承LayoutFactory2(每个view创建的地方),在xml里面自定义设置一个额外属性,如果有地方需要自定义自重,使用该属性设置

2、与自家ui小姐姐商讨确定字重的等级集,比如我们公司就制定一共5个等级字重

3、根据字号以及等级,设计一套计算规则来计算出StrokeWidth

3.1实现细节

在xml中自定义属性textBoldStyle,枚举,定义了5个等级

<!-- 系统TextView自定义额外属性 --><attr name="textBold" format="enum"><enum name="zero" value="0" /><enum name="one" value="1" /><enum name="two" value="2" /><enum name="three" value="3" /><enum name="four" value="4" /></attr>

在要用到的xml的文件TextVIew节点下设置该属性

<TextViewandroid:id="@+id/textView3"style="@style/TextVIewStyle"app:textBold="two" />

style属性:

<style name="TextVIewStyle"><item name="android:layout_width">match_parent</item><item name="android:layout_height">100dp</item><item name="android:gravity">center</item><item name="android:text">Hello World!你好世界!</item><item name="android:textSize">20sp</item></style>

重写LayoutFactory2,关键思想就是重写onCreateView,自己创建TextView以及TextView的子类(怎么重写?一个字,抄,抄系统源码),然后读取textBold属性,获取加粗等级,然后设计一套计算规则(我只是简单的根据字体dp进行等比放大缩小,效果还可以),得到设置画笔宽度的值

import android.content.Context;import android.content.res.TypedArray;import android.graphics.Paint;import android.graphics.Typeface;import android.text.TextUtils;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.TextView;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;public class NightThemeInflaterFactory implements LayoutInflater.Factory2 {private Map<TextView, Integer> map = new HashMap<>();private static final String NAMESPACE_RES_AUTO = "/apk/res-auto";private static final String[] mClassPrefixList = {"android.widget.","android.webkit.","android.app.","android.view."};//记录对应VIEW的构造函数private static final Class<?>[] mConstructorSignature = new Class[]{Context.class, AttributeSet.class};private static final HashMap<String, Constructor<? extends View>> mConstructorMap =new HashMap<String, Constructor<? extends View>>();@Overridepublic View onCreateView(View parent, String name, Context context, AttributeSet attrs) {return onCreateView(name, context, attrs);}@Overridepublic View onCreateView(String name, Context context, AttributeSet attrs) {//创建系统的控件View view = createSDKView(name, context, attrs);if (null == view) {//创建非系统控件view = createView(name, context, attrs);}//如果是TextView或者是继承了TextView的子控件if (view instanceof TextView) {TextView textView = (TextView) view;//查找textBold属性(xml中直接定义的)int value = attrs.getAttributeIntValue(NAMESPACE_RES_AUTO, "textBold", -1);//查找textBold属性(写在style里面的)if (value == -1) {TypedArray typedArray = context.obtainStyledAttributes(R.style.TextVIewStyle, new int[]{R.attr.textBold});value = typedArray.getInt(0, -1);typedArray.recycle();}float density = getDensity(context);float textSize = textView.getTextSize();//将文字大小换算成dp属性,根据dp进行放大缩小系数int dp = (int) (textSize / density);//我的项目是以dp的1/10为最大的等级,最低等级是0即正常字体(不加粗),//然后在1/10的基础上再划分为4个等级float fullNums = dp / 20f;value = Math.min(value, 4);float targetLevel = fullNums * value;if (value > -1 && textView.getTypeface().getStyle() != Typeface.BOLD) {textView.getPaint().setStrokeWidth(targetLevel);textView.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);map.put(textView, value);}}return view;}public void generateTvBold(float percent, Context context) {//我的项目是以dp的1/10为最大的等级,最低等级是0即正常字体(不加粗),//然后在1/10的基础上再划分为4个等级float density = getDensity(context);TextView textView = null;for (Map.Entry<TextView, Integer> entry : map.entrySet()) {textView = entry.getKey();float textSize = textView.getTextSize();int dp = (int) (textSize / density);float fullNums = dp / percent;int value = entry.getValue();float targetLevel = fullNums * value;textView.getPaint().setStrokeWidth(targetLevel);textView.getPaint().setStyle(Paint.Style.FILL_AND_STROKE);textView.invalidate();}}private View createSDKView(String name, Context context, AttributeSetattrs) {//如果包含 . 则不是SDK中的view 可能是自定义view包括support库中的Viewif (-1 != name.indexOf('.')) {return null;}//不包含就要在解析的 节点 name前,拼上: android.widget. 等尝试去反射for (int i = 0; i < mClassPrefixList.length; i++) {View view = createView(mClassPrefixList[i] + name, context, attrs);if (view != null) {return view;}}return null;}/*** @param name* @param context* @param attrs 反射创建view* @return*/private View createView(String name, Context context, AttributeSetattrs) {Constructor<? extends View> constructor = findConstructor(context, name);try {return constructor.newInstance(context, attrs);} catch (Exception e) {}return null;}private Constructor<? extends View> findConstructor(Context context, String name) {Constructor<? extends View> constructor = mConstructorMap.get(name);if (constructor == null) {try {Class<? extends View> clazz = context.getClassLoader().loadClass(name).asSubclass(View.class);constructor = clazz.getConstructor(mConstructorSignature);mConstructorMap.put(name, constructor);} catch (Exception e) {}}return constructor;}private float getDensity(Context context) {return context.getResources().getDisplayMetrics().density;}}

在activity的onCreate函数的setContentView之前设置使用我们自定义的layoutFactory2

@Overrideprotected void onCreate(Bundle savedInstanceState) {LayoutInflaterCompat.setFactory2(getLayoutInflater(), CustomFactory());super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。