自動適應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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章