TextView 设置行高并垂直居中

需求: TextView 多行文本可以设置行高(如20dp),每行文本垂直居中。

效果如下:

多行文本,设置行高,垂直居中

实现思路:通过设置 TextView 的 lineSpacingExtralineSpacingMultiplier 来实现。

  • lineSpacingMultiplier 的值为行间距的倍数,默认值为 1.0f。
  • lineSpacingExtra 值为具体的行间距值,如20dp。
  • 垂直居中靠设置 paddingTop 和 paddingBottom

TextView 相关

TextView 内部除了继承自 View 的相关属性和 measure、layout、draw步骤,还包括:
- Layout: TextView 的文字排版、折行策略以及文本绘制都是在 Layout 里面完成的,TextView 的自身测量也受 Layout 的影响。Layout 是 TextView 执行setText方法后,由 TextView 内部创建的实例,并不能由外部提供。Layout有三个子类,BoringLayout、DynamicLayout、StaticLayout。
- TransformationMethod: 用来处理最终的显示结果的类,例如显示密码的时候把密码转换成圆点。这个类并不直接影响 TextView 内部储存的 Text ,只影响显示的结果。
- MovementMethod: 用来处理 TextView 内部事件响应的类,可以针 对TextView 内文本的某一个区域做软键盘输入或者触摸事件的响应。
- Drawables: TextView 的静态内部类,用来处理和储存 TextView 的 CompoundDrawables ,包括 TextView 的上下左右的 Drawable 以及错误提示的 Drawable。
- Spans: Spans 并不是特定的某一个类或者实现了某一个接口的类。它可以是任意类型,Spans实际上做的事情是在 TextView 的内部的 text 的某一个区域做标记。其中有部 分Spans 可以影响TextView的绘制和测量,如 ImageSpan、BackgroundColorSpan、AbsoluteSizeSpan。还有可以响应点击事件的ClickableSpan。
- Editor: TextView作为可编辑文本控件的时候(EditText),使用Editor来处理文本的区域选择处理和判断、拼写检查、弹出文本菜单等。
- InputConnection: EditText 的文本输入部分是在 TextView 中完成的。而 InputConnection 是软键盘和TextView之间的桥梁,所有的软键盘的输入文字、修改文字和删除文字都是通过 InputConnection 传递给 TextView 的。

TextView 默认文字的上下边距

TextView 的 textSize 属性代表的意义是字体的大小,体现为字体高度,一般单位是 sp, sp 代表的字体大小根据手机设置的文字大小有关,默认的 1sp = 1dp。但是Android 系统会默认的给文字增加一点边框。
默认效果

渲染图

Android 提供了一个 setIncludeFontPadding 方法.用来设置 TextView 是否在顶部和底部保留一些空隙,默认为 ture 。如果我们设置为 false 的话可能会导致某些语言显示的不完整, 如 Arabic Kannada 。在 StaticLayoutsetIncludePad 方法提到。

/**
 * Set whether to include extra space beyond font ascent and descent (which is
 * needed to avoid clipping in some languages, such as Arabic and Kannada). The
 * default is {@code true}.
 *
 * @param includePad whether to include padding
 * @return this builder, useful for chaining
 * @see android.widget.TextView#setIncludeFontPadding
 */
public Builder setIncludePad(boolean includePad) {
    mIncludePad = includePad;
    return this;
}

通过 android:includeFontPadding="false" 可以去掉一定的边距值但是不能完全去掉。还少达不到
文字高度精确,所以不通过过设置 lineSpacingMultiplier 来改变, lineSpacingMultiplier 为 0 , 那么多行文本就都变成一行了。
右边的绿色背景的效果

最终结果是:

lineSpacingMultiplier = 0
lineSpacingExtra = 行高
paddingTop = paddingBottom = (行高-字体大小)* 0.5

计算paddingTop

设置高度

封装成控件。这里继承了EditText, 默认的编辑文本时的行高会改变,所以在文本变化时需要重新设置.

package xyz.hanks.note.ui.widget;


import android.content.Context;
import android.graphics.Canvas;
import android.text.Editable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.widget.EditText;

import xyz.hanks.note.R;

/**
 * 每一行的文字垂直居中
 * Created by hanks on 16/7/2.
 */
public class LineTextView extends EditText {

    private float ITEM_HEIGHT = 125;
    boolean reLayout = false;
    TextWatcher textWatcher;

    public LineTextView(Context context) {
        this(context,null);
    }

    public LineTextView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LineTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        addTextChangedListener(new android.text.TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (textWatcher != null) {
                    textWatcher.beforeTextChanged(charSequence, i, i1, i2);
                }
            }
            @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                float add = ITEM_HEIGHT;
                setLineSpacing(0f, 1f);
                setLineSpacing(add, 0);
                setIncludeFontPadding(false);
                setGravity(Gravity.CENTER_VERTICAL);
                int top = (int) ((add - getTextSize()) * 0.5f);
                setPadding(getPaddingLeft(), top, getPaddingRight(), -top);
                if (textWatcher != null) {
                    textWatcher.onTextChanged(charSequence, i, i1, i2);
                }
            }
            @Override public void afterTextChanged(Editable editable) {
                if (textWatcher != null) {
                    textWatcher.afterTextChanged(editable);
                }
            }
        });

    }

    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!reLayout) {
            reLayout = true; 
            setIncludeFontPadding(false);
            setGravity(Gravity.CENTER_VERTICAL);
            setLineSpacing(ITEM_HEIGHT, 0);
            int top = (int) ((ITEM_HEIGHT - getTextSize()) * 0.5f);
            setPadding(getPaddingLeft(), top, getPaddingRight(), -top);
            requestLayout();
            invalidate();
        }
    }

    public void addTextWatcher(TextWatcher textWatcher) {
        this.textWatcher = textWatcher;
    }

    public interface TextWatcher {
        void beforeTextChanged(CharSequence var1, int var2, int var3, int var4);
        void onTextChanged(CharSequence var1, int var2, int var3, int var4);
        void afterTextChanged(Editable var1);
    }
}

参考链接:

TextView源码解析

用TextPaint来绘制文字

文章来自: http://hanks.xyz

发布了272 篇原创文章 · 获赞 60 · 访问量 43万+
展开阅读全文

Android中 垂直居中的问题

12-11

我在LinearLayout中嵌套了一个RelativeLayout布局,在布局文件中有两个TextView,一个内容有一行,一个内容有多行,但我想使这两个TextView中的内容中心对齐,应该怎么做啊? <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/set_name" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="25dp" android:gravity="center_vertical" android:text="设备名称" /> <com.klkj.cealp.publicclass.SlipSwitch android:id="@+id/main_on_off" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/set_name" android:layout_marginRight="10dp" android:layout_marginLeft="15dp" android:layout_centerHorizontal="true" android:layout_weight="1" android:gravity="center" /> <TextView android:id="@+id/set_date_time" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_alignBaseline="@id/set_name" android:layout_toRightOf="@+id/main_on_off" android:gravity="center_vertical" android:paddingRight="10dp" android:text="@string/date_time" /> </RelativeLayout> </LinearLayout> 不会插入图片啊 要不就发个图片看一下了 求解 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览