8

私の Android レイアウトには、画面の使用可能な幅の半分を使用する TextView があります。実行時に、テキストを (長い) 電子メール アドレスに設定します。例えば:

googleandroiddeveloper@gmail.com

テキストが 1 行に収まらない場合、Android は改行を挿入しますが、これは望ましい動作です。ただし、改行位置は、行に収まらない最初の文字の前です。結果は次のようになります。

googleandroiddeveloper@gmai
l.com

これは、特に電子メールアドレスでは、ちょっと見苦しいと思います。文字の直前に改行を表示したい@:

googleandroiddeveloper
@gmail.com

もちろん、 に を追加することもでき\nますstrings.xml。しかし、電子メール アドレスは、1 行に収まる場合でも、常に 2 行を使用します。

\u200BメールアドレスにZERO WIDTH SPACE ( ) を追加することで解決策を見つけたとすでに思っていました。

<string name="email">googleandroiddeveloper\u200B@gmail.com</string>

ただし、標準のスペース以外では、Android は特殊なスペース文字を改行可能なスペースとして検出しないため、この時点で改行を追加しません。

アプリケーションの複数の場所で多くの電子メール アドレスを扱っているため、文字の前に壊れやすく目に見えないスペースを追加するソリューションを探しています@。そのため、Android は、1 行に収まらない場合に電子メール アドレスをラップします。

4

2 に答える 2

6

@Luksprogのソリューションは非常に優れており、多くの場合問題を解決します。ただし、クラスをさらに改善するために、いくつかの点でクラスを変更しました。これらは変更です:

  • with を使用すると問題が発生するため、テキストの確認と操作のonSizeChanged代わりに使用しました。onMeasureonMeasureLinearLayoutlayout_weight
  • getPaddingLeft()と を使用して、テキストの横方向のパディングを考慮しましたgetPaddingRight()
  • 測定afterAt時に I を に置き換えpositionましたposition + 1。それ以外の場合、結果の電子メール アドレスには 2 つの が含まれます@

コード:

public class EmailTextView extends TextView {

    public EmailTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        // the width the text can use, that is the total width of the view minus
        // the padding
        int availableWidth = w - getPaddingLeft() - getPaddingRight();
        String text = getText().toString();
        if (text.contains("\n@")) {
            // the text already contains a line break before @
            return;
        }
        // get the position of @ in the string
        int position = -1;
        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == '@') {
                position = i;
                break;
            }
        }
        if (position > 0) {
            final Paint pnt = getPaint();
            // measure width before the @ and after the @
            String beforeAt = text.subSequence(0, position).toString();
            String afterAt = text.subSequence(position + 1, text.length())
                    .toString();
            final float beforeAtSize = pnt.measureText(beforeAt);
            final float afterAtSize = pnt.measureText(afterAt);
            final float atSize = pnt.measureText("@");
            if (beforeAtSize > availableWidth) {
                // the text before the @ is bigger than the width
                // so Android will break it
                return;
            } else {
                if ((beforeAtSize + afterAtSize + atSize) <= availableWidth) {
                // the entire text is smaller than the available width
                    return;
                } else {
                    // insert the line break before the @
                    setText(beforeAt + "\n@" + afterAt);
                }
            }
        }
    }
}

EmailTextViewデフォルトと比較したスクリーンショットを次に示しますTextView

メールテキストビュー

すべてのメールアドレスで、期待どおりに機能します。の前のテキスト@がすでに広すぎるため、最後のアドレスは変更されません。そのため、システムは前にそれを分割し、それによって電子メール アドレスが混乱するため、別の改行を含める必要はありません。

于 2012-12-12T14:51:07.027 に答える
2

以下のカスタムTextViewクラスを見ることができます (ただし、おそらくあまり効率的ではありません)。

public static class NewLineText extends TextView {

    private static final String CHALLANGE_TEXT = "\n@";

    public NewLineText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        String text = getText().toString();
        if (text.contains(CHALLANGE_TEXT)) {
            return;
        }
        int position = -1;
        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == '@') {
                position = i;
                break;
            }
        }
        if (position > 0) {
            final Paint pnt = getPaint();
            String beforeAt = text.subSequence(0, position).toString();
            String afterAt = text.subSequence(position, text.length())
                    .toString();
            final float beforeAtSize = pnt.measureText(beforeAt);
            final float afterAtSize = pnt.measureText(afterAt);
            final float atSize = pnt.measureText("@");
            if (beforeAtSize > getMeasuredWidth()) {
                // return ?! the text before the @ is bigger than the width
                // so Android will break it
                return;
            } else {
                if ((beforeAtSize + afterAtSize + atSize) <= getMeasuredWidth()) {
                    return;
                } else {
                    setText(beforeAt + CHALLANGE_TEXT + afterAt);
                }
            }
        }
    }
}
于 2012-12-05T19:56:35.403 に答える