استارت‌آپ و کارآفرینی

معرفی MaterialDrawer با پشتیبانی از راست به چپ در اندروید

برنامه‌هایی که از Drawer استفاده می‌کنند زیاد هستن و اکثرا این منوی پرکاربرد رو در سمت چپ برنامه قرار دادن (برنامه‌های فارسی البته) که از چپ به راست باز می‌شه. مدتی قبل به دنبال یک کتابخونه خوب با پشتیبانی از RTL می‌گشتم که اتفاقی این کتابخونه رو پیدا کردم.

چندتا از ویژگی‌هاش رو میگم:

  • به‌راحتی با هر پروژه‌ای که دارید در مدت زمان خیلی کم integrate میشه.
  • از اندروید ورژن ۱۰ به بالا پشتیبانی می‌کنه.
  • امکان معرفی چندین پروفایل کاربری مثل برنامه جیمیل رو داره.
  • و از همه مهمتر اینکه به راحتی راست به چپ یا اصطلاحا RTL میشه.

مراحل کار و سورس برنامه رو در Github به همراه تمامی commit‌هایی که انجام شده قرار دادم. هر گونه pull request در جهت بهبود برنامه پذیرفته می‌شود 🙂

قبل از هر چیز با استفاده از Android Studio یک پروژه جدید با یک activity از نوع empty ایجاد می‌کنیم:

Empty Activity

وقتی که پروژه ایجاد شد و کار gradle تموم شد، برنامه رو اجرا کنید تا خروجی برنامه رو ببینید:

Hello World

ابتدا خطوط زیر رو به gradle.build برنامه اضافه می‌کنیم:

compile 'com.android.support:design:23.1.1'
compile('com.mikepenz:materialdrawer:4.5.8@aar') {
       transitive = true
}
compile 'com.mikepenz:google-material-typeface:2.2.0.1@aar'
compile 'com.mikepenz:fontawesome-typeface:4.4.0.1@aar'

منتظر باشید تا کار sync کتابخونه‌ها تموم بشه.
بعدش به کلاس MainActivity دو متغییر زیر رو اضافه می‌کنیم:

 private AccountHeader headerResult = null;
 private Drawer result = null;

اولین متغییر برای تعریف حساب کاربری و هدر Drawer و دومی هم برای تعریف لیست منو مورد استفاده قرار می‌گیره. در ادامه مقدار دهی و تنظیمات هر کدوم توضیح داده میشه.
برای استفاده از قالب‌های ارائه‌شده توسط این کتابخانه فایل activity_main.xml رو به صورت زیر ویرایش کنید:

<?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:fitsSystemWindows="true"
    tools:context="ir.bkhezr.materialdrawerrtl.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.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" />

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

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

با این تغییر می‌توان به toolbar برنامه دسترسی پیدا کرد و مقادیرش رو به دلخواه تغییر داد. نکته دیگه مربوط به styleهای استفاده شده هست، این استایل‌ها در فایل styles.xml به صورت زیر تعریف شده‌اند:

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

هدف از این تغییرات استفاده از برنامه به صورت تمام‌صفحه هست که در تنظیمات المان CoordinatorLayout به صورت android:fitsSystemWindows=”true” مشخص شده.
سپس به MainActivity کد زیر رو برای دسترسی به toolbar اضافه می‌کنیم:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

برای اعمال استایل کتابخونه به فایل AndroidManifest.xml خط زیر را در بخش MainActivity اضافه می‌کنیم:

android:theme="@style/MaterialDrawerTheme.Light.DarkToolbar"

حالا نوبت به مقداردهی هدر و لیست میرسه، ابتدا یک پروفایل با مشخصات زیر ایجاد می‌کنیم:

IProfile profile = new ProfileDrawerItem().withName("Behrouz Khezry").withEmail("bkhezry@gmail.com").withIcon(R.drawable.profile);

سپس کدهای زیر رو اضافه می‌کنیم:

headerResult = new AccountHeaderBuilder()
              .withActivity(this)
              .withCompactStyle(true)
              .addProfiles(
                      profile,
                      new ProfileSettingDrawerItem().withName("Add Account").withDescription("Add new Gmail Account").withIcon(new IconicsDrawable(this, GoogleMaterial.Icon.gmd_plus).actionBar().paddingDp(5).colorRes(R.color.material_drawer_dark_primary_text)).withIdentifier(1),
                      new ProfileSettingDrawerItem().withName("Manage Account").withIcon(GoogleMaterial.Icon.gmd_settings)
                )
              .withSavedInstance(savedInstanceState)
              .withTextColor(Color.BLACK)
              .build();
