77

画像の周りにテキストを配置する方法があれば教えてください。このような:

------  text text text
|    |  text text text
-----   text text text
text text text text
text text text text

この質問について、Android 開発者から回答がありました。しかし、自分のバージョンのTextViewを実行することで、彼が何を意味するのかわかりませんか? ヒントをありがとう。

2010 年 2 月 8 日月曜日の午後 11 時 5 分に、Romain Guy は次のように書いています。

やあ、

これは、提供されたウィジェットとレイアウトだけを使用して行うことはできません。これを行うには独自のバージョンの TextView を作成できますが、難しいことではありません。

4

9 に答える 9

68

android.text.style.LeadingMarginSpan.LeadingMarginSpan2現在は可能ですが、API 8 で利用可能なインターフェイスを使用して、バージョン 2.2 以上の携帯電話でのみ可能です。

英語ではありませんが、ここから直接ソース コードをダウンロードできます

アプリケーションを古いデバイスと互換性を持たせたい場合は、フローティング テキストなしで別のレイアウトを表示できます。次に例を示します。

レイアウト (古いバージョンのデフォルト。新しいバージョンではプログラムによって変更されます)

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView 
            android:id="@+id/thumbnail_view"
            android:src="@drawable/icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    <TextView android:id="@+id/message_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/thumbnail_view"
            android:textSize="18sp"
            android:text="@string/text" />
</RelativeLayout>

ヘルパー クラス

class FlowTextHelper {

    private static boolean mNewClassAvailable;

    static {
        if (Integer.parseInt(Build.VERSION.SDK) >= 8) { // Froyo 2.2, API level 8
           mNewClassAvailable = true;
        }
    }

    public static void tryFlowText(String text, View thumbnailView, TextView messageView, Display display){
        // There is nothing I can do for older versions, so just return
        if(!mNewClassAvailable) return;

        // Get height and width of the image and height of the text line
        thumbnailView.measure(display.getWidth(), display.getHeight());
        int height = thumbnailView.getMeasuredHeight();
        int width = thumbnailView.getMeasuredWidth();
        float textLineHeight = messageView.getPaint().getTextSize();

        // Set the span according to the number of lines and width of the image
        int lines = (int)FloatMath.ceil(height / textLineHeight);
        //For an html text you can use this line: SpannableStringBuilder ss = (SpannableStringBuilder)Html.fromHtml(text);
        SpannableString ss = new SpannableString(text);
        ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        messageView.setText(ss);

        // Align the text with the image by removing the rule that the text is to the right of the image
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)messageView.getLayoutParams();
        int[]rules = params.getRules();
        rules[RelativeLayout.RIGHT_OF] = 0;
    }
}

MyLeadingMarginSpan2 クラス (API 21 をサポートするように更新)

public class MyLeadingMarginSpan2 implements LeadingMarginSpan2 {
    private int margin;
    private int lines;
    private boolean wasDrawCalled = false;
    private int drawLineCount = 0;

    public MyLeadingMarginSpan2(int lines, int margin) {
        this.margin = margin;
        this.lines = lines;
    }

    @Override
    public int getLeadingMargin(boolean first) {
        boolean isFirstMargin = first;
        // a different algorithm for api 21+
        if (Build.VERSION.SDK_INT >= 21) {
            this.drawLineCount = this.wasDrawCalled ? this.drawLineCount + 1 : 0;
            this.wasDrawCalled = false;
            isFirstMargin = this.drawLineCount <= this.lines;
        }

        return isFirstMargin ? this.margin : 0;
    }

    @Override
    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
        this.wasDrawCalled = true;
    }

    @Override
    public int getLeadingMarginLineCount() {
        return this.lines;
    }
}

使用例

ImageView thumbnailView = (ImageView) findViewById(R.id.thumbnail_view);
TextView messageView = (TextView) findViewById(R.id.message_view);
String text = getString(R.string.text);

Display display = getWindowManager().getDefaultDisplay();
FlowTextHelper.tryFlowText(text, thumbnailView, messageView, display);

これは、アプリケーションが Android 2.2 デバイスでどのように見えるかです。 Android 2.2 テキストが画像の周りを流れる

これは Android 2.1 デバイス用です。

Android 2.1 テキストは画像の近くにあります

于 2011-12-11T10:09:40.697 に答える
7

これはFlowTextHelperの改善です(vorrtexの返信から)。テキストと画像の間に追加のパディングを追加する可能性を追加し、パディングも考慮に入れるように行計算を改善しました。楽しみ!

public class FlowTextHelper {
   private static boolean mNewClassAvailable;

   /* class initialization fails when this throws an exception */
   static {
       try {
           Class.forName("android.text.style.LeadingMarginSpan$LeadingMarginSpan2");
           mNewClassAvailable = true;
       } catch (Exception ex) {
           mNewClassAvailable = false;
       }
   }

   public static void tryFlowText(String text, View thumbnailView, TextView messageView, Display display, int addPadding){
       // There is nothing I can do for older versions, so just return
       if(!mNewClassAvailable) return;



       // Get height and width of the image and height of the text line
        thumbnailView.measure(display.getWidth(), display.getHeight());
        int height = thumbnailView.getMeasuredHeight();
        int width = thumbnailView.getMeasuredWidth() + addPadding;
        messageView.measure(width, height); //to allow getTotalPaddingTop
        int padding = messageView.getTotalPaddingTop();
        float textLineHeight = messageView.getPaint().getTextSize();

        // Set the span according to the number of lines and width of the image
        int lines =  (int)Math.round((height - padding) / textLineHeight);
        SpannableString ss = new SpannableString(text);
        //For an html text you can use this line: SpannableStringBuilder ss = (SpannableStringBuilder)Html.fromHtml(text);
        ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), 0);
        messageView.setText(ss);

        // Align the text with the image by removing the rule that the text is to the right of the image
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)messageView.getLayoutParams();
        int[]rules = params.getRules();
        rules[RelativeLayout.RIGHT_OF] = 0;
   }


}
于 2012-04-19T08:33:22.077 に答える
4

Vorrtex と Ronen の答えは、1 つの詳細を除いて私にとってはうまくいっています。SpannableString にスパンを設定するときに変更したことがわかりました

ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), 0);

ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, lines, 0);

画像の後にスパンを止めました。すべての場合に必要ではないかもしれませんが、共有したいと思います。

于 2013-11-12T18:55:52.887 に答える
3

この質問は私の質問と同じようです Androidの画像の下のコンテンツで空のスペースを埋める方法

フローテキスト ライブラリを使用して解決策を見つけました。これまでに役立つ可能性のある最初の回答を見つけてください。

于 2012-11-28T04:58:54.223 に答える
1

「しかし、私自身のバージョンの TextView を実行することで、彼が何を意味するのかわかりませんか?」

彼は、クラス android.widget.TextView (または Canvas またはその他のレンダリング可能なサーフェス) を拡張し、その周りにテキストが流れる埋め込み画像を許可する独自のオーバーライド バージョンを実装できることを意味します。

これは、作成する方法によってはかなりの作業になる可能性があります。

于 2010-03-09T22:11:37.720 に答える
0

MyLeadingMarginSpan2 クラスのより快適なコンストラクターを提供できます

    MyLeadingMarginSpan2(Context cc,int textSize,int height,int width) {                
    int pixelsInLine=(int) (textSize*cc.getResources().getDisplayMetrics().scaledDensity);              
    if (pixelsInLine>0 && height>0) {
        this.lines=height/pixelsInLine;          
    } else  {
        this.lines=0;
    }
    this.margin=width; 
}
于 2014-10-14T09:53:18.667 に答える