Android Multiline Snackbar


84

http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs에Snackbar 표시된대로 Android 디자인 지원 라이브러리의 새로운 기능을 활용 하여 여러 줄 스낵바를 표시 하려고합니다 .

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 에만 표시됩니다. 모든 행을 표시하려면 어떻게해야합니까?

추신 : 시도했는데 Toast모든 라인이 표시되었습니다.


AFAIK, 스낵바는 빠른 사용자 경고 / 피드백을위한 것이며 "싱글 라인"과 같이이를 지원하도록 설계되었습니다. 여러 줄로 된 경고 / 피드백을 표시하려면 사용자가 메시지를 읽은 후 조치를 취할 수 있으므로 대화 상자를 표시하는 것이 좋습니다.
mudit

3
@mudit은 국제화에 대해 생각합니다. 영어 문자열이 한 줄에 들어갈 수 있더라도 독일어는 맞지 않을 수 있습니다. 또한 Google은 여러 줄 스낵바에 대한 머티리얼 디자인 사양을 제공했습니다 (질문에서 연결했습니다). 피해야하는 이유는 무엇입니까?
Dima Kornilov 15.06.08

답변:


224

maxLinesSnackbars Textview 의 속성을 설정하기 만하면됩니다.

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하여 Snackbar의 TextView에 액세스합니다.

당신도 사용할 수 있습니다 R.id.snackbar_text. 그것은 나를위한 일입니다.


필요한 실제 줄 수를 계산하는 방법이 있습니까? 아니면 추측해야합니까?
Chris

@ 크리스는 안드로이드가있을 수 있지만, 텍스트가 자동으로 축소된다됩니다 작은 길이가 ... 경우 당신은 맥스를 지정할 수 있습니다
Nilesh Senta

22
최신 androidx libs의 경우 com.google.android.material.R.id.snackbar_text 여야합니다. 그러나 IMHO ID는 향후 변경 될 수 있으므로이 관행은 피해야합니다.
mtsahakis 2011

1
이것은 지원 라이브러리의 각 버전에 따라 변경 될 수있는 TextView ID에 의존하기 때문에이 답변은 실제로 영구적 인 솔루션이 아니라 해킹입니다. 작동 할 수도 있지만 프로덕션에서 임의로 중단 될 수도 있습니다.
Chapz

1
이에 대한 권장 API가 있습니까? 이 방법이 해킹이라는 데 동의하지만 이에 대해 노출 된 API가 없다면 대안이 없습니다.
fobbymaster

31

앱의 values.xml에서 사용되는 미리 정의 된 값을 재정의 할 수 있습니다.

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

이 값은 기본적으로 Snackbar에서 사용됩니다.


18
앱에서 컴파일 또는 런타임 오류를 생성하지 않고 이름을 바꾸거나 삭제할 수있는 디자인 라이브러리에 의해 정의 된 개인 정수이기 때문에 이러한 관행은 피해야합니다.
Oasis Feng

4
예,하지만 이것은 OS의 개인 리소스에 액세스하는 것과는 매우 다르다는 점을 분명히해야한다고 생각합니다. 동일한 버전의 디자인 라이브러리를 사용하는 한 작동합니다. 최신 버전으로 업데이트하는 경우 어쨌든 앱을 철저히 테스트해야한다면 체크리스트에 추가하세요.
devconsole

단 한 줄만 표시되는 킨들 화재 장치에서는 작동하지 않는다는 것을 알려줍니다. @Nilesh 답변이 작동했습니다.
Naveen Dissanayake

1
체크리스트가 길어지는 것이 마음에 들지 않아 비추천했습니다.
ban-geoengineering

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

이것에 대한 나의 발견은 다음과 같습니다.

Android는 여러 줄 스낵바를 지원하지만 여러 줄 스낵바의 높이가 80dp (거의 2 줄)가되어야한다는 설계 지침과 일치하는 최대 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
: 나는 그러나 재료 사양이 너무 112dp와 플로팅 작업을 언급이 답변을 받아 i.imgur.com/1ACCoQb.png
디마 코르닐로프