result = new DrawerBuilder()
              .withActivity(this)
              .withAccountHeader(headerResult) //set the AccountHeader we created earlier for the header
              .addDrawerItems(
                      new PrimaryDrawerItem().withName("Home").withIcon(FontAwesome.Icon.faw_home).withIdentifier(1),
                      new PrimaryDrawerItem().withName("Free Play").withIcon(FontAwesome.Icon.faw_gamepad),
                      new PrimaryDrawerItem().withName("Custom").withIcon(FontAwesome.Icon.faw_eye),
                      new SectionDrawerItem().withName("Section Header"),
                      new SecondaryDrawerItem().withName("Settings").withIcon(FontAwesome.Icon.faw_cog),
                      new SecondaryDrawerItem().withName("Help").withIcon(FontAwesome.Icon.faw_question).withEnabled(false),
                      new SecondaryDrawerItem().withName("Source").withIcon(FontAwesome.Icon.faw_github),
                      new SecondaryDrawerItem().withName("Contact").withIcon(FontAwesome.Icon.faw_bullhorn)
              )
              .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                  @Override
                  public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                      if (drawerItem != null && drawerItem.getIdentifier() == 1) {
                       }

                       if (drawerItem instanceof Nameable) {
                            toolbar.setTitle(((Nameable) drawerItem).getName().getText(MainActivity.this));
                        }

                        return false;
                    }
                })
            .withSavedInstance(savedInstanceState)
            .withDrawerGravity(Gravity.END)
            .build();

دقت کنید که با تغییر Gravity.END منو از سمت راست باز میشه با تغییر این مقدار به Gravity.START منو از سمت چپ باز خواهد شد.

تقریبا برنامه‌مون آماده‌ست، برنامه رو اجرا می‌کنیم و خروجی برنامه به صورت زیر هست:

MaterialDrawer

Main Activity

اگه دقت کنید متن toolbar به سمت راست نیومده و هنوز سمت چپ هست برای جابجا کردنش به سمت راست، من خودم یه ایده دادم شاید روش بهتر و ساده‌تری وجود داشته باشه، اگه هست توی کامنت بهم بگید، ممنون میشم.
من از menu استفاده کردم، ابتدا فایل menu_main.xml رو ایجاد می‌کنیم و کد زیر رو داخلش وارد می‌کنیم:

<menu 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"
    tools:context="ir.bkhezry.materialdrawerrtl.MainActivity">
    <item
        android:id="@+id/title"
        android:orderInCategory="100"
        android:title="MaterialDrawer"
        app:showAsAction="always" />
    <item
        android:id="@+id/drawershow"
        android:orderInCategory="100"
        android:title=""
        android:icon="@mipmap/ic_view_headline_white_48dp"
        app:showAsAction="always" />
</menu>

با این کار یک عکس و یک متن به ActionBar اضافه میشه. از عکس برای باز کردن Drawer و از متن برای نمایش عنوان برنامه استفاده می‌کنیم. دقت کنید که باید عنوان اصلی toolbar رو هم به صورت خالی در نظر بگیریم:

toolbar.setTitle("");
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
     int id = item.getItemId();
     if (id == R.id.drawershow) {
          result.openDrawer();
          return true;
     }
     return super.onOptionsItemSelected(item);
 }

برنامه رو اجرا می‌کنیم، خروجی برنامه به صورت زیر هست:
ّFinal ActionBar

حتما به لینک اصلی کتابخونه مراجعه کنید، توضیحات خیلی بیشتری ارائه شده، همچنین اگه به بخش issue مراجعه کنید متوجه خواهید شد که ارائه‌دهنده این کتابخونه هیچ سوالی رو بی‌جواب نگذاشته.

 

