एंड्रॉइड मल्टीलाइन स्नैकबार


84

मैं नए लाभ उठाने के लिए कोशिश कर रहा हूँ Snackbarएंड्रॉयड डिजाइन समर्थन लाइब्रेरी से बहु Snackbar प्रदर्शित करने के लिए के रूप में में दिखाया गया है, http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs :

import android.support.design.widget.Snackbar;

final String snack = "First line\nSecond line\nThird line";
Snackbar.make(mView, snack, Snackbar.LENGTH_LONG).show();

यह केवल First line...मेरे Nexus 7 पर प्रदर्शित होता है । इसे सभी लाइनों को कैसे प्रदर्शित किया जाए?

PS: मैंने कोशिश की Toastऔर इसने सभी लाइनों को प्रदर्शित किया।


AFAIK, स्नैकबर्स त्वरित उपयोगकर्ता चेतावनी / प्रतिक्रिया के लिए हैं और इसे "सिंगल लाइन" का समर्थन करने के लिए डिज़ाइन किया गया है। यदि आप एक चेतावनी / प्रतिक्रिया दिखाना चाहते हैं जिसमें बहुस्तरीय हैं, तो मैं आपको एक संवाद दिखाने का सुझाव दूंगा क्योंकि उपयोगकर्ता आपके संदेश को पढ़ने के बाद कार्रवाई कर सकता है।
मुदित

3
@ मुदित अंतर्राष्ट्रीयकरण के बारे में सोचते हैं। भले ही अंग्रेजी स्ट्रिंग एकल पंक्ति में फिट हो सकती है, जर्मन नहीं हो सकता है। साथ ही Google ने मल्टीलाइन स्नैकबार के लिए मटीरियल डिज़ाइन कल्पना प्रदान की (मैंने इसे प्रश्न में जोड़ा) - अगर इसे टाला जाए तो क्यों?
दीमा कोर्निलोव

जवाबों:


224

maxLinesस्नैकबर्स टेक्स्टव्यू की विशेषता सेट करें

