it-swarm.com.de

Wie wird StaticLayout in Android verwendet?

Ich muss meine eigene TextView erstellen, damit ich StaticLayout gelernt habe, um Text auf einer Leinwand zu zeichnen. Dies ist der direkten Verwendung von Canvas.drawText() vorzuziehen, so die documentation . Die Dokumentation enthält jedoch keine Beispiele für die Vorgehensweise. Es gibt nur einen vagen Hinweis darauf, dass StaticLayout.Builder der neuere Weg ist, dies zu tun.

Ich habe ein Beispiel gefunden hier , aber es scheint etwas veraltet zu sein.

Ich habe schließlich gearbeitet, wie ich es mache, also füge ich meine Erklärung unten hinzu.

13
Suragch

StaticLayout ( ähnlich wie DynamicLayout und BoringLayout ) wird zum Layout und Zeichnen von Text auf einer Leinwand verwendet. Es wird häufig für die folgenden Aufgaben verwendet:

  • Messen, wie groß der mehrzeilige Text sein soll, nachdem er angelegt wurde.
  • Zeichnen von Text auf einem Bitmap-Bild.
  • Erstellen einer benutzerdefinierten Ansicht, die ihr eigenes Textlayout behandelt (im Gegensatz zur Erstellung einer zusammengesetzten Ansicht mit einem eingebetteten TextView). TextView selbst verwendet StaticLayoutintern

Textgröße messen

Einzelne Zeile

Wenn Sie nur eine einzelne Textzeile haben, können Sie diese mit Paint oder TextPaint messen. 

String text = "This is some text."

TextPaint myTextPaint = new TextPaint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
mTextPaint.setColor(0xFF000000);

float width = mTextPaint.measureText(text);
float height = -mTextPaint.ascent() + mTextPaint.descent();

Multiline

Wenn jedoch Zeilenumbrüche vorhanden sind und Sie die Höhe benötigen, ist es besser, StaticLayout zu verwenden. Sie geben die Breite an und dann können Sie die Höhe von StaticLayout erhalten. 

String text = "This is some text. This is some text. This is some text. This is some text. This is some text. This is some text.";

TextPaint myTextPaint = new TextPaint();
myTextPaint.setAntiAlias(true);
myTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
myTextPaint.setColor(0xFF000000);

int width = 200;
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
float spacingMultiplier = 1;
float spacingAddition = 0;
boolean includePadding = false;

StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, width, alignment, spacingMultiplier, spacingAddition, includePadding);

float height = myStaticLayout.getHeight(); 

Neue API

Wenn Sie das neuere StaticLayout.Builder (verfügbar von API 23) verwenden möchten, können Sie Ihr Layout folgendermaßen erhalten:

StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), myTextPaint, width);
StaticLayout myStaticLayout = builder.build();

Sie können Additionseinstellungen mit Punktnotation anheften:

StaticLayout.Builder builder = StaticLayout.Builder.obtain(text, 0, text.length(), myTextPaint, width)
        .setAlignment(Layout.Alignment.ALIGN_NORMAL)
        .setLineSpacing(spacingMultiplier, spacingAddition)
        .setIncludePad(includePadding)
        .setMaxLines(5);
StaticLayout myStaticLayout = builder.build();

Text auf ein Bild schreiben

Ich kann dies in der Zukunft noch erweitern, aber für jetzt sehen Sie diesen Beitrag für ein Beispiel einer Methode, die StaticLayout verwendet und eine Bitmap zurückgibt.

Erstellen einer benutzerdefinierten Textverarbeitungsansicht

Hier ist ein Beispiel einer benutzerdefinierten Ansicht mit StaticLayout. Es verhält sich wie ein einfaches TextView. Wenn der Text zu lang ist, um auf den Bildschirm zu passen, werden Zeilen automatisch umbrochen und die Höhe wird erhöht.

enter image description here

Code 

MyView.Java

public class MyView extends View {

    String mText = "This is some text.";
    TextPaint mTextPaint;
    StaticLayout mStaticLayout;

    // use this constructor if creating MyView programmatically
    public MyView(Context context) {
        super(context);
        initLabelView();
    }

