赞
踩
在客户端中不论是PC端,还是移动端主要价值之一就体现在用户交互方面,也就是用户体验了,接下来讲的是很常见的字体加粗问题
UI大找茬
在开发中经常会遇到设计说某个文本字体粗度不对,需要重一点,或者轻一点,这时候当系统控件原属性不满足需求时,就需要我们定制化处理一下
虽然看起来写了不少,但其实核心只在于获取当前控件的 Paint(画笔)
后重新设置strokeWidth、style
属性 ,然后重新绘制即可!
tip
:差点忘记说了,如果通过该篇未满足你的诉求,你可以看一下设计是否使用了字体库,一般字体库也会提供常规字体和加粗字体,关于字体库方面的知识,可以直接前往 深入浅出字体、字体库
设计比较喜欢拿 Android 与 IOS 做对比,所以经常会遇到一些 IOS 分分钟解决的问题,Android 却需要花多倍的时间来处理,以前经常会遇到 1 IOS = 1.5||2 Android 的场景,现在这环境可能比较这样的场景也比较少咯
关于字体粗度的实际设置,主要是在体现其 字重
(字体粗细),因字重等级不同,带来的效果也有所不同
Andoird 提供的字体粗度主要有俩种
相对于Android 提供的 regular-400
,bold-700
两种字重(设置600以下均以400字重效果来显示;设置700才会显示出加粗文字)- 源码中常以 0 - 1设置字重 ;iOS系统原生字体字重等级全面,从100-600都有,效果也更全一些,网上找了一个对比图如下
由于 Andoird 的开源性,在国内有着众多厂商,不同厂商有时候也会设计自已品牌的系统字体包,所以即便是相同的代码,也可能在不同的安卓手机上呈现的效果也可能不相同,因此我们往往需要通过一些自定义控件来尽量保持效果的一致性!
Android 为 TextView
、EditText
提供了 textStyle
属性用于设置字体粗度
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="字体粗度"
android:textStyle="bold" />
实现效果
关于 textStyle
属性值,主要提供了以下三种类型
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MediumTextView">
<attr name="mediumState" format="boolean" />
</declare-styleable>
</resources>
首先在 attr/attrs
添加自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MediumTextView">
<attr name="mediumState" format="boolean" />
</declare-styleable>
</resources>
实现效果
Tip:以下俩种方式均可正常使用,建议使用优化后的减少无效逻辑
package com.example.boldtext import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.support.v7.widget.AppCompatTextView import android.util.AttributeSet class MediumOldTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) { private var mediumState: Boolean = false init { val array = context.obtainStyledAttributes(attrs, R.styleable.MediumTextView) mediumState = array.getBoolean(R.styleable.MediumTextView_mediumState, false) array.recycle() } override fun onDraw(canvas: Canvas?) { if (mediumState) { val strokeWidth = paint.strokeWidth val style = paint.style paint.strokeWidth = 0.6f paint.style = Paint.Style.FILL_AND_STROKE super.onDraw(canvas) paint.strokeWidth = strokeWidth paint.style = style } else { super.onDraw(canvas) } } fun setMediumState(mediumState: Boolean) { this.mediumState = mediumState requestLayout() } }
去除一些无用逻辑、代码
package com.example.boldtext import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.support.v7.widget.AppCompatTextView import android.util.AttributeSet class MediumTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) { private var mediumState: Boolean = false init { val array = context.obtainStyledAttributes(attrs, R.styleable.MediumTextView) mediumState = array.getBoolean(R.styleable.MediumTextView_mediumState, false) array.recycle() } override fun onDraw(canvas: Canvas?) { if (mediumState) { //可通过设置该数值改变加粗字重 paint.strokeWidth = 0.6f paint.style = Paint.Style.FILL_AND_STROKE } super.onDraw(canvas) } fun setMediumText(mediumText: Boolean) { this.mediumState = mediumText requestLayout() // postInvalidate() } }
静态为 xml
设置,动态为代码设置
<com.example.boldtext.MediumTextView
android:id="@+id/medium_view"
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:text="加粗字体"
app:mediumState="true" />
package com.example.boldtext
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val mediumView = findViewById<MediumTextView>(R.id.medium_view)
//设置加粗
mediumView.setMediumState(true)
}
}
实现效果
Tip:假设别的组件也有字体加粗的需求,可以尝试继承该组件
创建 - 自定义组件
package com.example.boldtext import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.support.v7.widget.AppCompatTextView import android.util.AttributeSet open class TypefaceTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) { private var mTypefaceScale: Float = 0.0f enum class TypefaceScale { MEDIUM, MEDIUM_SMALL, DEFAULT, } override fun onDraw(canvas: Canvas?) { if (mTypefaceScale == 0f) { return super.onDraw(canvas) } val strokeWidth = paint.strokeWidth val style = paint.style paint.strokeWidth = mTypefaceScale paint.style = Paint.Style.FILL_AND_STROKE super.onDraw(canvas) paint.strokeWidth = strokeWidth paint.style = style } fun setTypefaceScale(scale: TypefaceScale = TypefaceScale.DEFAULT) { mTypefaceScale = when (scale) { TypefaceScale.DEFAULT -> 0.0f TypefaceScale.MEDIUM_SMALL -> 0.6f TypefaceScale.MEDIUM -> 1.1f } postInvalidate() } }
使用方式
package com.example.boldtext
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val typefaceView = findViewById<TypefaceTextView>(R.id.typeface_view)
//设置加粗
typefaceView.setTypefaceScale(TypefaceTextView.TypefaceScale.MEDIUM_SMALL)
}
}
控件引入
<com.example.boldtext.TypefaceTextView
android:id="@+id/typeface_view"
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
android:text="TypefaceTextView 加粗字体" />
扩展:因为我们用的是 splitties
三方的一个布局组件,所以分享、记录一些扩展函数,逐步分析、学习
布局方式
add(lParams(), typefaceTextView {
gravity = gravityEnd
typefaceScale = TypefaceScale.MEDIUM_SMALL
textSize = 14f
textColor = "#333333".toColorInt()
})
add函数 将子布局添加到对应ViewGroup中
import android.view.View
import android.view.ViewGroup
inline fun <V : View> ViewGroup.add(lp: ViewGroup.LayoutParams, view: V): V = view.also { addView(it, lp) }
splitties - lParams
函数
inline fun LinearLayout.lParams( width: Int = wrapContent, height: Int = wrapContent, initParams: LinearLayout.LayoutParams.() -> Unit = {} ): LinearLayout.LayoutParams { contract { callsInPlace(initParams, InvocationKind.EXACTLY_ONCE) } return LinearLayout.LayoutParams(width, height).apply(initParams) } inline fun LinearLayout.lParams( width: Int = wrapContent, height: Int = wrapContent, gravity: Int = -1, weight: Float = 0f, initParams: LinearLayout.LayoutParams.() -> Unit = {} ): LinearLayout.LayoutParams { contract { callsInPlace(initParams, InvocationKind.EXACTLY_ONCE) } return LinearLayout.LayoutParams(width, height).also { it.gravity = gravity it.weight = weight }.apply(initParams) }
View - typefaceTextView
函数
// TypefaceTextView 防苹果系统的字体加粗------------------------------------------------------------------ inline fun Context.typefaceTextView( @IdRes id: Int = View.NO_ID, @StyleRes theme: Int = NO_THEME, initView: TypefaceTextView.() -> Unit = {} ): TypefaceTextView { return view(::TypefaceTextView, id, theme, initView) } inline fun View.typefaceTextView( @IdRes id: Int = View.NO_ID, @StyleRes theme: Int = NO_THEME, initView: TypefaceTextView.() -> Unit = {} ): TypefaceTextView { return context.typefaceTextView(id, theme, initView) } inline fun Ui.typefaceTextView( @IdRes id: Int = View.NO_ID, @StyleRes theme: Int = NO_THEME, initView: TypefaceTextView.() -> Unit = {} ): TypefaceTextView { return ctx.typefaceTextView(id, theme, initView) } // -------------------------------------------------------------------------------------------------------
typefaceTextView - typefaceScale
加粗类型函数
enum class TypefaceScale { // MEDIUM, MEDIUM_SMALL, DEFAULT, } var TypefaceTextView.typefaceScale: TypefaceScale @Deprecated(NO_GETTER, level = DeprecationLevel.HIDDEN) get() = noGetter set(value) { val scale = when (value) { // TypefaceScale.MEDIUM -> TypefaceTextView.TypefaceScale.MEDIUM TypefaceScale.MEDIUM_SMALL -> TypefaceTextView.TypefaceScale.MEDIUM_SMALL TypefaceScale.DEFAULT -> TypefaceTextView.TypefaceScale.DEFAULT } setTypefaceScale(scale) }
为了方便直接在 xml
中使字体加粗,需要在控件上引入自定义属性,故需添加以下属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TypefaceTextView">
<attr name="fontScale" format="enum">
<enum name="normal" value="0" />
<enum name="medium" value="1" />
<enum name="bold" value="2" />
</attr>
</declare-styleable>
</resources>
创建 - 自定义组件
package com.example.boldtext import android.content.Context import android.graphics.Canvas import android.graphics.Paint import android.support.v7.widget.AppCompatTextView import android.util.AttributeSet class TypefaceTextView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatTextView(context, attrs, defStyleAttr) { private var mTypefaceScale: Float = 0.0f init { if (attrs != null) { val array = context.obtainStyledAttributes(attrs, R.styleable.TypefaceTextView) val typefaceScale = array.getInt(R.styleable.TypefaceTextView_fontScale, 0) mTypefaceScale = when (typefaceScale) { 1 -> 0.6f 2 -> 1.1f else -> 0.0f } array.recycle() } } enum class TypefaceScale { MEDIUM, DEFAULT, BOLD } override fun onDraw(canvas: Canvas?) { if (mTypefaceScale == 0f) { return super.onDraw(canvas) } val strokeWidth = paint.strokeWidth val style = paint.style paint.strokeWidth = mTypefaceScale paint.style = Paint.Style.FILL_AND_STROKE super.onDraw(canvas) paint.strokeWidth = strokeWidth paint.style = style } internal fun setTypefaceScale(scale: TypefaceScale = TypefaceScale.DEFAULT) { mTypefaceScale = when (scale) { TypefaceScale.DEFAULT -> 0.0f TypefaceScale.MEDIUM -> 0.6f TypefaceScale.BOLD -> 1.1f } invalidate() } }
静态设置 fontScale
属性为枚举类型中的其一
<com.example.boldtext.TypefaceTextView
android:layout_width="match_parent"
android:layout_height="45dp"
android:gravity="center"
app:fontScale="bold"
android:text="TypefaceTextView 加粗字体" />
package com.example.boldtext
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val typefaceView = findViewById<TypefaceLTextView>(R.id.typeface_view)
//设置加粗
typefaceView.setTypefaceScale(TypefaceLTextView.TypefaceScale.MEDIUM)
}
}
只能设置我们声明的枚举类型,如果项目需要扩展到更多粗度的话,可以自行增加!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。