View snackbarView = snackbar.getView();
TextView textView = (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
textView.setMaxLines(5);  // show multiple line

यदि आप अधिक हाल की "com.google.android.material:material:1.0.0"निर्भरता का उपयोग कर रहे हैं , तो आप इसका उपयोग करेंगे: com.google.android.material.R.id.snackbar_textस्नैकबार के टेक्स्ट व्यू तक पहुंचने के लिए।

आप चाहे तो इसका उपयोग भी कर सकते हैं R.id.snackbar_text। यह मेरे लिए काम कर रहा है।


क्या वास्तविक तरीके से आवश्यक लाइनों की गणना करने का एक तरीका है, या क्या हमें अनुमान लगाना है?
क्रिस

@ क्रिस के पास एंड्रॉइड हो सकता है लेकिन आप मैक्सलाइन को निर्दिष्ट कर सकते हैं यदि पाठ छोटी लंबाई है तो यह स्वचालित रूप से सिकुड़ जाएगा ...
नीलेश शांति

22
नवीनतम androidx के लिए libs.google.android.material.R.id.snackbar_text होना चाहिए। लेकिन भविष्य में IMHO आईडी बदल सकती है इसलिए इस अभ्यास से बचना चाहिए।
मस्तहाकिस

1
चूंकि यह टेक्स्ट व्यू आईडी पर निर्भर करता है जो समर्थन के प्रत्येक संस्करण के साथ बदल सकता है, यह उत्तर वास्तव में एक स्थायी समाधान नहीं है, बल्कि एक हैक है। यह काम कर सकता है, लेकिन यह उत्पादन में बेतरतीब ढंग से टूट सकता है।
चापज

1
क्या इसके लिए अनुशंसित एपीआई है? मैं मानता हूं कि यह विधि एक हैक है, लेकिन अगर इसके लिए कोई एपीआई नहीं है, तो इसका कोई विकल्प नहीं है।
फोबाइमैस्टर

31

एक मूल्यों के लिए पूर्वनिर्धारित मूल्य को ओवरराइड कर सकता है जो ऐप के मानों में होता है। xml

<integer name="design_snackbar_text_max_lines">5</integer>

यह मान Snackbar द्वारा डिफ़ॉल्ट रूप से उपयोग किया जाता है।


18
इस अभ्यास से बचना चाहिए, क्योंकि यह डिज़ाइन लाइब्रेरी द्वारा परिभाषित एक निजी पूर्णांक है, जिसे आपके ऐप में कोई संकलन या रनटाइम त्रुटि उत्पन्न किए बिना नाम बदला या हटाया जा सकता है।
ओएसिस फेंग

4
हां, लेकिन मुझे लगता है कि यह स्पष्ट किया जाना चाहिए कि यह ओएस के निजी संसाधनों तक पहुंचने से बहुत अलग है। यह तब तक काम करेगा जब तक आप डिज़ाइन लाइब्रेरी के एक ही संस्करण से चिपके रहेंगे। यदि आप किसी नए संस्करण में अपडेट होते हैं, तो आपको अपने ऐप को वैसे भी पूरी तरह से परखना होगा, बस इसे अपनी चेकलिस्ट पर रखें।
Devconsole

बस आपको बता दें कि यह किंडल फायर उपकरणों पर काम नहीं करता है जो केवल 1 लाइन दिखाते हैं। @ निलेश जवाब ने काम किया।
नवीन डिसनायके

1
नीचे की ओर देखा क्योंकि मुझे चेकलिस्ट के विचार लंबे समय तक पसंद नहीं हैं।
प्रतिबंध-जियोइंजीनियरिंग

13
Snackbar snackbar =  Snackbar.make(view, "Text",Snackbar.LENGTH_LONG).setDuration(Snackbar.LENGTH_LONG);
View snackbarView = snackbar.getView();
TextView tv= (TextView) snackbarView.findViewById(android.support.design.R.id.snackbar_text);
tv.setMaxLines(3); 
snackbar.show();

11

यहाँ इस पर मेरी खोज है:

एंड्रॉइड मल्टीलाइन स्नैकबार का समर्थन करता है, लेकिन इसकी 2 लाइनों की अधिकतम सीमा होती है जो डिज़ाइन दिशानिर्देश से मेल खाती है जहां यह कहता है कि मल्टीलाइन स्नैक बार की ऊंचाई 80dp (लगभग 2 लाइनें) होनी चाहिए

इसे सत्यापित करने के लिए, मैंने चीज़केक Android नमूना परियोजना का उपयोग किया। अगर मैं निम्नलिखित स्ट्रिंग का उपयोग करता हूं:

Snackbar.make(view, "Random Text \n When a second snackbar is triggered while the first is displayed", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();

इस स्थिति में, मैं 2 पंक्ति के पाठ के साथ मल्टीलाइन स्नैक बार देख सकता हूं, अर्थात "जब दूसरा स्नैकबार ट्रिगर होता है" लेकिन अगर मैं इस कोड को निम्नलिखित कार्यान्वयन में बदलता हूं:

Snackbar.make(view, "Random Text \n When \n a second snackbar is triggered while the first is displayed", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();

मैं केवल "रैंडम टेक्स्ट \ nWhen ... " देख सकता हूं । इसका अर्थ है कि डिज़ाइन लाइब्रेरी जानबूझकर अधिकतम 2 पंक्तियों का टेक्स्टव्यू बाध्य करती है।


2
मैंने इस उत्तर को स्वीकार कर लिया है, लेकिन सामग्री के चश्मे में 112dp के साथ स्नैकबार का उल्लेख भी है: i.imgur.com/1ACCoQb.png
दीमा

क्या आप आयाम में मल्टीलाइन स्नैक बार की ऊंचाई को नाम दे सकते हैं?
अल्फा


1
यदि आप उस गाइड लाइन को स्वीकार नहीं करना चाहते हैं तो किसी भी दिशानिर्देश का पालन न करें। अगर Google अपने दिशानिर्देश और टूल में बहुत सही है, तो डेवलपर के लिए ग्रेडल बिल्ड सिस्टम सिरदर्द क्यों है?
जिगर

@DimaKornilov यह 112dp पर सेट किया जाएगा यदि और केवल अगर आपके पास पाठ है जो पूरी तरह से 2 पंक्तियों का है और आप एक कार्रवाई प्रदान करते हैं। उस स्थिति में कार्रवाई स्नैकबार को 112dp तक विस्तारित करने का कारण होगी।
क्रिस्टोफर रुकिंस्की

5

सामग्री डिजाइन के लिए, संदर्भ है com.google.android.material.R.id.snackbar_text

val snack = Snackbar.make(myView, R.string.myLongText, Snackbar.LENGTH_INDEFINITE).apply {
                view.findViewById<TextView>(com.google.android.material.R.id.snackbar_text).maxLines = 10
            }
            snack.show()

3

स्नैकबार द्वारा निहित टेक्स्टव्यू के लिए संसाधन ID को हार्डकोड करने वाले सुझावों का एक विकल्प टेक्स्टव्यू खोजने के लिए पुनरावृति करना है। यह लंबे समय तक सुरक्षित है और आपको आईडी बदलने के न्यूनतम डर के साथ समर्थन लाइब्रेरी को अपडेट करने देता है।

उदाहरण:

 public static Snackbar getSnackbar(View rootView, String message, int duration) {
    Snackbar snackbar = Snackbar.make(rootView, message, duration);
    ViewGroup snackbarLayout = (ViewGroup) snackbar.getView();

    TextView text = null;

    for (int i = 0; i < snackbarLayout.getChildCount(); i++) {
        View child = snackbarLayout.getChildAt(i);

        // Since action is a button, and Button extends TextView,
        // Need to make sure this is the message TextView, not the 
        // action Button view.
        if(child instanceof TextView && !(child instanceof Button)) {
            text = (TextView) child;
        }
    }

    if (text != null) {
        text.setMaxLines(3);
    }
    return snackbar;
}

पाठ किसी भी तरह से अशक्त
stannums

अपना कोड दोबारा जांचें। स्नैकबार के लेआउट के लिए यहां AOSP स्रोत कोड है। आप देखेंगे कि वहां एक TextView ऑब्जेक्ट है, इसलिए टेक्स्ट का अशक्त होना संभव नहीं है।
चेटेल ओस्जो

findViewsWithTextआप पाठ पहले से ही जानते हैं , इसलिए उपयोग करना और भी बेहतर हो सकता है । यह समाधान कुछ स्थितियों में टूट सकता है (जैसे कि यदि हमारा पाठ दृश्य स्नैकबार लेआउट के बच्चे का बच्चा बन जाता है)।
नातारियो

यह मेरे लिए काम नहीं करेगा। SnackbarLayout का इसके अंदर एक और दृश्य है। तो snackbarLayout.getChildAt()कभी नहीं लौटेगा TextView
विटर ह्यूगो श्वाब

2

SetMaxLines का उपयोग करने के बजाय, मैं अपनी सामग्री के लिए टेक्स्टव्यू रैप बनाने के लिए setSleleLine का उपयोग करता हूं।

String yourText = "First line\nSecond line\nThird line";
Snackbar snackbar = Snackbar.make(mView, yourText, Snackbar.LENGTH_SHORT);
    TextView textView =
        (TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text);
    textView.setSingleLine(false);
snackbar.show();

2

यह मेरे लिए काम करता है

Snackbar snackbar =  Snackbar.make(mView, "Your text string", Snackbar.LENGTH_INDEFINITE);
((TextView) snackbar.getView().findViewById(android.support.design.R.id.snackbar_text)).setSingleLine(false);
snackbar.show();

2

देर से, लेकिन किसी के लिए उपयोगी हो सकता है:

public void showSnackBar(String txt, View view){
    final Snackbar snackbar = Snackbar.make(view,txt,Snackbar.LENGTH_INDEFINITE)
        .setAction("OK", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //do something
            }
        });
    View view = snackbar.getView();
    TextView textView = (TextView) view.findViewById(android.support.design.R.id.snackbar_text);
    textView.setMaxLines(5);
    snackbar.show();
}

वाट? आपने केवल अंतिम चर को शून्य सौंपा और इसे श्रोता में बुलाया? आप 100% एनपीई चाहते हैं?
१ip:

@OsipXD उसके लिए निश्चित है :)
Android डेवलपर