47 نظرات
  1. مهدی می گوید

    ببخشید ولی DrawerLayout که توی ساپورت لایبرری ۴ گنجانده شده و به راحتی راست به چپ میشه دیگه نیازی به استفاده از لایبرری های دیگه نیست.

    1. بهروز خضری می گوید

      بله حرف شما درسته.
      این کتابخانه چیزی بیشتر از راست به چپ کردن داره والا چهار هزار ستاره نمی‌گرفت.
      مثل این می‌مونه بگیم که وقتی جاوا اسکریپت همه چیز داره، چه نیازی به جی کوئری هست.

  2. محمد می گوید

    بسیار عالی و کاربردی مثله همیشه Top 🙂

  3. فایبرکانکس می گوید

    خیلی جالبه مطالب شما همش تخصصی هستند و کسی جز برنامه نویسان متوجه نمیشوند. این خیلی روند خوبیه و امیدوارم همه وبلاگ های ایران تخصصی بشوند.

  4. majid می گوید

    فوق العاده بووووووود:-*

  5. I.M.A.N می گوید

    سلام دوستان
    من برای ساخت منوی کشویی از این روش استفاده کردم . روش بسیار راحت و ساده ای است اما برای تغییر سایز و رنگ دادن به آیکون ها ( در حالت پیش فرض آیکون ها خاکستری نمایش داده می شوند حتی اگر رنگی باشند) با مشکل مواجه شدم که البته با سرچ زیاد حل شد.

    مشکل الان اینجاست که چطور فونت های استفاده شده را به فونت دلخواه تغییر دهم؟؟؟؟؟

    1. بهروز خضری می گوید

      سلام وقت بخیر، برای تغییر فونت برنامه به این آدرس که مقاله ای دیگر از سایت هست مراجعه کنید:
      http://goo.gl/wcB77w

  6. I.M.A.N می گوید

    سلام. ممنون از راهنمایی تون . ولی من همون مرحله ی اول گیر کردم. موقع اضافه کردن کتابخونه به اندروید استودیو با خطا مواجه میشم. شاید باید وی پی ان استفاده کنم؟ درسته؟

    1. بهروز خضری می گوید

      چند روزه که پورت ۴۴۳ با کندی سرعت و بعضا با قطعی مواجه هست، بله استفاده کنید 🙂

  7. I.M.A.N می گوید

    ممنون بهروز جان

  8. I.M.A.N می گوید

    سلام . میخواستم بدونم چطور میشه عناصر روی دراورو به این روش روی کل دراور ست کرد؟ مثلا من پنج تا گزینه داره لیستم و توی گوشی ۴٫۷ اینچ تا پایین منو پر میشه ولی روی گوشی ۵ اینچ فضای پایین خالی می مونه که اصلا جالب نیست. ممنون میشم راهنمایی کنین

    1. بهروز خضری می گوید

      در این مورد ایده‌ای ندارم
      توو بخش issue کتابخانه هم گشتم و چیزی پیدا نکردم.
      به فرض اندازه در ۵ اینچ کاملا fit بشه
      برای سایزهای کوچکتر یعنی همین ۴٫۷ باید اسکرول کنید تا همه آیتم‌ها رو ببینید
      به نظرم کلا روش درستی نیست این کار.

  9. کویرسبز می گوید

    سلام ممنونم بابت آموزش خوبتون
    ی خواهشی داشتم می خوام از datepiker بصورت فارسی ( شمسی) که امکان انتخاب تاریخ توسط کاربر رو داشته باشه توی برنامه استفاده کنم ی کتابخونه پیدا کردم اما هر کاری می کنم خطا میده امکانش هست مثل کاری برای منو انجام از این کتابخونه یاستفاده کنید و ی آموزشی بدید ؟
    خیلی ممنون میشم https://github.com/alirezaafkar/SunDatePicker

    1. بهروز خضری می گوید

      سلام،
      این کتابخانه رو تست کردم و خطایی نداشت.

  10. کویر سبز می گوید

    سلام امکانش هست ی مثال عملی بزنید من هر کاری می کنم با مشکل برخورد می کنم ؟؟؟؟
    ممنون میشم

    1. بهروز خضری می گوید

      سلام،
      متن مقاله رو مجددا بخونید، ذکر شده که سورس کامل این مثال در گیت هاب قرار گرفته.

  11. ستار می گوید

    سلام و خسته نباشید به جناب خضری
    بنده نمونه رو از گیتهاب گرفتم و اجرا کردم چند مورد :
    اگر زبان گوشی انگلیسی باشه برنامه درست کار میکنه ولی اگر زبان گوشی فارسی باشه جواب نمیده!!
    یعنی خود اندروید طبق زبان گوشی تغییر اعمال میکنه!
    که نمونه دراوری که خود اندروید استودیو گذاشته تو زبان فارسی راست به چپ و انگلیسی چپ به راست میاره !
    چطور میشه در دو حالت (زبان گوشی هر زبانی که باشه ) راست به چپ بیاره ؟؟؟؟

    1. بهروز خضری می گوید

      سلام،
      من تا الان روی گوشی با زبان فارسی تست نکردم. دو پیشنهاد دارم
      اول اینکه locale برنامه رو در برنامه‌نویسی تغییر بدید
      http://stackoverflow.com/questions/2900023/change-language-programatically-in-android

      دوم اینکه در بخش issue این کتابخانه گفته شده که برای راست به چپ بودن، باید در Android manifest گزینه rtl رو اضافه کنید که به حداقل نسخه اندروید ۱۴ نیاز داره. بگردید در اون بخش پیداش می‌کنید، اگه مشکل رو حل کردن، همینجا اطلاع بدید.
      ممنون.

    2. محمدرضا مهمدی کرتلایی می گوید

      شما میتونید از طریق کد زیر شرط تعیین زمانی که صفحه گوشی چپ به راست یا بالعکس باشه اینکارو براتون انجام بده.
      Configuration config = getResources().getConfiguration();
      if(config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
      }else{
      getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
      }

  12. ستار می گوید

    خیلی ممنونم بابت راهنمایتون
    با روش اول جواب گرفتم ، منتهی :
    زبان رو نباید رو فارسی گذاشت؛
    من زبان رو به انگلیسی ست کردم درست شد!
    ———————————————-
    احتمالا کتابخانه فقط در حالت انگیسی بودن دیوایس راست به چپ میکنه!
    حل شد ولی نمیدونم اصولیه یا نه!
    لطفا اگه اصولی نیست – راه های دیگه ای هست مطرح کنید ممنون میشم.
    چون کانفیگ کردن به انگلیسی اپ نمیدونم شاید در آینده مشکل ساز بشه!
    شایدم نشه!
    ولی باز بهتره از اصولی بودن کار خیالمون راحت بشه خوبه!

    1. بهروز خضری می گوید

      بر روی گوشی اس سه سامسونگ که فارسی بود تستش کردم،
      در هر دو حالت فارسی و انگلیسی از سمت راست باز شد. شاید برای اون دستگاه خاص مشکل داره، پیشنهاد می‌کنم روش دوم رو هم امتحان کنید

  13. ستار می گوید

    خیلی ممنون گوشی من هواوی y511 – anroid 4.2.2 – احتمالا همینطوریه که شما میفرمایید!
    نمونه دوم رو رفتم تو پیج گیتهابش – نتونستم چیزی در این مورد پیدا کنم.
    اگه بیشتر راهنمایی کنین ممنون میشم!

    1. بهروز خضری می گوید

      یه rtl جستجو می‌کردید کلی راهنمایی و سوال وجود داره
      https://github.com/mikepenz/MaterialDrawer/issues/1044

  14. ستار می گوید

    جناب خضری ممنون برای پاسخ هاتون
    زیاد وقتتون رو گرفتم – همون روش اول رو اجرا میکنم
    ————
    خیلی لطف کردین !
    آموزشهاتون و نکاتتون حرف ندارن!
    ———–

  15. سامان می گوید

    چطوری میشه nav drawer زیر Toolbar باز بشه ؟

    1. بهروز خضری می گوید

      سلام،
      به لینک زیر برید و دمو این کتابخانه رو نگاه کنید، مثالش ذکر شده
      https://github.com/mikepenz/MaterialDrawer

  16. محمد می گوید

    سلام و خسته نباشید
    دو تا سوال دارم اول اینکه ایتم های درون drawer رو چه جوری میشه راست چین کرد و دوم اینکه چه جوری رنگ drawer رو مانند مثال هاش میشه تیره کرد

    1. بهروز خضری می گوید

      سلام،
      برای سوالتون بهتره به بخش issue کتابخانه در گیت‌هاب مراجعه کنید. مثال‌هاش رو بررسی کنید، تنظیمات بیشتری داره.
      بخصوص در نسخه جدید.
      https://goo.gl/dSO1sl

  17. آتی وردپرس می گوید

    سلام ، ممنونم بابت انتنشار این پست و معرفی این کتابخانه . از گیتهاب گرفتمش و دارم راست به چپش رو بررسی می کنم . باز هم تشکر از شما

  18. dehghan می گوید

    با سلام، من وقتی که خطوط مربوط به کتابخانه mikepenz:materialdrawer را در قسمت gradle.bulid اضافه میکنم بعد از sync شدن برای هر سه کتابخانه با این خطا روبرو میشم
    Failed to resolve: com.mikepenz:materialdrawer:4.5.8
    چطور میتونم این مشکل را حل کنم و کتابخانه را به پروژه اضافه کنم

    1. بهروز خضری می گوید

      سلام. مشکل شما احتمالا بخاطر تحریم بودن jcenter‌ هست.
      متاسفانه برای سینک کردن کتابخانه‌ها به وی‌پی‌ان نیاز دارید.

      1. dehghan می گوید

        با سلام مجدد، حتی با استفاده از vpn هم ، دوباره خطا میده ….

        1. بهروز خضری می گوید

          سلام
          همین الان نسخه این آموزش و نسخه جدید کتابخانه رو تست کردم و با وی‌پی‌ان اضافه شد.

  19. امید می گوید

    سلام خسته نباشید چطوری میشه از این یه کلاس ساخت که مجبور نباشیم تو هر صفحه از اکتیوتی ها از این همه کد استفاده کنیم

    1. امید می گوید

      کسی ایده ای نداره؟

    2. بهروز خضری می گوید
  20. رضا بنایی می گوید

    بهروز جون عالیه (دلمم واست تنگ شده ;))

  21. سید محمد رضا می گوید

    سلام من این کتابخانه رو تونستم پیاده سازی کنم اما چرا نمیشه تو لایوت main.xml تغییرات رو به خوبی انجام داد و تازه اگر هم مثلا یه باتن در بالاترین سطح قرار بدیم میره زیر Toolbar

    1. بهروز خضری می گوید

      سلام،
      برای حل این مشکل از include‌ کردن layout مانند این مثال درgist استفاده کنید:
      https://gist.github.com/bkhezry/a638133716157411f61b5afc368a36e9

  22. اسماعیل می گوید

    واقعا ممنونم.عالی بود.

  23. علی زنده دل می گوید

    سلام.
    برای حالت Em,bedded که منو زیر toolbar باز بشه چکار باید بکنم؟
    میخوام زیر تولبار باشه و drawertoggle هم موقعی که منو باز میشه به صورت فلش در بیاد

  24. امیر اکبرزاده می گوید

    با سلام و خسته نباسید ممنونم از آموزش خوبتون
    در همون ابتدا موقع اظافه کردن compile ها به فایل gradle.bield با خطا مواجه میشم ممنونم راهنمایی بفرمایید بدجوری گیر کردم :((((((((((
    عکسش رو نتونستم اینجا آپلود کنم

  25. َamir می گوید

    سلام آموزش بسیار عالی بود فقط سوالی که برام بیش اومد میخواستم بدونم چطوری میشه به هر یک از ایتم های داخل منوی کشوییمون وظیفه داد یا به صورتی تعریفشون کرد مثل یک باتن

  26. مهسا گلی می گوید

    سلام.اقا این همون یه که من میخوام.ولس من با اکلیپس کار میکنم و gradle.build رو نداره.
    خواهش میکنم کمکم کنید تا با اکلیپس درستش کنم.چیکار باید کنم.کتابخونه خاصی هم باید وارد کنم?

  27. milad می گوید

    سلام ببخشید میخواستم بدونم چگونه میشه رنگ ایکون نویگیشت دراور رو داخل تولبار تغیر داد اگه میشه راهنمایی کنید؟؟؟؟؟

  28. hesam می گوید

    سلام
    داخل تولبار با این خط به راحتی راست به چپ میشه نوشته و آیکون
    android:layoutDirection=”rtl”

  29. Rullah می گوید

    با سلام
    این مبحث بین سری آموزش جاوا بین قسمت های ۶ و ۷ قرار گرفته که به نظر نامرتبط می رسهُ لطفا اصلاح شود.
    تشکر

ارسال یک پاسخ

آدرس ایمیل شما منتشر نخواهد شد.