自动适应TextView for Android - Auto-fit TextView for Android

问题:

Background 背景

Many times we need to auto-fit the font of the TextView to the boundaries given to it. 很多时候,我们需要将TextView的字体自动调整到给定的边界。

The problem 问题

Sadly, even though there are many threads and posts (and suggested solutions) talking about this problem (example here , here and here ), none of them actually work well. 可悲的是,即使有很多线程和帖子(和建议的解决方案)谈论这个问题(例如这里这里这里的例子),它们都没有真正运作良好。

That's why, I've decided to test each of them till I find the real deal. 这就是为什么,我决定测试每一个,直到找到真正的交易。

I think that the requirements from such a textView should be: 我认为来自这样一个textView的要求应该是:

  1. Should allow using any font, typeface, style, and set of characters. 应允许使用任何字体,字体,样式和字符集。

  2. Should handle both width and height 应该处理宽度和高度

  3. No truncation unless text cannot fit because of the limitation, we've given to it (example: too long text, too small available size). 没有截断,除非文本由于限制而无法适应,我们已经给它(例如:文本太长,可用大小太小)。 However, we could request for horizontal/vertical scrollbar if we wish, just for those cases. 但是,如果我们愿意,我们可以请求水平/垂直滚动条,仅适用于那些情况。

  4. Should allow multi-line or single-line. 应该允许多线或单线。 In case of multi-line, allow max & min lines. 如果是多行,请允许最大和最小行。

  5. Should not be slow in computation. 计算速度不应该慢。 Using a loop for finding the best size? 使用循环找到最佳尺寸? At least optimize it and don't increment your sampling by 1 each time. 至少要优化它,不要每次增加1个采样。

  6. In case of multi-line, should allow to prefer resizing or using more lines, and/or allow to choose the lines ourselves by using the "\\n" character. 在多行的情况下,应该允许更喜欢调整大小或使用更多行,和/或允许使用“\\ n”字符自己选择行。

What I've tried 我试过的

I've tried so many samples (including those of the links, I've written about), and I've also tried to modify them to handle the cases, I've talked about, but none really work. 我已经尝试了很多样本​​(包括链接的那些,我已经写过了),而且我也尝试修改它们来处理这些情况,我已经谈过了,但没有一个真正起作用。

I've made a sample project that allows me to visually see if the TextView auto-fits correctly. 我做了一个示例项目,让我可以直观地看到TextView是否正确自动匹配。

Currently, my sample project only randomize the text (the English alphabet plus digits) and the size of the textView, and let it stay with single line, but even this doesn't work well on any of the samples I've tried. 目前,我的示例项目只是随机化文本(英文字母加上数字)和textView的大小,并让它保持单行,但即使这样也不适用于我尝试的任何样本。

Here's the code (also available here ): 这是代码(也可在此处获得 ):

File res/layout/activity_main.xml 文件res/layout/activity_main.xml

<RelativeLayout 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" tools:context=".MainActivity">
  <Button android:id="@+id/button1" android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true" android:text="Button" />
  <FrameLayout android:layout_width="match_parent"
    android:layout_height="wrap_content" android:layout_above="@+id/button1"
    android:layout_alignParentLeft="true" android:background="#ffff0000"
    android:layout_alignParentRight="true" android:id="@+id/container"
    android:layout_alignParentTop="true" />

</RelativeLayout>

File src/.../MainActivity.java 文件src/.../MainActivity.java

public class MainActivity extends Activity
  {
  private final Random        _random            =new Random();
  private static final String ALLOWED_CHARACTERS ="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";

  @Override
  protected void onCreate(final Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ViewGroup container=(ViewGroup)findViewById(R.id.container);
    findViewById(R.id.button1).setOnClickListener(new OnClickListener()
      {
        @Override
        public void onClick(final View v)
          {
          container.removeAllViews();
          final int maxWidth=container.getWidth();
          final int maxHeight=container.getHeight();
          final FontFitTextView fontFitTextView=new FontFitTextView(MainActivity.this);
          final int width=_random.nextInt(maxWidth)+1;
          final int height=_random.nextInt(maxHeight)+1;
          fontFitTextView.setLayoutParams(new LayoutParams(width,height));
          fontFitTextView.setSingleLine();
          fontFitTextView.setBackgroundColor(0xff00ff00);
          final String text=getRandomText();
          fontFitTextView.setText(text);
          container.addView(fontFitTextView);
          Log.d("DEBUG","width:"+width+" height:"+height+" text:"+text);
          }
      });
    }

  private String getRandomText()
    {
    final int textLength=_random.nextInt(20)+1;
    final StringBuilder builder=new StringBuilder();
    for(int i=0;i<textLength;++i)
      builder.append(ALLOWED_CHARACTERS.charAt(_random.nextInt(ALLOWED_CHARACTERS.length())));
    return builder.toString();
    }
  }

The question 这个问题

Does anybody know of a solution for this common problem that actually work? 有人知道这个常见问题的解决方案吗?

Even a solution that has much less features that what I've written about, for example one that has just a constant number of lines of text, and adjusts its font according to its size, yet never have weird glitches and having the text get too large/small compared to its available space. 即使是一个解决方案,其功能要少得多,我所写的内容,例如一个只有一定数量的文本行,并根据其大小调整其字体,但从来没有奇怪的故障,并且文本也得到了解决方案与可用空间相比大/小。


GitHub project GitHub项目

Since this is such an important TextView, I've decided to publish a library, so that everyone could easily use it, and contribute to it, here . 由于这是一个非常重要的TextView,我决定发布一个图书馆,让每个人都可以轻松地使用它,并作出贡献, 在这里


解决方案:

参考一: https://en.stackoom.com/question/15CnN
参考二: https://stackoom.com/question/15CnN
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章