2

सामग्री घटक लाइब्रेरी के साथ आप इसे snackbarTextViewStyleऐप थीम में विशेषता के साथ परिभाषित कर सकते हैं :

<style name="AppTheme" parent="Theme.MaterialComponents.*">
  ...
  <item name="snackbarTextViewStyle">@style/snackbar_text</item>
</style>

<style name="snackbar_text" parent="@style/Widget.MaterialComponents.Snackbar.TextView">
    ...
    <item name="android:maxLines">5</item>
</style>

यहां छवि विवरण दर्ज करें

नोट : इसमें लाइब्रेरी के संस्करण 1.2.0 की आवश्यकता है ।


2
अच्छी बात है, लेकिन पुस्तकालय अभी भी अल्फा राज्य में है (मई 2020) :)
एंटोन मालिशेव

2

कोटलिन में, आप बस कर सकते हैं

Snackbar.make(root_view, "Yo\nYo\nYo!", Snackbar.LENGTH_SHORT).apply {
    view.snackbar_text.setSingleLine(false)
    show()
}

आप के setSingleLine(false)साथ भी बदल सकता है maxLines = 3

एंड्रॉइड स्टूडियो आपको जोड़ने के लिए संकेत देना चाहिए

import kotlinx.android.synthetic.main.design_layout_snackbar_include.view.*

संपादित करें

मैं इसे फिर से काम करने के लिए नहीं मिला है, इसलिए मैं सिर्फ वही साझा करूंगा जो मुझे लगता है कि कोटलिन में लिखने का सबसे साफ तरीका है जो कुछ अन्य लोगों ने पहले ही साझा किया है:

import com.google.android.material.R as MaterialR

Snackbar.make(root_view, "Yo\nYo\nYo!", Snackbar.LENGTH_SHORT).apply {
    val textView = view.findViewById<TextView>(MaterialR.id.snackbar_text)
    textView.setSingleLine(false)
    show()
}


