font-size 文字幅 収まる - TextView for Androidの自動フィット




7 Answers

私は、M-WaJeEhの答えを少し変えて、複合型のドロアブルを考慮に入れました。

getCompoundPaddingXXXX()メソッドpadding of the view + drawable space返しpadding of the view + drawable space 。 たとえば、 TextView.getCompoundPaddingLeft()参照してください。

問題:これは、テキストで使用可能なTextViewスペースの幅と高さの測定値を修正します。 描画可能なサイズを考慮しない場合は無視され、描画可能な部分とテキストが重なってしまいます。

更新されたセグメントadjustTextSize(String)

private void adjustTextSize(final String text) {
  if (!mInitialized) {
    return;
  }
  int heightLimit = getMeasuredHeight() - getCompoundPaddingBottom() - getCompoundPaddingTop();
  mWidthLimit = getMeasuredWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();

  mAvailableSpaceRect.right = mWidthLimit;
  mAvailableSpaceRect.bottom = heightLimit;

  int maxTextSplits = text.split(" ").length;
  AutoResizeTextView.super.setMaxLines(Math.min(maxTextSplits, mMaxLines));

  super.setTextSize(
      TypedValue.COMPLEX_UNIT_PX,
      binarySearch((int) mMinTextSize, (int) mMaxTextSize,
                   mSizeTester, mAvailableSpaceRect));
}
サイズ 動的 見切れる

バックグラウンド

TextViewのフォントを与えられた境界に自動的にフィットさせる必要があることがよくあります。

問題

残念ながら、この問題( hereherehere例)について多くのスレッドと投稿(そして示唆された解決策)があるにもかかわらず、実際にはうまく機能しません。

だからこそ、私は本当のことを見つけるまで、それぞれをテストすることに決めました。

私はそのようなtextViewからの要件は次のようにするべきだと思います:

  1. 任意のフォント、書体、スタイル、および文字セットを使用できるようにする必要があります。

  2. 幅と高さの両方を処理する必要があります

  3. 制限のためにテキストが収まりきらない限り、切捨ては行われません(例:テキストが長すぎる、利用可能なサイズが小さすぎます)。 ただし、希望の場合は、水平/垂直スクロールバーを要求することができます。

  4. 複数行または単一行を許可する必要があります。 複数行の場合、最大行と最小行を許可します。

  5. 計算が遅くてはいけません。 最適なサイズを見つけるためにループを使用していますか? 少なくともそれを最適化し、毎回サンプリングを1ずつ増加させないでください。

  6. 複数行の場合は、サイズ変更やより多くの行を使用することができます。また、 "\ n"文字を使用して行を自分自身で選択することもできます。

私が試したこと

私は非常に多くのサンプル(リンクのものを含めて、私が書いた)を試してきました。私も話しましたが、本当にうまくいきませんでした。

TextViewが自動的に正しくフィットするかどうかを視覚的に確認できるサンプルプロジェクトを作成しました。

現在のところ、私のサンプルプロジェクトでは、テキスト(英語のアルファベットと数字)とtextViewのサイズをランダム化して1行にとどめていますが、試したサンプルでもうまくいきません。

コードは次のとおりです( hereでも利用可能here ):

ファイル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>

ファイル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();
    }
  }

質問

誰かが実際に働くこの共通の問題に対する解決策を知っていますか?

私が書いたような機能がはるかに少ないソリューションでも、テキストの行数が一定で、フォントのサイズに合わせてフォントを調整するなど、奇妙な不具合はなく、テキストも手に入れることができます利用可能なスペースに比べて大/小。

GitHubプロジェクト

これは重要なTextViewなので、私はライブラリを公開することで、誰もが簡単に使用して貢献できるようにしhere




私の要件は

  • ScalableTextViewをクリックします。
  • listActivityを開き、さまざまな長さの文字列アイテムを表示します。
  • リストからテキストを選択します。
  • テキストを別のアクティビティのScalableTextViewに戻します。

私はリンクを参照しました: TextView TextをTextテキストの自動スケール )の枠内に収める (コメントを含む)とDialogTitle.java

私は、提供されたソリューションが素敵でシンプルだが、テキストボックスのサイズを動的に変更しないことがわかった。 これは、リストビューから選択したテキストの長さが ScalableTextView 既存のテキストの長さよりも大きい場合に効果的ですScalableTextView内の既存のテキストよりも小さい長さのテキストを選択すると、テキストのサイズが増えず、小さいサイズのテキストが表示されます。

