Android Multiline Snackbar

时间:2015-06-08 09:32:51

标签: android android-support-library android-design-library

我尝试利用Android设计支持库中的新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();

它只在我的Nexus 7上显示First line...。如何让它显示所有行?

PS:我尝试了Toast并显示了所有行。

17 个答案:

答案 0 :(得分:25)

可以覆盖app的values.xml中使用的预定义值

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

默认情况下,Snackbar会使用此值。

答案 1 :(得分:10)

以下是我的发现:

Android确实支持多线小吃店,但它的最大限制为2行符合设计指南,其中多行小吃店的高度应为80dp(差不多2行)

为了验证这一点,我使用了cheesesquare 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();

在这种情况下,我可以看到带有第二行文字的多行小吃店,即“当第二个小吃栏被触发时”,但如果我将此代码更改为以下实施:

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

我只能看到“随机文字\ n当 ... ”时。这意味着设计库有意强制textview最多2行。

答案 2 :(得分:9)

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

答案 3 :(得分:3)

包含对快餐栏包含的textview的资源ID进行硬编码的建议的替代方法是迭代查找TextView。它更长久更安全,让您更新支持库,而不必担心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;
}

答案 4 :(得分:2)

我没有使用setMaxLines,而是使用setSingleLine将textview包装到其内容中。

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

答案 5 :(得分: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();

答案 6 :(得分:1)

迟到,但可能对某人有帮助:

 public void showSnackBar(String txt,View view){
        Snackbar snackbar = null;

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

答案 7 :(得分:1)

我建议您使用 com.google.android.material.snackbar.Snackbar。这是谷歌推荐的方式。首先,您必须添加小吃店。

final Snackbar snackbar = Snackbar.make(
            findViewById(R.id.activity_layout),
            "snackbar explanation text \n multilines \n\n here",
            Snackbar.LENGTH_INDEFINITE)
            .setAction(R.string.action_settings, new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // your action here
                }
            });

然后添加多行支持

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

最后显示小吃店。

snackbar.show();

答案 8 :(得分:1)

一种这样做的方法,在新版本的库中发生更改时,它不会崩溃:

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

一种在不使用ID的情况下做到这一点的方法,将Snackbar中的所有TextView设置为具有无限多行:

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

Java中的相同功能:

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

答案 9 :(得分:1)

通过Material Components Library,您可以使用应用主题中的 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>

enter image description here

注意:它需要库的版本 1.2.0

答案 10 :(得分:0)

2021 年 Kotlin 中 com.google.android.material:material:1.4.0

的答案

isSingleLine = falsemaxLines = 5

都是必需的
Snackbar.make(view, "line 1\nline 2", BaseTransientBottomBar.LENGTH_INDEFINITE)
    .apply {
        this.view.findViewById<TextView>(com.google.android.material.R.id.snackbar_text)?.apply {
            maxLines = 5
            isSingleLine = false
        }
    }
    .show()

答案 11 :(得分:0)

为避免出现其他答案,可以使用updateMaxLine,如果Google决定更改文本视图的ID,则此解决方案不太可能破解)

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

请注意,此选项将更新Snakbar视图中所有文本视图的最大行(我认为这不重要)

将此添加为扩展名

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

enter image description here

答案 12 :(得分:0)

因此,由于我使用的是来自Google的最新材料设计库,com.google.android.material:material:1.1.0,并且我在下面使用了以下简单的代码段,以解决在小吃栏中增加行数的问题。希望对新开发人员也有帮助。

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

答案 13 :(得分:0)

在kotlin中,您可以使用扩展程序。

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

答案 14 :(得分: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

答案 15 :(得分:0)

对于材料设计,引用为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()

答案 16 :(得分:0)

在科特林,你可以做

Snackbar.make(rootView, "Yo!", Snackbar.LENGTH_LONG).apply {
    view.snackbar_text.setSingleLine(false)
    show()
}

如果需要,可以将setSingleLine(false)替换为maxLines = 3

Android Studio应该提示您添加

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