پیاده سازی Tab توسط TabLayout و ViewPager متریال دیزاین
در این بخش به نحوه پیاده سازی Tab ها با استفاده از Fragment و ویجت های TabLayout و ViewPager در اندروید می پردازیم که شامل مباحث زیر می باشد:
- معرفی Tab (تب) متریال در اندروید
- معرفی کامپوننت TabLayout
- معرفی کامپوننت ViewPager
- ساخت یک کلاس برای مدیریت فرگمنت ها و عنوان تب ها در ViewPager و TabLayout
- نحوه اضافه کردن عنوان (text) به Tab ها
- نحوه اضافه کردن آیکون به Tab ها
- نمایش همزمان آیکون و تکست در تب ها
- ویرایش تب ها مانند تغییر رنگ text، رنگ نوار پایین Tab و…
- کاربرد خاصیت های tabGravity و tabMode در TabLayout
این مبحث در قالب PDF و در ۲۹ صفحه تهیه شده که در ادامه چند صفحه ی ابتدایی آن را مشاهده می کنید:
آشنایی با Tab (تب) ها در اندروید:
بنام خدا. Tab ها تقریبا در همه پلتفرم ها و برنامه ها استفاده می شوند. در سیستم عامل ویندوز وقتی یک پنجره تنظیمات را باز می کنید، در بالای پنجره چندین Tab تعبیه شده که با انتخاب هرکدام، به تعدادی از گزینه های مرتبط با عنوان آن تب دسترسی خواهید داشت. یا مثال ساده تر، در مرورگرهای وب مانند کروم و فایرفاکس، برای مشاهده هر وب سایت یک تب (Tab) جدید باز می کنیم. در سایر پلتفرم ها و نرم افزارها هم به همینصورت از Tab ها استفاده می شود. از جمله در سیستم عامل و نرم افزارهای اندروید.
اولین مثالی که به ذهنم رسید پیام رسان WhatsApp است:
در زیر Toolbar سه Tab به نامهای Calls، Chats و Contacts تعریف شده که با انتخاب هر یک از تب ها، محتوا و لیست مرتبط با آن نمایش داده می شود.
معرفی TabLayout در متریال دیزاین
TabLayout یکی دیگر از ویجت (کامپوننت) هایی است که اندروید در متریال دیزاین معرفی کرده و در کتابخانه design در دسترس است. با استفاده از ویجت TabLayout امکان تعریف و مدیریت Tab ها فراهم می شود (یعنی گزینه های Calls، Chats و Contacts در مثال بالا).
ViewPager چیست؟
ViewPager ویجت دیگری است که با استفاده از Fragment ها، می تواند چندین فرگمنت را در یک اکتیویتی نمایش دهد که با کشیدن صفحه به چپ یا راست و یا انتخاب Tab ها در TabLayout، فرگمنت ها به ترتیبی که تعیین کرده ایم نمایش داده می شوند (لیست چت ها، مکالمات و مخاطبین در مثال بالا).
یعنی در اپلیکیشن WhatsApp علاوه بر اینکه با لمس هریک از تب ها، به محتوای آن (یعنی فرگمنت مرتبط با آن تب) دسترسی داریم، با کشیدن فرگمنت ها به دو طرف نیز تب ها جابجا می شوند.
یک پروژه با نام Tabs ایجاد می کنم و با توجه به اینکه در زمان تهیه این آموزش، اکثر دیوایس ها از API 17 و به بالا پشتیبانی می کنند، MinSDK را روی ۱۷ تنظیم می کنم. همانطور که در ابتدا اشاره شد، لازم است کتابخانه design را به پروژه اضافه کنیم:
dependencies { implementation 'com.android.support:appcompat-v7:27.0.2' implementation 'com.android.support:design:27.0.2' }
در مرحله اول، ActionBar پیش فرض پروژه را مطابق آنچه در آموزش تولبار بیان شد، حذف کرده و Toolbar متریال را جایگزین می کنم:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" tools:context="ir.android_studio.tabs.MainActivity"> <android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:id="@+id/m_toolbar" android:background="?attr/colorPrimary" android:elevation="3dp" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> </android.support.v7.widget.Toolbar> </LinearLayout>
من لایه را به LinearLayout از نوع vertical تغییر دادم تا ویجت هایی که اضافه می کنم زیر یکدیگر قرار بگیرند. البته پیاده سازی با RelativeLayout یا CoordinatorLayout نیز امکان پذیر است.
MainActivity.java:
package ir.android_studio.tabs; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; public class MainActivity extends AppCompatActivity { Toolbar mToolbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mToolbar = findViewById(R.id.m_toolbar); setSupportActionBar(mToolbar); } }
قبل از ادامه کار، پروژه را اجرا می کنم تا مطمئن شوم تولبار به اکتیویتی اضافه شده است:
در ادامه، چند فرگمنت ساده به پروژه اضافه می کنم:
سه فرگمنت با نامهای FragmentOne، FragmentTwo و FragmentThree به پروژه اضافه شد که در layout هر فرگمنت یک TextView وجود دارد. مانند fragment_one.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="ir.android_studio.tabs.FragmentOne"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="Fragment One" android:textSize="30sp"/> </FrameLayout>
مجدد main_activity.xml را باز کرده و به صورت زیر دو تگ TabLayout و ViewPager را به لایه اضافه می کنم:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" tools:context="ir.android_studio.tabs.MainActivity"> <android.support.v7.widget.Toolbar android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:id="@+id/m_toolbar" android:background="?attr/colorPrimary" android:elevation="3dp" app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> </android.support.v7.widget.Toolbar> <android.support.design.widget.TabLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/tab_layout" android:background="?attr/colorPrimary" /> <android.support.v4.view.ViewPager android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/view_pager" /> </LinearLayout>
فایل colors.xml:
xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#009688</color> <color name="colorPrimaryDark">#00796B</color> <color name="colorAccent">#FFC107</color> </resources>
برای TabLayout رنگ پس زمینه یکسان با Toolbar تعریف کردم تا به صورت یکپارچه نمایش داده شوند.
TabLayout و ViewPager را در اکتیویتی تعریف می کنم:
package ir.android_studio.tabs; import android.support.design.widget.TabLayout; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; public class MainActivity extends AppCompatActivity { Toolbar mToolbar; TabLayout tbLayout; ViewPager vPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mToolbar = findViewById(R.id.m_toolbar); setSupportActionBar(mToolbar); vPager = findViewById(R.id.view_pager); tbLayout = findViewById(R.id.tab_layout); } }
در ادامه برای مدیریت و نمایش فرگمنت ها یک کلاس جدید با نام دلخواه ViewPagerAdapter به پروژه اضافه می کنم:
ViewPagerAdapter.java:
package ir.android_studio.tabs; public class ViewPagerAdapter { }
سپس این کلاس را از FragmentPagerAdapter ارث بری می کنم. FragmentPagerAdapter به یک import نیاز دارد که همانند گذشته با Alt + Enter انجام می دهم:
package ir.android_studio.tabs; import android.support.v4.app.FragmentPagerAdapter; public class ViewPagerAdapter extends FragmentPagerAdapter { }
اندروید استودیو علامت اخطار نشان می دهد که با کلیک روی آن و انتخاب Implements Methods، به دو متد مورد نیاز FragmentPagerAdapter به کلاس اضافه می شود.
سپس اخطار دیگری میگیرم مبنی بر اینکه یک Constructor (متد سازنده) نیز باید اضافه شود:
در نهایت کلاس به اینصورت تکمیل می شود:
package ir.android_studio.tabs; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; public class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return null; } @Override public int getCount() { return 0; } }
من به دو List نیاز دارم. یکی برای تعریف فرگمنت ها و دیگری برای عنوان Tab ها. پس یک List از نوع Fragment با نام دلخواه frgList و یک لیست از نوع String با نام دلخواه titleList می سازم:
package ir.android_studio.tabs; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import java.util.ArrayList; import java.util.List; public class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> frgList = new ArrayList<>(); private final List<String> titleList = new ArrayList<>(); public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { return null; } @Override public int getCount() { return 0; } }
تصویر نهایی خروجی پروژه این مبحث آموزشی:
جهت مطالعه ادامه آموزش، فایل PDF را دانلود نمائید
توجه : سورس پروژه داخل پوشه Exercises قرار داده شده است.
با توجه به اینکه آموزشهای پایه با قیمت پایین در اختیار کاربر قرار گرفته و درآمد حاصل صرف تامین هزینه های وب سایت و تهیه آموزش های آتی می شود، به اشتراک گذاری این فایل با دیگران خلاف اخلاق خواهد بود.
تعداد صفحات : ۲۹
حجم : ۲ مگابایت
قیمت : ۱۶ هزار تومان
توجه: صرفا در صورتی از درگاه پشتیبان استفاده کنید که قادر به پرداخت از طریق سبد دانلود نباشید.
افزودن به سبد دانلود درگاه پشتیبان
سلام وقتتون بخیر، من تحقیق درباره تب منو و نحوه ایجادش میخوام گوگل رو زیر و رو کردم مطلب درستی پیدا نکردم راهنمایی میکنید بیزحمت؟
سلام وقتتون بخیر
من برنامه رو مو به مو انجام دادم و به اندروید ایکس هم تبدیل کردم اما برنامه بعد از نصب موقع اجرا کرش میکنه لطفا راهنمایی کنید
هزاران دلیل میتونه داشته باشه. تب Build پایین اندروید استودیو رو بعد کرش کردن اپ بررسی کنید ببینید کجا ارور می گیرید
سلام مهندس/
https://s4.uupload.ir/files/screenshot_2021-08-15_051423_7si6.jpg
توی وب سرچ کردم ولی نتونستم مشکلم رو حل کنم.زحمت بکشید ببینید مشکل کجاست و چرا برا من Tab ها رو نشون نمی ده(فقط به نمایش در نمی آد وگرنه وقتی روی Tab ها کلیک می کنم Fragment ها جا به جا می شن)/
https://stackoverflow.com/a/60782796/8314092
سلام وقت بخیر من میخام هر تب رو به یک اکتیویتی که قبلا طراحی کردم وصل کنم.از این آموزش استفاده کردم
https://www.androidhive.info/2012/05/android-combining-tab-layout-and-list-view/
ولی الان بهم هشدار میده کلاس TabActivity از api 13 دیگه قابل استفاده نیست و deprecate شده
چه کنم به نظر شما؟
عذرخواه بابت تاخیر. باید از فرگمنت ها بجاش استفاده کنید
https://android-studio.ir/android-fragments
درود به شما و وقت بخیر
من یک سوالی داشتم چرا اندروید استدیو من از یک کتابخانه ای دیگر فرگمنت استفاده می کند و نسخه ورژن ۴ کلادر لیستش نیست؟ امکانش هست راهنمایی بفرمایید؟
اگه منظورتون androidX هست مطلب زیر رو مطالعه بفرمایید:
https://android-studio.ir/androidx-migration-guide
getSupportFragmentManager()
برای من وجود نداره مشکل کچاست؟
پوزش بابت تاخیر
مطمئن بشید داخل اکتیویتی کد میزنید که از Fragment ارث بری (extends) شده
آموزش ها عالی هست . بنده خودم از سایت خرید کردم راضی هستم .
واسه کسایی که از قبل در این حوزه فعالیت داشتند مثل بنده متوجهد میشن
فقط خیلی خوب بود اگه برای افراد کاملا مبتدی آموزش های جداگانه و ساده تر تهیه می شد .
لطف دارید دوست عزیز. ولی بعید میدونم از این ساده تر هم ممکن باشه
سلام.
implementation ‘com.android.support:design:27.0.2’
رو نمیشه به گردل اضافه کرد.
اگر میشه بگید چطور باید بنویسم با Androidx
و همین طور اگر بگیر چطور باید کتابخونه مناسب رو پیدا کنیم و چطور از ساپورت بیایم به اندروید ایکس، ممنون میشم.
زحمت بکشید روی نوار ” لطفا قبل از مطالعه مباحث آموزشی لیست تغییرات اندروید استودیو را بررسی فرمائید ” کلیک کنید
یه درگاه درست حسابی واسه پرداخت انتخاب میکرین
با کارت ملت پرداخت نمیکنه میگه محدود است
از درگاه کمکی استفاده کنید. به پرداخت هست
سلام درگاه کمکی هم ۴۰۴ میده
احتمالا مشکل مقطعی بوده
سلام . من توی نوشتن اپ از androidx استفاده کردم . کتابخانه material به جای design و appcompat رو هم وارد کردم . اما توی ساختن tab مشکل دارم و این خط که توی عکس زیر دورش خط کشیدم رونمیتونم اجرا کنم
http://8upload.ir/uploads/f07249938.png
فکر کنم فرمان توی androidx فرق داره .
محض اطلاع فرمان ViewPagerAdapter رو نمیشناسه و قرمز نشون میده
بعید میدونم مربوط به Androidx باشه. وقتی این رو مینویسید هیچ گزینه ای برای ایمپورت کردن نمیاد؟
آقا ممنون . مشکل حل شد . توی ساخت کلاس viewpageradapter یه حرف رو اشتباه نوشته بودم
سلام . من یه برنامه نوشتم و داخلش ۴ تا tab داره . داخل layout یکی از تب ها ویو های زیادی استفاده شده که حدود ۱۰۰۰ خط هستش . برا همین لود برنامه سنگین شده . میخواستم ببینم چه کاری میتونم انجام بدم که این لایوت رو بشه به چنتا لایوت تقسیم کرد و همزمان اجرا بشن روی یک تب . چنتا فرگمنت ایجاد کردم ولی تا اونجایی که تو ضیحات شما رو خوندم فرگمنت ها رو روی یه فرگمنت دیگه (که همون فرگمنت تب هست) .نمیشه گذاشت چون از appcompat استخراج نشده
بعید میدونم تقسیم کردن لیاوت بتونه تاثیر مثبتی داشته باشه. بالاخره در نهایت همه view ها اجرا میشه. نمونه سورس های رایگانی که تو وب هستند رو بررسی کنید ببینید لایه های سنگین به چه صورت پیاده سازی شده و یا اینکه چه راهکاری برای لود سریع درنظر گرفتن
با سلام من تب ویو ساختم و حالا میخوام برای هر تب یه فلاتینگ اکشت باتن بزارم ولی فلاتینگ اکشن باتن به زیر صقحه میره و دیده نمیشه راه حلش چیه؟
اینم عکساش برای درک بهتر حرفم
http://uupload.ir/files/kr5j_screenshot_۲۰۱۹۰۵۰۲-۰۱۱۰۳۷.png
اینم دومی . معلومه که فلاتینگ اکشن باتن بخاطر تب لیاوت مقداری رفته پایین راه چاره چیه ؟
http://uupload.ir/files/8tyo_screenshot_۲۰۱۹۰۵۰۲-۰۱۱۰۳۵.png
نتایج زیر رو چک کنید باید به جواب برسید:
http://bit.ly/2LhhnNJ
سلام
آیا راهی هست هنگام add کردن موارد در آرایه ، آیکون رو هم همونجا ست کرد یعنی تابعی به Adapter اضافه بشه که اینکار رو براساس شماره ایندکس و یا نام آیکون اضافه کنه ؟
با سلام
دوستانی که forceclose یا stop میشه پروژشون
باید داخل کد جاوای فرگمنت ها تمام رویدادها به جز onCreateView رو پاک کنن تا برنامه اجرا بشه
سلام
این اموزش رو دقیقا مثل کدهایی که اورده شده انجامش دادم ولی برای من forceclose کرد.نیاز به implement داشت.واسه همین در همون mainactivity که extends شده بود از appcompact این کد رو اضافه کردم و در ایمولیتر نشون داده شد.
public class MainActivity extends AppCompatActivity implements FragmentOne.OnFragmentInteractionListener ,FragmentTwo.OnFragmentInteractionListener, FragmentThree.OnFragmentInteractionListener{
…………………….
}
گفتم شاید دوستان همچنین مشکلی واسشون پیش اومده باشه
سلام
چطور میشه وقتی وارد برنامه بشیم تب انتخابی پیش فرض روی تب وسط باشه؟
کامنتهای قبلی رو بررسی کنید
با عرض سلام وتشکر به خاطر آموزش های شما
من می خواستم به زبان فارسی تب هارو بنویسم فقط میشه بگید چطوری وقتی که میخواهیم اولین بار وارد اپلیکیشن بشیم تب انتخابی روی تب سمت راستی باشه؟
باید برنامه تون رو راست چین کنید. سرچ کنید آموزش راست چین کردن اپ اندرویدی
سلام من تمامی کد ها رو زدم اما در قسمت ایمپورت کردن
import android.support.design.widget.TabLayout;
TabLayout رو نمیشناسه
کتابخانه های مورد نیاز رو داخل build.gradle اضافه کردین؟
سلام.
من برنامه ای دارم که مشابه آموزش شماست. appbar دارای قابلیت اسکرول هست و برای اینکه قسمت انتهایی viewpager قابل نمایش باشه یک ScrollingViewBehavior واسش نوشتم که پدینگ پایین ویوپیجر رو اصلاح می کنه. همه چیز درسته فقط نمی دونم چرا وقتی اسکرول می کنم (چه در شبیه ساز و چه در دیوایس) ، پدینگ پرش داره!!
سوالم رو (به همراه یک سوال جانبی) در استک آورفلو هم پرسیدم که البته هنوز جواب نداره.
اگه میشه راهنمایی کنید.
واسه ملاحضه ی رفتار :
https://stackoverflow.com/questions/51116794/viewpager-bottom-padding-skipping-with-custom-scrollingviewbehavior
یه فایل گیف هم از اتفاق مورد نظر آپ کردم اونجا.
ممنون
سلام
اقا من میخوام توی این تب بندی ها از دکمه استفاده بکنم
دقیق همونطور که توی مین اکتیویتی انجام میدم اینجا هم انجام بدم باید چه اموزشی ببینم ؟
دکمه بزارم و عملکرد تعریف بکنم
مباحث intent و fragment رو مطالعه بفرمایید
خداییش عالیه دستتون درد نکنه 😐
فقط آخرش شد مثل جدایی نادر از سیمین
کلا معلوم نشد چی شد :(((
دستتون درد نکنه خیلی دنبال تب بندی بودم و بالاخره اینجا پیداش کردم و خریدش کردم فوق العاده کاربردی و ارزون(بهتر بگم رایگان)
واقعا عالی بود.
ممنون بزرگوار
سلام من این سه تب رو ساختم الان می خوام تب رو فعال کنم یعنی کلیک که روی تب شد وصل بشه به قسمت پیام کاربر چه قطعه کدی رو نیاز داره
خیلی ممنون و متشکر.
آموزشتون خیلی هم کاربردی و گیرا هست. من با اینکه اکثر این مفاهیم رو تو فیلم های آموزشی هم دیده بودم ولی اینجا بهتر متوجه شدم. اکثر آموزش هاتون رو هم خریدم، برای اینکه کمک ناچیزی بشه به پیشرفت سایتتون.
متاسفانه عده ای اندک که درکی از فرهنگ ندارن، میان زیر این همه زحمت راحت یک کلام می نویسن آموزشتون بدرد نمی خوره، و گند می زنن به تمام زحمات نویسنده ی آموزش و امید کسانی که در حال یادگیری هستن رو خراب می کنن. همین امر هم باعث شده تولید علم و تولید محتوا تو کشور ما حتی تو سطوح بالای دانشگاهی تبدیل بشه به یه کپی و پیست ساده.
متشکر
ممنون از شما دوست عزیز. موفق باشید
با این آموزش مسخرتون.
برید به سایت های دیگه هم سربزنید بفهمید آموزش دادن یعنی چی
این چه آموزشیه دیگه؟؟؟
تا وسطاش رفتی ولش کردین؟
اصن فرگمنت هارو تعریف نکردین به جایی وصل نکردین!!
پس من برم بقیشو حدس بزنم
یکم دقت کنید میبینید فصل هشتم مربوط به فرگمنته که رایگانم هست. نیازی نیست حدس بزنید!
سلام من این برنامه رو نوشتم همون همش نرم افزار اجرا نشد و بسته شد . java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.abdollah.tabs2/com.example.abdollah.tabs2.MainActivity}: java.lang.ClassCastException: android.support.design.widget.CoordinatorLayout cannot be cast to android.support.v7.widget.Toolbar
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2434)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
at android.app.ActivityThread.access$900(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1347)
at android.os.Handler.dispatchMessage(Handler.java:102)
این خطاهایی که داد نمیدونم چیکارش کنم ؟
android.support.design.widget.CoordinatorLayout cannot be cast to android.support.v7.widget.Toolbar
اکتیویتی رو یه چک بکنید. ظاهرا برای تولبار، اشتباهی CoordinatorLayout رو cast کردین