ScalableTextView.javaを修正して、テキストの長さに基づいてテキストサイズを再調整しました。 ここに私のScalableTextView.java

public class ScalableTextView extends TextView
{
float defaultTextSize = 0.0f;

public ScalableTextView(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
    setSingleLine();
    setEllipsize(TruncateAt.END);
    defaultTextSize = getTextSize();
}

public ScalableTextView(Context context, AttributeSet attrs)
{
    super(context, attrs);
    setSingleLine();
    setEllipsize(TruncateAt.END);
    defaultTextSize = getTextSize();
}

public ScalableTextView(Context context)
{
    super(context);
    setSingleLine();
    setEllipsize(TruncateAt.END);
    defaultTextSize = getTextSize();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
    setTextSize(TypedValue.COMPLEX_UNIT_PX, defaultTextSize);
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    final Layout layout = getLayout();
    if (layout != null)
    {
        final int lineCount = layout.getLineCount();
        if (lineCount > 0)
        {
            int ellipsisCount = layout.getEllipsisCount(lineCount - 1);
            while (ellipsisCount > 0)
            {
                final float textSize = getTextSize();

                // textSize is already expressed in pixels
                setTextSize(TypedValue.COMPLEX_UNIT_PX, (textSize - 1));

                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                ellipsisCount = layout.getEllipsisCount(lineCount - 1);
            }
        }
    }
}
}

ハッピーコーディング....




この問題に対する正式な解決策があります。 Android Oで導入されたTextViewの自動サイズ設定は、Support Library 26で利用可能で、Android 4.0まで下位互換性があります。

https://developer.android.com/preview/features/autosizing-textview.html

私もこの情報を含むhttps://.com/a/42940171/47680が管理者によって削除された理由はhttps://.com/a/42940171/47680ません。




テキストビューを画像に変換し、境界内の画像を拡大/縮小します。

ビューをイメージに変換する方法の例を以下に示します: ビューをビットマップに変換し、Androidに表示せずに

問題は、あなたのテキストを選択することはできませんが、そのトリックを行う必要があります。 私はそれを試していないので、(スケーリングのために)どのように見えるか分からない。




これを試して

TextWatcher changeText = new TextWatcher() {
     @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                tv3.setText(et.getText().toString());
                tv3.post(new Runnable() {           
                    @Override
                    public void run() {
                    while(tv3.getLineCount() >= 3){                     
                            tv3.setTextSize((tv3.getTextSize())-1);                     
                        }
                    }
                });
            }

            @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override public void afterTextChanged(Editable s) { }
        };



@Malachiaszによって記述された問題のクイックフィックス

私はこの問題を、自動サイズ変更クラスでカスタムサポートを追加して修正しました:

public void setTextCompat(final CharSequence text) {
    setTextCompat(text, BufferType.NORMAL);
}

public void setTextCompat(final CharSequence text, BufferType type) {
    // Quick fix for Android Honeycomb and Ice Cream Sandwich which sets the text only on the first call
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 &&
        Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
        super.setText(DOUBLE_BYTE_WORDJOINER + text + DOUBLE_BYTE_WORDJOINER, type);
    } else {
        super.setText(text, type);
    }
}

@Override
public CharSequence getText() {
    String originalText = super.getText().toString();
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1 &&
        Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
        // We try to remove the word joiners we added using compat method - if none found - this will do nothing.
        return originalText.replaceAll(DOUBLE_BYTE_WORDJOINER, "");
    } else {
        return originalText;
    }
}

yourView.setTextCompat(newTextValue)代わりに電話するyourView.setText(newTextValue)




Android O以降、xmlのテキストのサイズを自動的に変更することができます:

https://developer.android.com/preview/features/autosizing-textview.html

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:autoSizeTextType="uniform"
    app:autoSizeMinTextSize="12sp"
    app:autoSizeMaxTextSize="100sp"
    app:autoSizeStepGranularity="2sp"
  />

Android Oを使用すると、TextViewの特性や境界に基づいて自動的にテキストのサイズを拡大または縮小してレイアウトに合わせるようTextViewに指示できます。この設定により、ダイナミックコンテンツを使用してさまざまな画面でテキストサイズを最適化することが容易になります。

Support Library 26.0 Betaは、Android Oより前のAndroidバージョンを実行しているデバイスのTextView機能の自動サイズ調整を完全にサポートしています。このライブラリはAndroid 4.0(APIレベル14)以上のサポートを提供します。android.support.v4.widgetパッケージには、後方互換性のある機能にアクセスするためのTextViewCompatクラスが含まれています。




Related