Android में StaticLayout का उपयोग कैसे किया जाता है?




canvas text (2)

यहाँ कैनवास पर बहुस्तरीय पाठ बनाने के लिए मेरी व्याख्या है।

पेंट वस्तु की घोषणा करें। TextPaint का उपयोग करें जो पेंट का विस्तार है।

TextPaint textPaint;

पेंट ऑब्जेक्ट को प्रारंभ करें। अपना रंग, आकार आदि सेट करें।

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

GetTextHeight फ़ंक्शन जोड़ें

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

अपने onDraw फ़ंक्शन में इस तरह निम्नलिखित पंक्तियाँ डालें

@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();
}

शिष्टाचार केओसी के पद पर जाता है

मुझे अपना स्वयं का कस्टम टेक्स्ट StaticLayout बनाने की आवश्यकता है इसलिए मैं एक कैनवस पर पाठ आकर्षित करने के लिए StaticLayout बारे में सीख रहा हूं। यह Canvas.drawText() सीधे उपयोग करने के लिए बेहतर है, या इसलिए documentation कहता है। हालाँकि, दस्तावेज़ीकरण कोई उदाहरण नहीं देता कि यह कैसे किया जाता है। StaticLayout.Builder को करने का नया तरीका होने के लिए केवल एक अस्पष्ट संदर्भ है।

मुझे here एक उदाहरण मिला लेकिन यह थोड़ा दिनांकित लगता है।

मैंने आखिरकार काम किया हालांकि यह कैसे करना है इसलिए मैं नीचे अपनी व्याख्या जोड़ रहा हूं।


StaticLayout ( StaticLayout और BoringLayout समान ) का उपयोग किसी कैनवास पर टेक्स्ट को लेआउट और ड्रा करने के लिए किया जाता है। यह आमतौर पर निम्नलिखित कार्यों के लिए उपयोग किया जाता है:

  • यह निर्धारित करना कि बाहर रखे जाने के बाद कितना बड़ा बहुस्तरीय पाठ होगा।
  • बिटमैप छवि पर पाठ आकर्षित करना।
  • एक कस्टम दृश्य बनाना जो अपने स्वयं के टेक्स्ट लेआउट को संभालता है (जैसा कि एम्बेडेड टेक्स्ट व्यू के साथ एक समग्र दृश्य बनाने के विपरीत)। StaticLayout स्वयं StaticLayout internally उपयोग करता है।

पाठ का आकार मापना

इकलौती रेखा

यदि आपके पास केवल पाठ की एक पंक्ति है, तो आप इसे Paint या TextPaint माप सकते हैं।

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();

बहुपंक्ति

हालांकि, अगर लाइन रैपिंग है और आपको ऊंचाई की आवश्यकता है, तो StaticLayout का उपयोग करना बेहतर है। आप चौड़ाई प्रदान करते हैं और फिर आप StaticLayout से ऊंचाई प्राप्त कर सकते हैं।

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(); 

नई एपीआई

यदि आप नए StaticLayout.Builder (एपीआई 23 से उपलब्ध) का उपयोग करना चाहते हैं, तो आप इस तरह से अपना लेआउट प्राप्त कर सकते हैं:

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

आप डॉट नोटेशन का उपयोग करके अतिरिक्त सेटिंग्स पर काम कर सकते हैं:

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();

एक छवि पर पाठ लिखना

मैं भविष्य में इसका और विस्तार कर सकता हूं, लेकिन अब इस पोस्ट को एक ऐसे तरीके के उदाहरण के लिए StaticLayout जो StaticLayout का उपयोग करता है और एक बिटमैप लौटाता है।

कस्टम टेक्स्ट हैंडलिंग दृश्य बनाना

यहां StaticLayout का उपयोग करते हुए कस्टम दृश्य का एक StaticLayout । यह एक साधारण TextView तरह व्यवहार करता है। जब पाठ स्क्रीन पर फिट होने के लिए बहुत लंबा है, तो यह स्वचालित रूप से लाइन लपेटता है और इसकी ऊंचाई बढ़ाता है।

कोड

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>

टिप्पणियाँ

  • This , this और this सीखने में उपयोगी था कि कस्टम टेक्स्ट हैंडलिंग दृश्य कैसे बनाया जाए।

  • यदि आप कस्टम विशेषताएँ जोड़ना चाहते हैं जो कोड या xml से सेट की जा सकती हैं, तो व्यू क्लास बनाना देखें






staticlayout