    // this constructor is used when created from xml
    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initLabelView();
    }

    private void initLabelView() {
        mTextPaint = new TextPaint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
        mTextPaint.setColor(0xFF000000);

        // default to a single line of text
        int width = (int) mTextPaint.measureText(mText);
        mStaticLayout = new StaticLayout(mText, mTextPaint, (int) width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false);

        // New API alternate
        //
        // StaticLayout.Builder builder = StaticLayout.Builder.obtain(mText, 0, mText.length(), mTextPaint, width)
        //        .setAlignment(Layout.Alignment.ALIGN_NORMAL)
        //        .setLineSpacing(1, 0) // multiplier, add
        //        .setIncludePad(false);
        // mStaticLayout = builder.build();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Tell the parent layout how big this view would like to be
        // but still respect any requirements (measure specs) that are passed down.

        // determine the width
        int width;
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthRequirement = MeasureSpec.getSize(widthMeasureSpec);
        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthRequirement;
        } else {
            width = mStaticLayout.getWidth() + getPaddingLeft() + getPaddingRight();
            if (widthMode == MeasureSpec.AT_MOST) {
                if (width > widthRequirement) {
                    width = widthRequirement;
                    // too long for a single line so relayout as multiline
                    mStaticLayout = new StaticLayout(mText, mTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0, false);
                }
            }
        }

        // determine the height
        int height;
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightRequirement = MeasureSpec.getSize(heightMeasureSpec);
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightRequirement;
        } else {
            height = mStaticLayout.getHeight() + getPaddingTop() + getPaddingBottom();
            if (heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(height, heightRequirement);
            }
        }

        // Required call: set width and height
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // do as little as possible inside onDraw to improve performance

        // draw the text on the canvas after adjusting for padding
        canvas.save();
        canvas.translate(getPaddingLeft(), getPaddingTop());
        mStaticLayout.draw(canvas);
        canvas.restore();
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:id="@+id/activity_main"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:padding="@dimen/activity_vertical_margin"
    tools:context="com.example.layoutpractice.MainActivity">

    <com.example.layoutpractice.MyView
        Android:layout_centerHorizontal="true"
        Android:background="@color/colorAccent"
        Android:padding="10dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"/>
</RelativeLayout>

Anmerkungen

  • This , This und This waren hilfreich, um zu lernen, wie Sie eine benutzerdefinierte Textverarbeitungsansicht erstellen.

  • Siehe Ansichtsklasse erstellen , wenn Sie benutzerdefinierte Attribute hinzufügen möchten, die über Code oder XML festgelegt werden können.

64
Suragch

Hier ist meine Erklärung zum Zeichnen von mehrzeiligem Text auf Leinwand.

Paint-Objekt deklarieren. Verwenden Sie TextPaint, eine Erweiterung von Paint.

TextPaint textPaint;

Paint-Objekt initialisieren Stellen Sie Ihre eigene Farbe, Größe usw. ein.

textPaint = new TextPaint();
textPaint.setAntiAlias(true);
textPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
textPaint.setColor(Color.YELLOW);

Fügen Sie die getTextHeight-Funktion hinzu

private float getTextHeight(String text, Paint paint) {
    Rect rect = new Rect();
    Paint.getTextBounds(text, 0, text.length(), rect);
    return rect.height();
}

fügen Sie in Ihre onDraw-Funktion folgende Zeilen ein

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    String text = "This is a lengthy text. We have to render this properly. If layout mess users review will mess. Is that so ? ";

    Rect bounds = canvas.getClipBounds();

    StaticLayout sl = new StaticLayout(text, textPaint, bounds.width(),
            Layout.Alignment.ALIGN_CENTER, 1, 1, true);

    canvas.save();

    //calculate X and Y coordinates - In this case we want to draw the text in the
    //center of canvas so we calculate
    //text height and number of lines to move Y coordinate to center.
    float textHeight = getTextHeight(text, textPaint);
    int numberOfTextLines = sl.getLineCount();
    float textYCoordinate = bounds.exactCenterY() -
            ((numberOfTextLines * textHeight) / 2);

    //text will be drawn from left
    float textXCoordinate = bounds.left;

    canvas.translate(textXCoordinate, textYCoordinate);

    //draws static layout on canvas
    sl.draw(canvas);
    canvas.restore();
}

Höflichkeit geht an Beitrag von KOC

0
Nalin