当前位置: 首页 > 面试题库 >

在Android中对齐文本

邵骏喆
2023-03-14
问题内容

我需要说明一些文本(RTL),这是S1来自服务器的字符串()。但是a TextView不能证明文本的正确性,因此我必须使用a
WebView,现在必须创建一个HTML文件,其中将显示S1。然后,我将该html文件的地址存储在数据库中,然后显示该html文件。我曾经在SO上看到过这个问题,并且很多人建议使用3rd
party库,但我尝试了所有这些方法,但都无济于事(它们在90%的场景中都有效,但并不完全可靠)。

我觉得这种方法似乎很复杂,我想知道是否有更好的方法?


问题答案:

我使用以下代码来回答非常需要此主题的人们,并创建在每个显示中都支持的公式。

    public class TextJustify {

final static String SYSTEM_NEWLINE = "\n";
final static float COMPLEXITY = 5.12f; // Reducing this will increase
                                        // efficiency but will decrease
                                        // effectiveness
final static Paint p = new Paint();

/* @author Mathew Kurian */

public static void run(final TextView tv, float origWidth, int paddingLeft, int paddingRight, int marginLeft, int marginRight) {


    origWidth-= paddingRight+marginRight+paddingLeft+marginLeft;
    String s = tv.getText().toString();
    p.setTypeface(tv.getTypeface());
    String[] splits = s.split(SYSTEM_NEWLINE);
    float width = origWidth - 5;
    for (int x = 0; x < splits.length; x++)
        if (p.measureText(splits[x]) > width) {
            splits[x] = wrap(splits[x], width, p);
            String[] microSplits = splits[x].split(SYSTEM_NEWLINE);
            for (int y = 0; y < microSplits.length - 1; y++)
                microSplits[y] = justify(removeLast(microSplits[y], " "),
                        width, p);
            StringBuilder smb_internal = new StringBuilder();
            for (int z = 0; z < microSplits.length; z++)
                smb_internal.append(microSplits[z]
                        + ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
                                : ""));
            splits[x] = smb_internal.toString();
        }
    final StringBuilder smb = new StringBuilder();
    for (String cleaned : splits)
        smb.append(cleaned + SYSTEM_NEWLINE);
    tv.setGravity(Gravity.RIGHT);
    tv.setText(smb);
}

private static String wrap(String s, float width, Paint p) {
    String[] str = s.split("\\s"); // regex
    StringBuilder smb = new StringBuilder(); // save memory
    smb.append(SYSTEM_NEWLINE);
    for (int x = 0; x < str.length; x++) {
        float length = p.measureText(str[x]);
        String[] pieces = smb.toString().split(SYSTEM_NEWLINE);
        try {
            if (p.measureText(pieces[pieces.length - 1]) + length > width)
                smb.append(SYSTEM_NEWLINE);
        } catch (Exception e) {
        }
        smb.append(str[x] + " ");
    }
    return smb.toString().replaceFirst(SYSTEM_NEWLINE, "");
}

private static String removeLast(String s, String g) {
    if (s.contains(g)) {
        int index = s.lastIndexOf(g);
        int indexEnd = index + g.length();
        if (index == 0)
            return s.substring(1);
        else if (index == s.length() - 1)
            return s.substring(0, index);
        else
            return s.substring(0, index) + s.substring(indexEnd);
    }
    return s;
}

private static String justifyOperation(String s, float width, Paint p) {
    float holder = (float) (COMPLEXITY * Math.random());
    while (s.contains(Float.toString(holder)))
        holder = (float) (COMPLEXITY * Math.random());
    String holder_string = Float.toString(holder);
    float lessThan = width;
    int timeOut = 100;
    int current = 0;
    while (p.measureText(s) < lessThan && current < timeOut) {
        s = s.replaceFirst(" ([^" + holder_string + "])", " "
                + holder_string + "$1");
        lessThan = p.measureText(holder_string) + lessThan
                - p.measureText(" ");
        current++;
    }
    String cleaned = s.replaceAll(holder_string, " ");
    return cleaned;
}

private static String justify(String s, float width, Paint p) {
    while (p.measureText(s) < width) {
        s = justifyOperation(s, width, p);
    }
    return s;
}
  }

为了调用此代码,您必须使用以下代码,我测试了波斯语语言,并且在每种显示和设备上都运行良好。

     public static final int FinallwidthDp  = 320 ;
     public static final int widthJustify  = 223 ;

     DisplayMetrics metrics = new DisplayMetrics();
     getWindowManager().getDefaultDisplay().getMetrics(metrics);
     int widthPixels = metrics.widthPixels;

     float scaleFactor = metrics.density;
     float widthDp = widthPixels / scaleFactor;

     TextView tv = (TextView) findViewById(R.id.textView1);
     ViewGroup.MarginLayoutParams lp1 = (ViewGroup.MarginLayoutParams) tv.getLayoutParams();

     tv.setText(text);
     TextJustify.run(tv,widthDp / FinallwidthDp * widthJustify , tv.getPaddingLeft(),tv.getPaddingRight() , lp1.leftMargin, lp1.rightMargin);

此算法已在各种设备上进行了测试,并且在正常活动(非对话框)和的wrap- content宽度上都可以正常TextView工作,并且可以处理所有的填充和边距。如果对您不利,您可以进行更改,widthJustify直到对您有利为止,希望这一点有用。对于新更新看到这



 类似资料:
  • 问题内容: 我在一个Android应用程序中有一个列表视图,该列表视图用于显示包含字符串的ArrayList,并且找不到ListView的任何属性,这些属性使我无法将ListView Items的文本对齐到它的右边而不是左边。任何帮助将是巨大的,谢谢。 问题答案: 答案取决于您如何精确地建立列表。如果使用标准,则可以使用构造函数: 这样的xml布局在哪里:

  • 我试图设计我的片段,我想创建的文本将正好在按钮上方和中心。现在,我只创建了一个2个rowtables。但我仍然没有成功地把它对准我想要的。 这是XML: 这是我得到的:

  • 问题内容: 下面的代码(也可以在JSFiddle上作为演示使用没有将文本放在中间,正如我理想中的那样。即使使用属性,我也找不到任何方法可以使文本垂直居中。我怎样才能做到这一点? 问题答案: 创建一个用于文本内容的容器,也许是。 JSFiddle

  • 我有一个“p”标记,它是内联的(我不想显示它块),但当我使用时,它不起作用。 HTML: CSS:

  • 问题内容: 对于所有默认输入,您要填充的文本从左侧开始。您如何使它从右边开始? 问题答案: 在CSS中使用text-align属性: 这将在页面的所有输入中生效。 否则,如果只想对齐一个输入的文本,请设置内联样式:

  • 问题内容: 我的页面中有一个表格,我使用colgroups以相同的方式设置此列中的所有单元格的格式,对背景颜色和所有颜色均适用。但似乎无法弄清为什么文本对齐中心不起作用。它不会使文本居中对齐。 例: CSS: 问题答案: 只有有限的CSS属性集适用于column,而不是其中之一。 有关这种情况的说明,请参见“为什么只有四个属性应用于表列的奥秘”。 在您的简单示例中,最简单的解决方法是添加以下规则: