gpt4 book ai didi

android - 在 Android 的 TextView 中对齐文本

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:12:55 24 4
gpt4 key购买 nike

因此,正如你们大多数人所知,在 Android 的 TextView 中没有文本对齐。所以,我构建了一个自定义 TextView 来解决这个问题。但是,出于某种原因,有时标点符号会在某些设备中由于某种原因而中断行。我在 LG G3 和模拟器(运行最新版本的 Nexus 4)和逗号“,”上进行了测试,例如打破了 LG G3 上的理由,但在模拟器上没有。

如果我添加一个至少为 2 的 Padding start 和 end(或 left 和 right),问题就解决了。这对我来说看起来很武断。

基本上,我的逻辑是为了证明文本的合理性,我需要知道 TextView 本身的宽度,将文本构造成最大长度的行。然后,通过找到行中的空格数和剩余的空白空间,根据剩余像素(或 View 中的空间)拉伸(stretch)要缩放的“”(空格)字符。

它几乎完美地工作,而且大多数时候它也支持 RTL 文本。

这里有一些文本图片(一个简单的 lorem impsum),有和没有违规标记(第一个是在运行 7.1.1 的模拟器 nexus 4 上,第二个是在运行 v5.0 的 LG G3 上) Text on emulator running nexus 4 running Text on LG G3 running android 5.0

代码如下:

public class DTextView extends AppCompatTextView {

private boolean justify;

public DTextView(Context context) {
super(context);
}

public DTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(attrs);
}

public DTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}

private void setJustify(boolean justify) {
this.justify = justify;
if (justify) {
justify();
}
}

private void init(@Nullable AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DTextView, 0, 0);
justify = ta.getBoolean(R.styleable.DTextView_justify, false);

ta.recycle();
}

private SpannableStringBuilder justifyText() {

String[] words = getText().toString().split(" ");
setText("");

int maxLineWidth = getWidth() - getPaddingLeft() - getPaddingRight();

SpannableStringBuilder justifiedTextSpannable = new SpannableStringBuilder();

//This will build the new text with the lines rearranged so that they will have a width
//bigger than the View's own width
ArrayList<String> lines = new ArrayList<>(0);
String line = "";
for (String word : words) {
if (getWordWidth(line + word) < maxLineWidth) {
line += word + " ";
} else {
line = line.substring(0, line.length() - 1);
lines.add(line);
line = word + " ";
}
}
//Add the last line
lines.add(line);

for (int i = 0; i < lines.size() - 1; i++) {
justifiedTextSpannable.append(justifyLine(lines.get(i), maxLineWidth));
justifiedTextSpannable.append("\n");
}

justifiedTextSpannable.append(lines.get(lines.size() - 1));


return justifiedTextSpannable;
}

private SpannableString justifyLine(String line, float maxWidth) {

SpannableString sLine = new SpannableString(line);
float spaces = line.split(" ").length - 1;

float spaceCharSize = getWordWidth(" ");
float emptySpace = maxWidth - getWordWidth(line);
float newSpaceSize = (emptySpace / spaces) + spaceCharSize;
float scaleX = newSpaceSize / spaceCharSize;

for (int i = 0; i < line.length(); i++) {
if (line.charAt(i) == ' ') {
sLine.setSpan(new ScaleXSpan(scaleX), i, i + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}

return sLine;
}

private void justify() {
justify = false;
setText(justifyText());
invalidate();
}

private float getWordWidth(String word) {
return getPaint().measureText(word);
}

@Override
protected void onDraw(Canvas canvas) {
if (!justify)
super.onDraw(canvas);
else
justify();
}
}

我将非常感谢任何可以阐明这一点的人。

最佳答案

所以,在仔细研究之后:https://github.com/ufo22940268/android-justifiedtextview和一般的 TextView,我发现我的主要问题是我的方法。

使用缩放“”字符宽度的方法在理论上是合理的,但这样做之后,线条的宽度再次发生变化,因为线条的宽度似乎不是其各部分的总和。

我改变了我的方法并从上面的链接中获得灵感,所以在我的新方法中我单独绘制每个字符,而不是绘制整条线。如果文本需要对齐(基于自定义的“justify” bool 属性),那么它会画线并对齐它,否则它只会画线。

编辑:我现在更改了代码,以便它也支持 RTL 文本。我将在接下来的几天内将代码上传到某个地方。

结果如下: justify textview

代码如下:

public class DTextView extends AppCompatTextView {


private boolean justify;
private float textAreaWidth;
private float spaceCharSize;
private float lineY;

public DTextView(Context context) {
super(context);
}

public DTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}

public DTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}

/**
* @param attrs the attributes from the xml
* This function loads all the parameters from the xml
*/
private void init(AttributeSet attrs) {

TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DTextView, 0, 0);

justify = ta.getBoolean(R.styleable.DTextView_justify, false);

ta.recycle();
}

@Override
protected void onDraw(Canvas canvas) {
drawText(canvas);
}

private void drawText(Canvas canvas) {
TextPaint paint = getPaint();
paint.setColor(getCurrentTextColor());
paint.drawableState = getDrawableState();
textAreaWidth = getMeasuredWidth() - (getPaddingLeft() + getPaddingRight());

spaceCharSize = paint.measureText(" ");

String text = getText().toString();
lineY = getTextSize();

Layout textLayout = getLayout();

if (textLayout == null)
return;

Paint.FontMetrics fm = paint.getFontMetrics();
int textHeight = (int) Math.ceil(fm.descent - fm.ascent);
textHeight = (int) (textHeight * getLineSpacingMultiplier() + textLayout.getSpacingAdd());

for (int i = 0; i < textLayout.getLineCount(); i++) {

int lineStart = textLayout.getLineStart(i);
int lineEnd = textLayout.getLineEnd(i);

float lineWidth = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, paint);
String line = text.substring(lineStart, lineEnd);

if (line.charAt(line.length() - 1) == ' ') {
line = line.substring(0, line.length() - 1);
}

if (justify && i < textLayout.getLineCount() - 1) {
drawLineJustified(canvas, line, lineWidth);
} else {
canvas.drawText(line, 0, lineY, paint);
}

lineY += textHeight;
}

}

private void drawLineJustified(Canvas canvas, String line, float lineWidth) {
TextPaint paint = getPaint();

float emptySpace = textAreaWidth - lineWidth;
int spaces = line.split(" ").length - 1;
float newSpaceSize = (emptySpace / spaces) + spaceCharSize;

float charX = 0;

for (int i = 0; i < line.length(); i++) {
String character = String.valueOf(line.charAt(i));
float charWidth = StaticLayout.getDesiredWidth(character, paint);
if (!character.equals(" ")) {
canvas.drawText(character, charX, lineY, paint);
}

if (character.equals(" ") && i != line.length() - 1)
charX += newSpaceSize;
else
charX += charWidth;
}

}
}

和 XML:

<il.co.drapp.views.text.DTextView
android:layout_width="match_parent"
android:inputType="textMultiLine|textNoSuggestions"
app:justify="true"
android:id="@+id/justifyText"
android:text="@string/article_dummy_text"
android:layout_height="wrap_content" />

感谢 Aditya Vyas-Lakhan 提供的链接

关于android - 在 Android 的 TextView 中对齐文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44368339/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com