web-dev-qa-db-ja.com

Android TextView 1行あたりの文字数を見つける方法は?

だから私はAndroidに、画面の全長の幅とディップ5のパディングを持つTextViewを持っています。どのようにして1行に収まる文字数を計算できますか?画面?言い換えれば、テキストビューの列数を取得しようとしていますか?

テキストのサイズと幅に応じて手動計算を検討しましたが、1)相関関係がわからない、2)伏角単位のパディングのため、画面が異なれば実際のピクセル数も異なります。

全体的な質問:私はこれを使用して解決しようとしています:文字列が与えられた場合、テキストビューが文字列を文字ごとに印刷するときに、1つに収まらない単語をいつ開始するかがわかるように手動で文字列を編集するにはどうすればよいですか?次の行。注:textviewは、次の行に収まらない単語を自動的に配置することを知っていますが、アニメーションの入力のように1文字ずつ印刷しているため、textviewは、Wordが収まらないことを認識しません。その言葉のあふれている文字。

これをどこでも探しています...

ありがとう!

追加された解決策:

1つの可能な解決策:

public String measure2 (TextView t, String s) {
    String u = "";
    int start = 0;
    int end = 1;
    int space = 0;
    boolean ellipsized = false;
    float fwidth = t.getMeasuredWidth();
    for(;;) {
        //t.setText(s.substring(start, end));
        float twidth = t.getPaint().measureText(s.substring(start, end));
        if (twidth < fwidth){
            if (end < s.length())
                end++;
            else {
                if (!ellipsized)
                    return s;
                return u + s.subSequence(start, end);
            }
        }
        else {
            ellipsized = true;
            space = (u + s.substring(start, end)).lastIndexOf(" ");
            if (space == -1)
                space = end - 1;
            u += s.subSequence(start, space) + "\n";
            start = space + 1;
            end = start + 1;
        }
    }
}

ソリューション2ですが、それでもソリューション1を使用することがあります。

public String measure3 (TextView t, String s) {
    List<String> wlist = Arrays.asList(s.split(" "));
    if (wlist.size() == 1)
        return measure2(t, s);
    String u = "";
    int end = 1;
    float fwidth = t.getMeasuredWidth();
    for(;;) {
        //t.setText(s.substring(start, end));
        if (wlist.isEmpty())
            return u;
        String temp = listStr(wlist, end);
        float twidth = t.getPaint().measureText(temp);
        if (twidth < fwidth){
            if (end < wlist.size())
                end++;
            else {
                return u + temp;
            }
        }
        else {
            temp = listStr(wlist, end-1);
            if (end == 1)
                temp = measure2(t, temp);
            if (wlist.isEmpty())
                return u + temp;
            else
                u = u + temp + "\n";
            wlist = wlist.subList(end - 1, wlist.size());
            end = 1;
        }
    }
}

public String listStr (List<String> arr, int end) {
    String s = "";
    for (String e : arr.subList(0, end) ){
        s = s + e + " ";
    }
    return s.trim();
}

上記のコードを使用して、元の文字列s、つまり出力される文字列uを生成しました。ただし、このアプローチは非常に非効率的だと思います。別のアプローチまたはより良いアルゴリズムはありますか?注:私が修正したmeasure3にはいくつかのエラーがありますが、編集するのが面倒でした

20
Derek

これを試して:

_private boolean isTooLarge (TextView text, String newText) {
    float textWidth = text.getPaint().measureText(newText);
    return (textWidth >= text.getMeasuredWidth ());
}
_

文字の幅が可変であるため、何文字が収まるかを検出することは不可能です。上記の関数は、特定の文字列がTextViewに収まるかどうかをテストします。 newTextのコンテンツは、特定の行のすべての文字である必要があります。 trueの場合、新しい行を開始します(そして、新しい文字列を使用してパラメーターとして渡します)。


コメントへの回答:

  1. アプリは多くのシステムで実行できるため、正確に理由測定する必要があります。
  2. これはあなたの「全体的な質問」を解決する方法です。 str.size()>numColを使用する場合と大きすぎる場合の違いは何ですか?アニメーションを実装する必要があります(ヒント#1:改行文字を挿入します)
  3. 前に言ったように、新しい行を開始するときは、新しい文字列を開始します(ヒント#2:TextViewを拡張すると、setTextをオーバーライドすることでこれらすべてを実装できます)。 (ヒント#3:_static int lines;_で作成された行を追跡し、newString.split("\\r?\\n")[lines-1]を使用して長さを確認します)。
28
Aleadam

以下のコードでTextviewの全行と各文字の文字列を取得できます。その後、各行にスタイルを設定できます。

最初の行を太字にしました。

private void setLayoutListner( final TextView textView ) {
        textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                final Layout layout = textView.getLayout();

                // Loop over all the lines and do whatever you need with
                // the width of the line
                for (int i = 0; i < layout.getLineCount(); i++) {
                    int end = layout.getLineEnd(0);
                    SpannableString content = new SpannableString( textView.getText().toString() );
                    content.setSpan(new StyleSpan(Android.graphics.Typeface.BOLD), 0, end, 0);
                    content.setSpan(new StyleSpan(Android.graphics.Typeface.NORMAL), end, content.length(), 0);
                    textView.setText( content );
                }
            }
        });
    }

この方法を試してください。この方法で複数のスタイルを適用できます。

1
kinjal patel

同じ問題が発生し、2つのステップで1行あたりの文字数を計算しました。ステップ1:行数を計算する

 val widthOfTvComment = widthOfScreen - marginLeft - marginRight
 var bounds  = Rect()
 var Paint = Paint()
 Paint.textSize = textSize
 Paint.getTextBounds(comment,0,comment.length,bounds)

val lines = ( bounds.width()/widthOfTvComment)

ステップ2:1行あたりの文字数を計算しました

val charactersPerLine = comment.length / lines
1
NhatVM