متریال دیزاین : بخش ششم : کار با Snackbar

معرفی Snackbar یا اسنک بار در اندروید:

به نام خدا. Snackbar را می توان نسخه جدیدی از Toast دانست. شاید واژه “جایگزین” مناسب نباشد اما در موارد زیادی استفاده از اسنک بار به جای Toast می تواند رضایت بخش بوده و زیبایی بیشتری به اپ ما بدهد. ضمن اینکه در اسنک بار، شخصی سازی بیشتری در اختیار داریم.
به تصویر زیر دقت کنید:

اسنک بار در متریال دیزاین اندروید

بعد از اینکه کاربر در اپلیکیشنی مانند Gmail، ایمیلی را حذف می کند، پیغام Message is deleted بجای نمایش در قالب Toast، به صورت نواری با پس زمینه تیره رنگ و به حالت انیمیشن از پایین صفحه ظاهر شده و پس از پایان زمان تعیین شده به همانصورت به طرف پایین برگشته و محو می شود.
یا یک مثال دیگر از اسنک بار:

Android Material Design Snackbar

در اینجا پیغامی مبنی بر عدم دسترسی به شبکه به کاربر اعلام شده است.
در هر دو مثال بالا، علاوه بر نمایش پیغام، یک Action نیز در سمت راست اضافه شده که کاربر می تواند عملی را انجام دهد. مانند لغو حذف ایمیل در مثال اول و تلاش مجدد برای اتصال به شبکه در مثال دوم. پس یکی از مزیت های اسنک بار نسب به Toast همین قابلیت اضافه کردن دکمه و اکشن است.

دموی یک اسنک بار:

در ادامه به بررسی Snackbar در قالب یک پروژه می پردازم.

ساخت و بررسی Snackbar:

یک پروژه با نام Snackbar و MinSDK 17 در اندروید استودیو ایجاد کردم. مانند مباحث گذشته، اسنک بار نیز علاوه بر کتابخانه اصلی متریال دیزاین یعنی appcompat-v7 به کتابخانه design هم نیاز دارد:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:27.0.2'
    implementation 'com.android.support:design:27.0.2'
}

برای اینکه قابلیت های اسنک بار به درستی اجرا شود (مانند قابلیت کشیدن به سمت راست برای از بین بردن یا swipe-to-dismiss) لازم است view ای که Snackbar در آن قرار گرفته از جنس CoordinatorLayout باشد. پس لایه اکتیویتی را به CoordinatorLayout تبدیل کرده و یک id نیز به آن اختصاص می دهم:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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/crd_layout"
    tools:context="ir.android_studio.snackbar.MainActivity">
    

</android.support.design.widget.CoordinatorLayout>

فعلا با layout کاری ندارم و به تکمیل کدهای جاوای اکتیویتی می پردازم:

package ir.android_studio.snackbar;

import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    CoordinatorLayout crdLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        crdLayout = findViewById(R.id.crd_layout);

        Snackbar snkbr = Snackbar.make(crdLayout, "Sample Snackbar Message", 
        Snackbar.LENGTH_LONG);
        
        snkbr.show();

    }
}

ابتدا CoordinatorLayout را با نام دلخواه crdLayout تعریف کردم. سپس یک نمونه از Snackbar با نام snkbr ساختم. همانطور که مشاهده می کنید با استفاده از تابع make که ۳ پارامتر ورودی می گیرد، اسنک بار را تکمیل می کنیم. ورودی اول همان view پدر یعنی CoordinatorLayout است. ورودی بعد، متن پیغام و سومی مدت زمان نمایش پیغام است که سه مقدار LENGTH_LONG (نمایش طولانی مدت)، LENGTH_SHORT (نمایش کوتاه مدت) و LENGTH_INDEFINITE را می پذیرد. استفاده از مقدار LENGTH_INDEFINITE باعث می شود تا زمانی که کاربر اقدام به بستن Snackbar نکند (مانند کشیدن به سمت راست یا تایید اکشن موجود در اسنک بار) پیغام روی صفحه باقی بماند. در نهایت توسط متد show() اسنک بار نمایش داده می شود.
پروژه را اجرا می کنم:

اجرای Snackbar

به محض اجرای پروژه، اسنک بار نیز ظاهر شده و پس از چند ثانیه از صفحه حذف می شود. برای راحتتر شدن کار، اسنک بار را درون یک دکمه قرار می دهم تا با هر بار لمس دکمه، اجرا شود. به جای Button عادی از یک Floating Action Button استفاده می کنم تا یکی از اهمیت های استفاده از CoordinatorLayout را نیز در این مبحث درک کنید. FAB مبحث گذشته را به پروژه اضافه می کنم:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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/crd_layout"
    tools:context="ir.android_studio.snackbar.MainActivity">

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|start"
        android:layout_margin="16dp"
        android:src="@android:drawable/ic_dialog_email"
        app:backgroundTint="#2c489c"
        android:clickable="true"
        android:focusable="true"
        app:fabSize="normal"
        app:rippleColor="#b12f2f"/>

</android.support.design.widget.CoordinatorLayout>
package ir.android_studio.snackbar;

import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    CoordinatorLayout crdLayout;
    FloatingActionButton mFab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        crdLayout = findViewById(R.id.crd_layout);
        mFab = findViewById(R.id.fab);

        mFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

        Snackbar snkbr = Snackbar.make(crdLayout, "Sample Snackbar Message", 
        Snackbar.LENGTH_LONG);
                snkbr.show();

            }
        });

    }
}

در واقع همان پروژه FAB است با این تفاوت که بجای Toast از Snackbar استفاده شده. پروژه را اجرا می کنم:

اضافه کردن FloatingActionButton به پروژه

اجرای اسنک بار بعد از کلیک روی FAB

با لمس دکمه FAB، اسنک بار نمایش داده می شود. به تصویر دوم دقت کنید. با ظاهر شدن اسنک بار، FAB نیز به همان اندازه به بالا رفته و تداخل ایجاد نشده است در صورتی که اگر بجای CoordinatorLayout از سایر layout ها مانند RelativeLayout استفاده می کردیم، FAB در جای خود باقی می ماند و اسنک بار قسمتی از FAB را می پوشاند.

با استفاده از متد setDuration می توان مدت زمان نمایش اسنک بار را سفارشی کرد:

mFab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        Snackbar snkbr = Snackbar.make(crdLayout, "Sample Snackbar Message", 
        Snackbar.LENGTH_LONG);
        snkbr.setDuration(9000);
        snkbr.show();

    }
});

در کد بالا، اسنک بار به مدت ۹ ثانیه اجرا می شود.
اما در ابتدای مبحث به یکی از مهمترین برتری های Snackbar نسبت به Toast اشاره شد که تعریف اکشن است:

اضافه کردن Action به Snackbar

متد setAction دو ورودی نیاز دارد. ورودی اول عنوان اکشن و دومی یک OnClickListener که اکشن مدنظر درون آن تعریف می گردد. به اینصورت:

mFab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        Snackbar snkbr = Snackbar.make(crdLayout, "Sample Snackbar Message", 
        Snackbar.LENGTH_LONG);

        snkbr.setDuration(3000);

        snkbr.setAction("OK", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                
            }
        });

        snkbr.show();

    }
});

ساده ترین اکشن، استفاده از dismiss() است. این متد قبل از به پایان رسیدن زمان نمایش اسنک بار و هنگام لمس “OK” توسط کاربر، اسنک بار را می بندد. پس snkbr.dismiss() را به setAction اضافه کرده و پروژه را اجرا می کنم:

snkbr.setAction("OK", new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        snkbr.dismiss();

    }
});

اضافه کردن Action به Snackbar