यह उपयोग / आयात करने की पेशकश नहीं करता है snackbar_text
एंड्रॉयड डेवलपर

@androiddeveloper मुझे फिर से काम करने के लिए नहीं मिल सकता है, इसलिए मैंने जवाब अपडेट किया है।
गम्भी द ग्रीन

अब क्रैश: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setSingleLine(boolean)' on a null object reference
एंड्रॉइड डेवलपर

@androiddeveloper क्या आपके पास यह निर्भरता है: implementation 'com.google.android.material:material:1.1.0'और क्या आपका स्नैकबार com.google.android.material.snackbar.Snackbarएक है? यदि नहीं, android.support.design.R.id.snackbar_textतो संसाधन आईडी के रूप में प्रयास करें ।
गम्भी द ग्रीन

जब आप एक नया प्रोजेक्ट बनाते हैं (और मैंने किया था) वे हैं, और यह दुर्घटनाग्रस्त हो गया।
Android डेवलपर

1

ऐसा करने का एक तरीका जो पुस्तकालय के नए संस्करणों में बदलने की स्थिति में दुर्घटनाग्रस्त नहीं होगा:

Snackbar.make(...).setAction(...) {
    ...
}.apply {
    (view.findViewById<View?>(R.id.snackbar_text) as? TextView?)?.setSingleLine(false)
}.show()

और बिना आईडी के उपयोग किए जाने का एक तरीका है, स्नैकबार में सभी टेक्स्ट व्यू को असीमित मल्टी-लाइन के लिए सेट करना:

@UiThread
fun setAllTextViewsToHaveInfiniteLinesCount(view: View) {
    when (view) {
        is TextView -> view.setSingleLine(false)
        is ViewGroup -> for (child in view.children)
            setAllTextViewsToHaveInfiniteLinesCount(child)
    }
}

Snackbar.make(...).setAction(...) {
    ...
}.apply {
    setAllTextViewsToHaveInfiniteLinesCount(view)
}.show()

जावा में एक ही कार्य:

@UiThread
public static void setAllTextViewsToHaveInfiniteLines(@Nullable final View view) {
    if (view == null)
        return;
    if (view instanceof TextView)
        ((TextView) view).setSingleLine(false);
    else if (view instanceof ViewGroup)
        for (Iterator<View> iterator = ViewGroupKt.getChildren((ViewGroup) view).iterator(); iterator.hasNext(); )
            setAllTextViewsToHaveInfiniteLines(iterator.next());
}

1

कोटलिन में आप एक्सटेंशन का उपयोग कर सकते हैं।

// SnackbarExtensions.kt

fun Snackbar.allowInfiniteLines(): Snackbar {
    return apply { (view.findViewById<View?>(R.id.snackbar_text) as? TextView?)?.isSingleLine = false }
}

उपयोग:

Snackbar.make(view, message, Snackbar.LENGTH_LONG)
                        .allowInfiniteLines()
                        .show()

0

बस एक त्वरित टिप्पणी, यदि आप com.google.android.material:materialउपसर्ग या पैकेज का उपयोग कर रहे हैं, तो R.idहोना चाहिएcom.google.android.material

val snackbarView = snackbar.view
val textView = snackbarView.findViewById<TextView>(com.google.android.material.R.id.snackbar_text)
textView.maxLines = 3

0

इसलिए मैं गूगल से नवीनतम सामग्री डिजाइन पुस्तकालय का उपयोग कर रहा हूं, com.google.android.material:material:1.1.0 और मैंने स्निपरबार में अधिक लाइनों की अनुमति देने के लिए नीचे सरल कोड स्निपेट का उपयोग किया है। आशा है कि यह नए डेवलपर्स को भी मदद करेगा।

TextView messageView = snackbar.getView().findViewById(R.id.snackbar_text);
messageView.setMaxLines(5);

0

अन्य उत्तरों के उपयोग से बचने के लिए updateMaxLine, यदि Google किसी टेक्स्ट दृश्य की आईडी बदलने का निर्णय लेता है, तो यह समाधान टूटने की संभावना कम है)

val snackBar = Snackbar.make(view, message, duration)
 snackBar.view.allViews.updateMaxLine(5)
 snackBar.show()

बस ध्यान दें, यह विकल्प Snakbar दृश्य में सभी पाठ विचारों के लिए अधिकतम लाइन को अपडेट करेगा (जो tbh मुझे नहीं लगता है)

इसे विस्तार के रूप में जोड़ें

private fun <T> Sequence<T>.updateMaxLine(maxLine : Int) {
    for (view in this) {
        if (view is TextView) {
            view.maxLines = maxLine
        }
    }
}

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.