Android

[android] 커스텀 스낵바(custom Snackbar) 레이아웃 예제 및 총정리

안드로이드 스낵바(custom Snackbar)

스낵바(Snackbar)는 휴대폰 화면하단에 위치하는 메세지 박스입니다. 물론 토스트와 같이 스낵바의 위치를 변경할 수 있습니다. 스낵바는 자주 사용하는 토스트(Toast)와 유사합니다. 스낵바와 토스트의 가장 큰 차이점은 사용자의 액션을 받아서 처리하느냐 안하느냐의 차이라고 생각됩니다. 토스트는 사용자에게 정보성으로 제공되는 메세지인 반면에 스낵바는 메세지를 주는 동시에 경고성 알림을 주고 사용자에게 확인버튼을 제공하여 클릭을 유도할 수 있습니다. 사용자가 인지하고 넘어가는지 확인하는 방법으로 사용하면 유용합니다. 간단한 약관의 동의페이지를 스낵바로 만들어서 사용할 수도 있겠지요.

■토스트(Toast)

Toast.makeText(getApplicationContext(),"Hello",Toast.LENGTH_SHORT).show();

■스낵바(Snackbar)

Snackbar.make(view, "Replace with your own action"
, Snackbar.LENGTH_LONG).setAction("Action", null).show();

기본적인 사용방법으로 사용시 액션이벤트(setAciotn)를 추가할 수 있습니다. 아래 예제는 10초 간 나타났다 사라집니다.

Snackbar.make(view, "리뷰를 쓰러갈까요?", 10000).setAction("YES", new View.OnClickListener()
{
	@Override
	public void onClick(View v)
	{
		//마켓 링크 호출
	}
}).show();   

기본적인 사용방법으로 사용시 스낵바의 백그라운드 색상을 변경하는 방법입니다. setBackgroudColor를 사용해도 되며 다른 메소드도 지원합니다.

FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View view) {
		Snackbar snackbar;
		snackbar = Snackbar.make(view, "종료할까요?",Snackbar.LENGTH_LONG)
				.setActionTextColor(Color.BLUE).setAction("예", new View.OnClickListener()
				{
					@Override
					public void onClick(View v)
					{
						finish();
					}
				});
		View snackView = snackbar.getView();
		snackView.setBackgroundColor(Color.parseColor("#D47FA6"));
		snackbar.show();                
	}
});

커스텀 스낵바

다음으로 스낵바를 커스텀하여 사용하여봅니다. 샘플 예제로 탈출(EXIT) 레이아웃을 하나 생성하였습니다.

[exit_snackbar.xml]

<?xml version="1.0" encoding="utf-8"?>
<!--    android:background="@android:color/transparent"-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/bannerLayout"
    android:background="@drawable/bg_eixt_expane_shape_radius"
    android:gravity="center">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:id="@+id/topLayout"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="10dp"
        android:gravity="center_vertical">

        <ImageView
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:id="@+id/imageView3"
            android:background="@drawable/baseline_power_settings_new_24"/>

        <TextView
            android:id="@+id/textView21"
            android:layout_width="254dp"
            android:layout_height="wrap_content"
            android:text="@string/go_out"
            android:layout_marginLeft="5dp"
            android:textSize="20sp"
            android:textColor="#ffffff"
            android:layout_gravity="center_vertical"
            android:layout_marginRight="10dp" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="10dp"
        android:background="@color/colorAccent"/>

    <LinearLayout
        android:id="@+id/bottomLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="1dp"
        android:orientation="horizontal">
        <LinearLayout
            android:id="@+id/linearLayout3"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="@drawable/update_bg_left_shape_radius"
            android:gravity="center_vertical|center"
            android:layout_marginRight="2.5dp"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/answer_no"
                android:textColor="@color/colorContent"
                android:textSize="16sp"
                android:textStyle="bold" />
        </LinearLayout>
        <LinearLayout
            android:id="@+id/linearLayout4"
            android:layout_width="match_parent"
            android:layout_height="45dp"
            android:background="@drawable/update_bg_right_shape_radius"
            android:gravity="center_vertical|center"
            android:layout_marginLeft="2.5dp"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textView4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/answer_yes"
                android:textColor="@color/colorContent"
                android:textSize="16sp"
                android:textStyle="bold" />
        </LinearLayout>
    </LinearLayout> 
</LinearLayout>