گزینه ای با نام OK به سمت راست اضافه شده که با لمس آن، اسنک بار بسته می شود.
هر اکشن دیگری نیز می توان درنظر گرفتن. مثلا این اکشن نقش Undo را داشته باشد. یعنی در اپلیکیشن مدیریت ایمیل، بعد از نمایش پیغام “ایمیل ها حذف شد”، امکان لغو حذف وجود داشته باشد که با لمس گزینه Undo، ایمیل های حذف شده مجدد به اینباکس برگشته و پیغام جدیدی مبنی بر بازیابی ایمیل ها نمایش داده شود.

از setActionTextColor هم برای تغییر رنگ گزینه اکشن استفاده می شود:

mFab.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        final Snackbar snkbr = Snackbar.make(crdLayout, "Sample Snackbar Message",
        Snackbar.LENGTH_LONG);

        snkbr.setDuration(5000);

        snkbr.setAction("OK", new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                snkbr.dismiss();

            }
        });

        snkbr.setActionTextColor(Color.RED);

        snkbr.show();

    }
});

تغییر رنگ اکشن اسنک بار

اگر بخواهیم به جای استفاده از رنگهای پیش فرض اندروید، از رنگهای تعریف شده در colors.xml استفاده کنیم به اینصورت قابل انجام است:

snkbr.setActionTextColor(getResources().getColor(R.color.colorAccent));

در اینجا رنگ با نام colorAccent به setActionTextColor پاس داده می شود.

در نهایت رنگ متن پیغام و پس زمینه Snackbar را نیز به اینصورت تغییر می دهم:

View snkView = snkbr.getView();
snkView.setBackgroundColor(Color.GRAY);

TextView txtView = snkView.findViewById(android.support.design.R.id.snackbar_text);
txtView.setTextColor(Color.GREEN);

در ابتدا یک نمونه از View با نام دلخواه snkView ساخته و snkbr.getView را درون آن قرار می دهم. به اینصورت view مربوط به snkbr به snkView متصل می شود. حالا برای تعریف رنگ پس زمینه از setBackgroundColor و رنگ متن از setTextColor استفاده شده که لازم است از TextView یک نمونه ساخته و به آی دی snackbar_text پیوند دهیم. snackbar_text در خود اندروید تعریف شده و چون مربوط به کتابخانه design است به صورت android.support.design.R.id.snackbar_text قابل دسترسی است.

تغییر رنگ بک گراند و متن snackbar

MainActivity.java:

package ir.android_studio.snackbar;

import android.graphics.Color;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    CoordinatorLayout crdLayout;
    FloatingActionButton mFab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        crdLayout = findViewById(R.id.crd_layout);
        mFab = findViewById(R.id.fab);

        mFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            final Snackbar snkbr = Snackbar.make(crdLayout, "Sample Snackbar Message",
            Snackbar.LENGTH_LONG);

                snkbr.setDuration(5000);

                snkbr.setAction("OK", new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {

                        snkbr.dismiss();

                    }
                });

                // snkbr.setActionTextColor(Color.RED);

                snkbr.setActionTextColor(getResources().getColor(R.color.colorPrimaryDark));

                View snkView = snkbr.getView();
                snkView.setBackgroundColor(Color.GRAY);
                TextView txtView = snkView.findViewById(android.support.design.R.id.snackbar_text);
                txtView.setTextColor(Color.GREEN);

                snkbr.show();

            }
        });


    }
}

https://developer.android.com/reference/android/support/design/widget/Snackbar.html
https://material.io/guidelines/components/snackbars-toasts.html

توجه : سورس پروژه درون پوشه Exercises قرار داده شده است

دانلود فایل آموزشی با فرمت PDF به همراه سورس پروژه
تعداد صفحات : ۱۷
حجم : ۱ مگابایت
قیمت : رایگان

یک دیدگاه بنویسید

پرسش‌های زیر تایید و پاسخ داده نخواهد شد:
۱ : جزء موارد پاسخ داده شده در مطلب "مشکلات و پرسش های رایج" باشد
۲ : سوال قبلا توسط کاربران در دیدگاهها مطرح و پاسخ داده شده باشد
۳ : سوال خارج از مبحث آموزشی موجود در این صفحه باشد

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

کد امنیتی *