여러 줄 스낵바의 높이를 치수로 지정할 수 있습니까?
alp


1
가이드 라인을 받아들이고 싶지 않다면 어떤 가이드 라인도 따르지 마십시오. Google이 가이드 라인과 도구에서 그래들 빌드 시스템이 개발자에게 골칫거리 인 이유보다 훨씬 옳다면?
Jigar 2011

@DimaKornilov는 완전히 2 줄 길이의 텍스트가 있고 작업을 제공하는 경우에만 112dp로 설정됩니다. 이 경우 작업으로 인해 스낵바가 112dp로 확장됩니다.
Christopher Rucinski 2015

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

스낵바에 포함 된 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;
}

텍스트 든 항상 null이
stannums

코드를 다시 확인하십시오. 다음은 Snackbar의 레이아웃에 대한 AOSP 소스 코드 입니다. TextView 개체가 있다는 것을 알 수 있으므로 텍스트가 null이 될 수 없습니다.
Chantell Osejo 2017 년

findViewsWithText이미 텍스트를 알고 있기 때문에 사용하는 것이 더 나을 수 있습니다 . 이 솔루션은 몇 가지 상황에서 중단 될 수 있습니다 (예 : 텍스트 뷰가 스낵바 레이아웃의 하위 항목이되는 경우).
natario

이것은 나를 위해 작동하지 않습니다. SnackbarLayout에는 내부에 또 다른보기가 있습니다. 그래서는 snackbarLayout.getChildAt()을 반환하지 않습니다 TextView.
Vitor Hugo Schwaab

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

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

와트? 최종 변수에 null을 할당하고 리스너에서 호출 했습니까? 100 % NPE를 원하십니까?
osipxd 2018

@OsipXD Fixed for him :)
안드로이드 개발자

2

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>

여기에 이미지 설명 입력

참고 : 라이브러리 버전 1.2.0 이 필요합니다 .


2
좋은 지적이지만 라이브러리는 여전히 알파 상태입니다 (2020 년 5 월) :)
Anton Malyshev

2

Kotlin에서는 다음과 같이 할 수 있습니다.

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

또한 대체 할 수 setSingleLine(false)maxLines = 3 .

Android Studio에서

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

편집하다

나는 이것을 다시 작동시킬 수 없었기 때문에, 몇몇 다른 사람들이 이미 공유 한 것을 Kotlin에서 작성하는 가장 깨끗한 방법이라고 생각하는 것을 공유하겠습니다.

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 다시 작동하게 할 수 없으므로 답변을 업데이트했습니다.
Gumby The Green

지금 충돌 : java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setSingleLine(boolean)' on a null object reference
Android 개발자

@androiddeveloper이 종속성이 있습니까? implementation 'com.google.android.material:material:1.1.0'Snackbar가 com.google.android.material.snackbar.Snackbar하나입니까? 그렇지 않은 경우 android.support.design.R.id.snackbar_text리소스 ID로 시도 하십시오.
Gumby The Green

그것들은 당신이 새 프로젝트를 만들 때 얻는 것입니다 (그리고 내가 만들었습니다).
안드로이드 개발자

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

1

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

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

그래서 나는 Google의 최신 머티리얼 디자인 라이브러리를 com.google.android.material:material:1.1.0 사용하고 있으며 아래의 간단한 코드 스 니펫을 사용하여 스낵바에서 더 많은 라인을 허용하도록 해결했습니다. 새로운 개발자에게도 도움이되기를 바랍니다.

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

0

다른 답변의 불완전 함을 피하기 위해 updateMaxLineGoogle이 텍스트보기의 ID를 변경하기로 결정하면이 솔루션이 중단 될 가능성이 적습니다.)

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
        }
    }
}

여기에 이미지 설명 입력

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.