[activity_main.xml]

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mainLayout"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

    <include layout="@layout/content_main" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@drawable/baseline_dialpad_24" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

커스텀 스낵바를 사용하기위해서는  스낵바를 노출할 뷰(대상)이 필요합니다. 보통 MainActivity의 레이아웃를 지정합니다.

private View snackBarLayout;
snackBarLayout = findViewById(R.id.mainLayout);

스낵바를 사용해보면 패딩값이 적용되어 있는 것을 확인할 수 있습니다. 패딩값을 제거하는 방법입니다. setPadding()메소드를 사용하여 0으로 값을 설정합니다.

globalSnackbar = Snackbar.make(snackBarLayout, "", Snackbar.LENGTH_INDEFINITE);
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) globalSnackbar.getView();
layout.setPadding(0,0,0,0);  

setBackgroudTint()메소드는 exit_snackbar.xml 레이아웃의 백그라운드 색상을 변경하는 것이 아닙니다. 우리는 스낵바 자체의 레이아웃 안에 exit_snackbar.xml 레이아웃을 추가 하는 개념이라고 생각하시면 이해하기 쉽습니다. 즉 exit_snackbar.xml 레이아웃을 감싸는 레이아웃이 있다는 얘기지요. 스낵바의 BackgrountTint의 기본값은 values.xml에 설정되어 있습니다.

<color name="design_snackbar_background_color">#323232</color>

투명하게 변경하고 싶은 경우 아래 컬러를 하나 추가하여 사용하세요.

<color name="snackbar_transparent_bg_color">#00ffffff</color>
globalSnackbar.setBackgroundTint(ContextCompat.getColor(this, R.color.snackbar_transparent_bg_color));
globalSnackbar.setBackgroundTint(ContextCompat.getColor(this, R.color.colorAccent));
globalSnackbar.show();

[MainActivity.class]

    private Snackbar globalSnackbar;
    private View snackBarLayout;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
        
        Toolbar toolbar = findViewById(R.id.toolbar);
        
        snackBarLayout = findViewById(R.id.mainLayout);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action"
                , Snackbar.LENGTH_LONG).setAction("Action", null).show();
            }
        });
    }
    
    private void dismissGlobalSnackbar(){
        if(globalSnackbar!=null) {
            globalSnackbar.dismiss();
        }
    }    
    
    private void showAlarmSnackbar() {
        globalSnackbar = Snackbar.make(snackBarLayout, "", Snackbar.LENGTH_INDEFINITE);
        Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) globalSnackbar.getView();
        //layout.setBackgroundResource(R.drawable.backgroud_xml);
        layout.setPadding(0,0,0,0);  //마진값 없애기

        //inflate view
        View snackView = getLayoutInflater().inflate(R.layout.exit_snackbar, null);
        LinearLayout linearLayout3 = snackView.findViewById(R.id.linearLayout3);
        LinearLayout linearLayout4 = snackView.findViewById(R.id.linearLayout4);

        linearLayout3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismissGlobalSnackbar();
            }
        });


        linearLayout4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });

        layout.addView(snackView, 0);

        //레이아웃 백그라운드 색상변경
        //globalSnackbar.setBackgroundTint(ContextCompat.getColor(this, R.color.colorAccent));
        globalSnackbar.show();
 
    }    

[build.gradle]

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29

    defaultConfig {
        applicationId "test.app"
        minSdkVersion 23
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'androidx.navigation:navigation-fragment:2.3.1'
    implementation 'androidx.navigation:navigation-ui:2.3.1'

    //AdMob Ads SDK
    implementation 'com.google.android.gms:play-services-ads:19.5.0' 

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

[참고 자료]

https://stackoverflow.com/questions/41317923/android-snackbar-layout

[관련 자료]

https://stackoverflow.com/questions/33885424/how-to-create-android-snackbar-with-custom-layout

https://www.tutorialspoint.com/how-to-how-to-customize-snackbar-s-layout-in-android

https://stackoverflow.com/questions/32453946/how-to-customize-snackbars-layout

https://everyshare.tistory.com/47

[다른 글 더 보기]

[프로그래밍/Android] – [Android] 패키지명 일괄 변경 및 프로젝트 폴더명 변경하기

[프로그래밍/Android] – [Android] 다크 테마 만들기(Dark Theme)

Leave a Reply

error: Content is protected !!