پیاده سازی Bottom Sheet Dialog در اندروید

پیاده سازی یک Dialog از نوع Bottom Sheet Dialog
نمایش dialog تقریبا در هر برنامه اندرویدی لازم است. پیاده سازی یک Dialog بسیار ساده و آسان است. اما در این مقاله قصد داریم تا یک Bottom Sheet کمکی بسازیم. که بسیار شبیه یک Dialog عمل می کند. برای این منظور دو راه پیاده سازی داریم. یکی BottomSheetDialogFragment و دیگری BottomSheetDialog. به جای هر توضیحی توجه شما را به نتیجه نهایی کار جلب می کنم :
در این آموزش بهترین روش را برای پیاده سازی bottom sheet dialog مطابق با روش کار material design دنبال می نماییم.
قدم اول : ایجاد پروژه جدید و افزودن dependency مربوطه
implementation 'com.google.android.material:material:1.0.0'
قدم دوم : ساخت layout مروبط به Bottom Sheet
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="8dp" > <TextView android:id="@+id/textView" android:layout_marginTop="8dp" android:drawableLeft="@drawable/ic_share" android:drawableStart="@drawable/ic_share" android:text="@string/action_share" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" style="@style/ActionItem" /> <TextView android:id="@+id/textView2" android:drawableLeft="@drawable/ic_upload" android:drawableStart="@drawable/ic_upload" android:text="@string/action_upload" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView" style="@style/ActionItem" /> <TextView android:id="@+id/textView3" android:drawableLeft="@drawable/ic_copy" android:drawableStart="@drawable/ic_copy" android:text="@string/action_copy" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" style="@style/ActionItem" /> <TextView android:id="@+id/textView4" android:drawableLeft="@drawable/ic_print" android:drawableStart="@drawable/ic_print" android:text="@string/action_print" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView3" style="@style/ActionItem" /> </androidx.constraintlayout.widget.ConstraintLayout>
قدم سوم : آپدیت رنگ ها و dimens در resources
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#008577</color> <color name="colorPrimaryDark">#00574B</color> <color name="colorAccent">#D81B60</color> <color name="colorGray">#747474</color> </resources>
<?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="default_margin">16dp</dimen> <dimen name="drawable_padding">24dp</dimen> <dimen name="text_size">16sp</dimen> <dimen name="normal_padding">16dp</dimen> </resources>
تم مخصوص به Bottom Sheet Dialog مربوطه را به شکل زیر پیاده می سازیم :
<style name="ActionItem"> <item name="android:textSize">@dimen/text_size</item> <item name="android:drawablePadding">@dimen/drawable_padding</item> <item name="android:layout_width">0dp</item> <item name="android:layout_height">wrap_content</item> <item name="android:padding">@dimen/normal_padding</item> </style>
و در نهایت String های موجود در پروژه را در Strings.xml تعریف می کنیم :
<resources> <string name="app_name">Bottom Sheet Dialog Fragment</string> <string name="action_share">Share</string> <string name="action_upload">Upload</string> <string name="action_copy">Copy</string> <string name="action_print">Print</string> </resources>
قدم سوم : ساخت زیر کلاسی از BottomSheetDialogFragment
کلاسی با نام ActionBottomDialogFragment که از کلاس BottomSheetDialogFragment ارث بری می کند را می سازیم. در این کلاس از interface ی برای مدیریت callback ها و کلیک شدن هر کدام از موارد موجود در Bottom Sheet استفاده می شود.
import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.bottomsheet.BottomSheetDialogFragment; public class ActionBottomDialogFragment extends BottomSheetDialogFragment implements View.OnClickListener { public static final String TAG = "ActionBottomDialog"; private ItemClickListener mListener; public static ActionBottomDialogFragment newInstance() { return new ActionBottomDialogFragment(); } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.bottom_sheet, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); view.findViewById(R.id.textView).setOnClickListener(this); view.findViewById(R.id.textView2).setOnClickListener(this); view.findViewById(R.id.textView3).setOnClickListener(this); view.findViewById(R.id.textView4).setOnClickListener(this); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof ItemClickListener) { mListener = (ItemClickListener) context; } else { throw new RuntimeException(context.toString() + " must implement ItemClickListener"); } } @Override public void onDetach() { super.onDetach(); mListener = null; } @Override public void onClick(View view) { TextView tvSelected = (TextView) view; mListener.onItemClick(tvSelected.getText().toString()); dismiss(); } public interface ItemClickListener { void onItemClick(String item); } }
قدم چهارم : تکمیل layout مربوط به MainActivity
در این xml یک TextView برای نمایش نتیجه کلیک هر کدام از موارد در Bottom Sheet قرار داده شده است.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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" tools:context=".MainActivity" > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:background="@color/colorAccent" android:onClick="showBottomSheet" android:padding="8dp" android:text="Show BottomSheet" android:textColor="#fff" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.4" /> <TextView android:id="@+id/tvSelectedItem" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="32dp" android:textSize="@dimen/text_size" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" tools:text="Selected Item" /> </androidx.constraintlayout.widget.ConstraintLayout>
قدم نهایی : تکمیل کلاس MainActivity و ست نمودن OnClickListener های مربوطه
import android.os.Bundle; import android.view.View; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity implements ActionBottomDialogFragment.ItemClickListener { TextView tvSelectedItem; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvSelectedItem = findViewById(R.id.tvSelectedItem); } public void showBottomSheet(View view) { ActionBottomDialogFragment addPhotoBottomDialogFragment = ActionBottomDialogFragment.newInstance(); addPhotoBottomDialogFragment.show(getSupportFragmentManager(), ActionBottomDialogFragment.TAG); } @Override public void onItemClick(String item) { tvSelectedItem.setText("Selected action item is " + item); } }