TextView两端对齐
来源:互联网 发布:伦敦生活 知乎 编辑:程序博客网 时间:2024/06/06 16:15
在res文件加下添加attrs.xml文件,用于设置styleable
<?xml version="1.0" encoding="utf-8"?><resources> <!-- 末行对齐方式 --> <declare-styleable name="AlignTextView"> <attr name="align" format="enum"> <enum name="left" value="0"/> <enum name="center" value="1"/> <enum name="right" value="2"/> </attr> </declare-styleable></resources>
自定义AlignTextView.java类,继承自TextView
import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.text.TextPaint;import android.util.AttributeSet;import android.util.TypedValue;import android.widget.TextView;import java.util.ArrayList;import java.util.List;/** * 两端对齐的text view,可以设置最后一行靠左,靠右,居中对齐 * * @author YD */public class AlignTextView extends TextView { private float textHeight; // 单行文字高度 private float textLineSpaceExtra = 0; // 额外的行间距 private int width; // textView宽度 private List<String> lines = new ArrayList<String>(); // 分割后的行 private List<Integer> tailLines = new ArrayList<Integer>(); // 尾行 private Align align = Align.ALIGN_LEFT; // 默认最后一行左对齐 private boolean firstCalc = true; // 初始化计算 private float lineSpacingMultiplier = 1.0f; private float lineSpacingAdd = 0.0f; private int originalHeight = 0; //原始高度 private int originalLineCount = 0; //原始行数 private int originalPaddingBottom = 0; //原始paddingBottom private boolean setPaddingFromMe = false; // 尾行对齐方式 public enum Align { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT // 居中,居左,居右,针对段落最后一行 } public AlignTextView(Context context) { super(context); setTextIsSelectable(false); } public AlignTextView(Context context, AttributeSet attrs) { super(context, attrs); setTextIsSelectable(false); lineSpacingMultiplier = attrs.getAttributeFloatValue("http://schemas.android" + "" + ".com/apk/res/android", "lineSpacingMultiplier", 1.0f); int[] attributes = new int[]{android.R.attr.lineSpacingExtra}; TypedArray arr = context.obtainStyledAttributes(attrs, attributes); lineSpacingAdd = arr.getDimensionPixelSize(0, 0); originalPaddingBottom = getPaddingBottom(); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AlignTextView); int alignStyle = ta.getInt(R.styleable.AlignTextView_align, 0); switch (alignStyle) { case 1: align = Align.ALIGN_CENTER; break; case 2: align = Align.ALIGN_RIGHT; break; default: align = Align.ALIGN_LEFT; break; } ta.recycle(); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); //首先进行高度调整 if (firstCalc) { width = getMeasuredWidth(); String text = getText().toString(); TextPaint paint = getPaint(); lines.clear(); tailLines.clear(); // 文本含有换行符时,分割单独处理 String[] items = text.split("\\n"); for (String item : items) { calc(paint, item); } //使用替代textview计算原始高度与行数 measureTextViewHeight(text, paint.getTextSize(), getMeasuredWidth() - getPaddingLeft() - getPaddingRight()); //获取行高 textHeight = 1.0f * originalHeight / originalLineCount; textLineSpaceExtra = textHeight * (lineSpacingMultiplier - 1) + lineSpacingAdd; //计算实际高度,加上多出的行的高度(一般是减少) int heightGap = (int) ((textLineSpaceExtra + textHeight) * (lines.size() - originalLineCount)); setPaddingFromMe = true; //调整textview的paddingBottom来缩小底部空白 setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), originalPaddingBottom + heightGap); firstCalc = false; } } @Override protected void onDraw(Canvas canvas) { TextPaint paint = getPaint(); paint.setColor(getCurrentTextColor()); paint.drawableState = getDrawableState(); width = getMeasuredWidth(); Paint.FontMetrics fm = paint.getFontMetrics(); float firstHeight = getTextSize() - (fm.bottom - fm.descent + fm.ascent - fm.top); int gravity = getGravity(); if ((gravity & 0x1000) == 0) { // 是否垂直居中 firstHeight = firstHeight + (textHeight - firstHeight) / 2; } int paddingTop = getPaddingTop(); int paddingLeft = getPaddingLeft(); int paddingRight = getPaddingRight(); width = width - paddingLeft - paddingRight; for (int i = 0; i < lines.size(); i++) { float drawY = i * textHeight + firstHeight; String line = lines.get(i); // 绘画起始x坐标 float drawSpacingX = paddingLeft; float gap = (width - paint.measureText(line)); float interval = gap / (line.length() - 1); // 绘制最后一行 if (tailLines.contains(i)) { interval = 0; if (align == Align.ALIGN_CENTER) { drawSpacingX += gap / 2; } else if (align == Align.ALIGN_RIGHT) { drawSpacingX += gap; } } for (int j = 0; j < line.length(); j++) { float drawX = paint.measureText(line.substring(0, j)) + interval * j; canvas.drawText(line.substring(j, j + 1), drawX + drawSpacingX, drawY + paddingTop + textLineSpaceExtra * i, paint); } } } /** * 设置尾行对齐方式 * * @param align 对齐方式 */ public void setAlign(Align align) { this.align = align; invalidate(); } /** * 计算每行应显示的文本数 * * @param text 要计算的文本 */ private void calc(Paint paint, String text) { if (text.length() == 0) { lines.add("\n"); return; } int startPosition = 0; // 起始位置 float oneChineseWidth = paint.measureText("中"); int ignoreCalcLength = (int) (width / oneChineseWidth); // 忽略计算的长度 StringBuilder sb = new StringBuilder(text.substring(0, Math.min(ignoreCalcLength + 1, text.length()))); for (int i = ignoreCalcLength + 1; i < text.length(); i++) { if (paint.measureText(text.substring(startPosition, i + 1)) > width) { startPosition = i; //将之前的字符串加入列表中 lines.add(sb.toString()); sb = new StringBuilder(); //添加开始忽略的字符串,长度不足的话直接结束,否则继续 if ((text.length() - startPosition) > ignoreCalcLength) { sb.append(text.substring(startPosition, startPosition + ignoreCalcLength)); } else { lines.add(text.substring(startPosition)); break; } i = i + ignoreCalcLength - 1; } else { sb.append(text.charAt(i)); } } if (sb.length() > 0) { lines.add(sb.toString()); } tailLines.add(lines.size() - 1); } @Override public void setText(CharSequence text, BufferType type) { firstCalc = true; super.setText(text, type); } @Override public void setPadding(int left, int top, int right, int bottom) { if (!setPaddingFromMe) { originalPaddingBottom = bottom; } setPaddingFromMe = false; super.setPadding(left, top, right, bottom); } /** * 获取文本实际所占高度,辅助用于计算行高,行数 * * @param text 文本 * @param textSize 字体大小 * @param deviceWidth 屏幕宽度 */ private void measureTextViewHeight(String text, float textSize, int deviceWidth) { TextView textView = new TextView(getContext()); textView.setText(text); textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); int widthMeasureSpec = MeasureSpec.makeMeasureSpec(deviceWidth, MeasureSpec.EXACTLY); int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); textView.measure(widthMeasureSpec, heightMeasureSpec); originalLineCount = textView.getLineCount(); originalHeight = textView.getMeasuredHeight(); }}
activity_main.xml布局中添加一个普通的TextView,添加一个AlignTextView
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.zcn.demo.aligntextview.MainActivity"> <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <!--com.zcn.demo.aligntextview这个路径是你自定义AlignTextView类的路径--> <com.zcn.demo.aligntextview.AlignTextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>
AlignTextViews的使用和正常的TextView使用一样
public class MainActivity extends AppCompatActivity { private AlignTextView alignText; private TextView text; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (TextView)findViewById(R.id.text); text.setText("这个是测试文本,用于观察现象,做对比使用,this is test text,for to see the different in different Controls"); alignText = (AlignTextView)findViewById(R.id.text1); alignText.setText("这个是测试文本,用于观察现象,做对比使用,this is test text,for to see the different in different Controls"); }}
阅读全文
0 0
- 两端对齐的TextView
- Android TextView两端对齐
- Android TextView两端对齐
- TextView两端对齐
- 自定义 TextView 两端对齐
- TextView两端对齐
- Android TextView两端对齐、文本两端对齐
- 两端分散对齐的Textview
- Android两端对齐的TextView
- android TextView 分散对齐(两端对齐)
- TextView实现分散对齐(两端对齐)
- 实现TextView 文字排版,分散两端对齐
- textview 文字排版问题,实现两端对齐
- Android TextView两端完美对齐解决方案
- 自定义TextView使上下文字两端对齐
- Android textview文字两端对齐,中间空白
- Android]TextView实现分散对齐(两端对齐)
- [Android]TextView实现分散对齐(两端对齐)
- LeedCode Longest Substring Without Repeating Characters
- 认识AS中的Gradle
- 51nod 1183 编辑距离
- Mybatis Cause: java.lang.ClassNotFoundException: Cannot find class: BaseResultMap
- 强大的vim配置文件,让编程更随意
- TextView两端对齐
- springcloud_7(配置中心的高可用)
- hdu 3605 Escape (二分图匹配)
- hdu1166:敌兵布阵
- 看国外女神级程序员,直播写代码一年的感悟
- hdu 4027
- Java中@Override的作用和用法
- poj 1147:Binary codes (置换群)
- 数据库SQL优化大总结之 百万级数据库优化方案