استفاده از اسلایدینگ منو + Navigation Drawer دست ساز و خانگی (آموزش)
آموزش ویدئویی مخصوص ساخت ActionBar بهمراه Navigation Drawer را از لینک زیر دریافت کنید .
سلام.
چند روز پیش یکی از دوستان نحوه ایجاد یه Navigation Drawer یا همون منوی بقل رو میخواست یاد بگیره که قرار شد براش یه تاپیک کامل بزنم .
روش های ایجاد یک Navigation Drawer یا Sliding Menu به شرح ذیل هست :
استفاده از لایبری های آماده ، که نمونه هایییش رو در زیر براتون قرار دادم .
nicolasjafelle/SherlockNavigationDrawer
اگر در گوگل سرچ هم بزنید بیشتر هم وجود داره .
روش دوم ساخت یک Navigation Drawer هست با استفاده از کتابخانه خود اندروید و به صورت دست ساز.
خوب در آموزش های استاد آقاجانی استفاده از این نوع لایبری ها که آماده هستن داده شده ، پس ما آموزش ساخت یک Navigation Drawer دست ساز رو میدیم .
برای ساخت این منو ابتدا لایبری ساپورت ورژن 4 رو به پروژه اضافی میکنیم .
بعد یک لایه جدید در ریسورس هاتون اضافی کنید مثلا به اسم main_root.xml
حالا یک لایه دیگه به نام main.xml و یک لایه دیگه هم به نام navigation_drawer.xml
حالا به ترتیب براتون میگم که این لایه ها دقیقا چیه .
ابتدا لایه main.xml داخل این لایه میتونید صفحه بندی هاتون روانجام بدید دقیقا این همون لایه ای هست که همیشه ما توش UI رو درست میکنیم یا به عبارتی لایه Activity .
لایه navigation_drawer.xml هم لایه مربوط به منو شماست که با توجه به نیازی که دارید طراحی میکنید .
خب تا اینجاش ما کار خاصی انجام ندادیم و فقط لایه هامون رو درست کردیم ، در navigation_drawer layout یه نکته وجود داره و اون این هست که شما باید در لایه ی پدر بهش gravity بدید مثل کد زیر :
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="@dimen/sliding_menu_width" android:layout_height="match_parent" /////////////////////////////////////// android:layout_gravity="left" android:layout_marginLeft="20dp" android:background="#2a2a2a" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="48dp" android:background="#be2f23" android:orientation="vertical" > <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerInside" android:src="@drawable/menu" /> </LinearLayout> <ListView android:id="@+id/lst" android:layout_width="match_parent" android:layout_height="wrap_content" tools:listitem="@layout/view_category" > </ListView> </LinearLayout>
خب همونطور که در کد بالا مشخصه ما به لایه پدر یه gravity دادیم این مقدار برای این هست که مشخص کنیم منوی ما از کدوم ور باید بیاد ینی منو سمت راست باشه یا سمت چپ .
میریم سراغ main_root.xml ، شبیه به چسب عمل میکنه و 2 لایه دیگه رو به هم میچسبونه .
داخل این لایه ما از یک DrawerLayout استفاده میکنیم نحوه استفاده هم به شکل زیر هست .
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" > <include layout="@layout/main" /> <include layout="@layout/navigation_drawer " /> </android.support.v4.widget.DrawerLayout>
خب توجه داشته باشید که همونطور که قبلا هم گفته شد شما باید از لایبری ساپورت ورژن 4 استفاده کنید .
خب اینجا 2 تا خط داریم که یکم نامهوم شاید باشه
<include layout="@layout/main" /> <include layout="@layout/navigation_drawer " />
اولین خط لایه main و دومین خط لایه navigation_drawer رو داخل لایه main_root اصطلاحا include میکنه یا میاره توش .
خب کار ما تموم شد با xml میریم سراغ کد نویسی
داخل کلاس اکتیویتی مربوطه شما باید به جای اینکه
setContentView(R.layout.main);
مینویسید
setContentView(R.layout.main_root);
و با استفاده از کد زیر Drawer Layout رو بهش معرفی میکنیم :
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
البته این معرفی هیچ لزومی نداره همین الان شما میتونید با بردن انگشت به گوشه صفحه ، منو خودتون رو باز کنید ولی ما میخوایم یکم قشنگ تر کار کنیم و یه دکمه هم تعریف کنیم که وقتی روش کلیک شد منو باز و بسته بشه :)
حالا یه دکمه تعریف میکنیم و براش Onclick رو Override میکنیم و کد زیر رو توش منویسیم :
btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(drawerLayout.isDrawerOpen(Gravity.LEFT)){ drawerLayout.closeDrawers(); }else { drawerLayout.openDrawer(Gravity.LEFT); } } });
خوب توضیح کد بالا هم بدیم که دیگه کار تمومه ، if(drawerLayout.isDrawerOpen(Gravity.LEFT)) یعنی اگر منو باز بود با استفاده از این کد ببندش drawerLayout.closeDrawers(); و در غیر این صورت با استفاده از این کد زیر بازش کن :
drawerLayout.openDrawer(Gravity.LEFT);
یه نکته باقی میمونه داخل کدی که برای باز کردن یا بستن استفاده کردیم یه پرانتز هست که توش نوشتیم Gravity.LEFT، این یعنی منوی ما از کدوم سمت باز شده یا باید بشه .
پس داخل پرانتز همیشه مقدارش برابر جهت منوی شما هست که سمت چپ قرار داره یا راست .
آخر سر شما هم چین چیزی دارید :
موفق و سربلند باشید :)
من از روشی که در مستندات گوگل هست استفاده کردم به نظرم روش شما آسونتره حالا چند تا سئوال دارم:
من لایه ی مربوط به navigation_drawer.xml به این صورت تعریف کردم:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="@+id/drawer_list"
android:layout_width="220dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#BfE4F1FE" />
</android.support.v4.widget.DrawerLayout>
در آموزش های گوگل از فرگمنت استفاده کرده و من برای اینکه بتونم لایه ی اکتیویتی اصلی رو زیر منوی کشویی نشون بدم ،در اکتیویتی اصلی که از کلاس NavigationDrawer ارث بری شده از کد زیر استفاده کردم:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frameLayout = (FrameLayout)findViewById(R.id.content_frame);
View activityView = G.inflater.inflate(R.layout.main_layout, null,false);
frameLayout.addView(activityView)
اکتیویتی اصلی به عنوان یه هدایتگر به بخش های مختلف استفاده میشه ولی در این حالت با انتخاب هر اکتیویتی که با دیتابیس سروکار داره برنامه کرش میکنه علت از کجا میتونه باشه؟
سئوال2 : کاربرد این کدها چیه؟
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
سئوال 3: برای اینکه در روش شما navigationDrawer روی ActionBar قرار نگیره باید چیکار کرد؟
دوستانی که دوست دارند اسلادینگ منوشون به شکل زیر باشه میتونن از روش زیر که لینکش رو گذاشتم استفاده کنن :
با سلام دوستان من آموزش sliding رو طبق کلیپ پیش رفتم میخوام بهش 3تا tabاضافه کنم ممنون میشم کمکم کنین و بگین چه کدهایی رو کجا برنامه وارد کنم ممنون میشم
برای من ارور
DrawerLayout must be measured with MeasureSpec.EXACTLY.
Exception details are logged in Window > Show View > Error Log
میده چجوری حلش کنم؟ممنون.
من فیلم اموزشی ساخت sliding menu شما رو دیدم و کاملا بدون مشکل پیاده سازی کردم.فقط یه مشکله کوچکی وجود داره به اینصورت که با زدن دکمه به درستی باز و بسته میشه و با دست هم تا زمانی که دستمان را از روی صفحه نکشیده ایم به سمت مورد نظر میتونیم بکشیم اما وقتی باز هست نمیدونم چرا نمیشه به طرف داخل با دست کشید و تنها زمانی بسته میشه که در یک جای صفحه تاچ میشه.
با سلام
من از slidingmenu که شما آموزش دادین استفاده کردم مشکلی هم نداره
حالا یکی از منوها کاربر را به صفحه ای منتقل میکنه که دیزاین تون صفحه مثل تب های واتس اپ است که با کشیدن به چپ و راست محتوای همون fragmnet را نشان میده ولی از این خط ایراد میگیره
اگر از این راه برم صفحه به چپ و راست کشیده میشه ولی منو ها را نشان نمیده
viewPager = (ViewPager) findViewById(R.id.viewPager);
tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(tabsAdapter);
ولی وقتی از کد زیر استفاده میکنم این خط را error میده actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS
این هم کد کل صفحه :
package view;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
public class HomePageActivity extends FragmentActivity implements ActionBar.TabListener {
private ViewPager viewPager;
private ActionBar actionBar;
private TabsFragmentPagerAdapter tabsAdapter;
private String[] days = new String[]{ "menu1", "menu2", "menu3", "menu4", "menu5", "menu6", "menu7", "menu8", "menu9" };
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.home_activity);
/* viewPager = (ViewPager) findViewById(R.id.viewPager);
tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(tabsAdapter);*/
tabsAdapter = new TabsFragmentPagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setAdapter(tabsAdapter);
actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (int i = 0; i < 9; i++) {
actionBar.addTab(actionBar.newTab().setText(days[i]).setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int arg) {
// TODO Auto-generated method stub
actionBar.setSelectedNavigationItem(arg);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
});
}
@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);
return true;
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
}
با توجه به اینکه اگر از library که استاد اموزش دادند استفاده کنم مشکلی پیش نمیاد ولی بدلیل سرعت و حجم کم ترجیح میدم از آموزش شما استفاده کنم
و سوال بعدی این هست که برای ساخت پروژه از اندروید 2.2 استفاده کردم ولی بعد از اضافه کردن library که شما معرفی کردید
(android-support-v7-appcompat) وقتی که توی قسمت properties پروژه نگاه میکنم تبدیل شده به اندورید 4 و اگر تغییر بدم به error بر میخورم وقتی که برنامه را روی نسخه اندروید 2.2 نصب کردم متوجه شدم ، برای این شکل چه راه حلی دارید؟؟
سلام
آقای کاشی زاده ممنون از آموزش خوبتون
من طبق همین آموزش شما اسلایدینگ منو را میسازم و به خوبی اجرا میشه ولی یک مشکلی داره اون هم این که وقتی اسلایدینگ منو باز هست و روی یک جای خالی از لایه اسلایدینگ منو کلیک میکنم روی آیتم هایی که زیر اون لایه یعنی روی صفحه اصلی هست کلیک میشه
چطور باید این مشکل را برطرف کنم؟
سلام و خسته نباشید به خاطر ویدئوی مفیدتون. خب الان یه سوال برام پیش اومده. میخوام بدونم من توی اسلاید منو اومدم چند آیتم انتخاب کردم که با زدن اون آیتم ها اکتیویتی های مربوط به اون باز بشن. الان من چطور باید اینکار رو انجام بدم؟ چون آقای آقاجانی هم در این مورد چیزی نگفتن.
سلام دوستان . من دارم رو یه پروژه کار می کنم که صفحاتش fragement هستند . دوتا sliding menu پیدا کردم روی اکتیویتی هایی که از Activity ارث بری می کنند درست کار میکنن ولی روی fragement ها نه .
مثلا یکی از این sliding menu ها توی این خط ارور میده و هرکاری کردم مشکلش حل نشد :
کسی راه حل رو میدونه ؟
menu.attachtoActivity();
و واسه اسلایدمنو آیتم هایی قرار دادم و طبق گفته ی شما توی همون اکتیویتی که اسلایدمنو رو ساختم واسش رویداد کلیک قرار دادم. طبق کد زیر:
LinearLayout layout_home = (LinearLayout) findViewById(R.id.layout_home);
layout_home.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent(getApplicationContext(), ActivitySecond.class);
startActivity(intent);
}
});
layout_home در واقع یه Linear Layout هست که شامل آیکون و عنوان آیتم هست. ولی اجرا کردم به فورس کلوز انجامید.
با تشکر از آقای کاشی زاده اگه براتون ممکن ایجاد اسلاید منو در چند صفحه رو یه مثال بزنید ممنون میشم
با سلام خدمت جناب کاشی زاده - با تشکر از آموزشتون - من پروژه را موفق اجرا کردم اما میخواهم نویگیشن منو از سمت راست باز بشه
سلام و خسته نباشید - چطور میشه وقتی نویگیشن منو باز میشه روی اکشن بار بیفته ؟ با تشکر
سلام . من عین فیلم رفتم اما چندتا مشکل دارم .
1- در اکشن بار طبق تصویر از دو طرف خالی میمانه. و چون از اندروید استودیو استفاده میکنم اکشن بار پیش فرض پشتش میمانه. اینو چ کنم ؟
2- اسلایدینگ منو اصلا حرکت نمیکنه و با اجرای برنامه باز میمانه و بسته نمیشه .
3- وقتی روی دکمه کلیک میکنم بسته ک نمیشه هیچ ، کرش میکنه.
البته لازم بذکر است اون لایبریی ها را اظافه نکردم چون در اندروید استودیو AppCompad وجود داشت بطور پیش فرض.
آقای کاشی زاده و دوستان وقت بخیر
من تمام کامنت ها و پاسخ ها رو خوندم تمام اینا که گفته شد درباره ورژن 2 هست حالا اگه همون ابتدا بخوایم از ورژن 4 استفاده کنیم و نیاز به اضافه کردن کتابخونه نباشه باید چطور یه drawer menu بسازیم؟
یکم راهنمایی و یا یه آموزش معرفی میکنید درباره این کار در ورژن 4
تشکر
سلام ممنون آقای کاشی زاده بابت آموزشتون
فقط یه مشکل اساسی من فرم rootاز main و slidingmenu ارث میبرد این تا اینجا . حالا میخوام روی main و sliding menu دکمه تعریف کنم که با کلیک روی آن عملیات خاص خود را انجام دهد . من آمدم و در xml های مربوطه دکمه ها را گذاشتم حالا کداشونا مثلا main تو اکتیویتیه خودش بذارم اجرا نمیشه باید چکار کنم ؟
در لایبری استاد برای jfeinstein قابلیت TOUCH_MODE وجود داشت که میشد مقدار حساسیت رو برای SlidingMewnu رو مقداری برابر FullScreen قرار داد در DrawerLayout میتونید این مقدار رو به دلخواه تغییر بدید :
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
try {
Field mDragger = drawerLayout.getClass().getDeclaredField("mLeftDragger");//mRightDragger or mLeftDragger based on Drawer Gravity
mDragger.setAccessible(true);
ViewDragHelper draggerObj = (ViewDragHelper) mDragger.get(drawerLayout);
Field mEdgeSize = draggerObj.getClass().getDeclaredField("mEdgeSize");
mEdgeSize.setAccessible(true);
int edge = mEdgeSize.getInt(draggerObj);
mEdgeSize.setInt(draggerObj, edge * 3); //any int value you want
} catch (Exception e) {
e.printStackTrace();
}
سلام آقای کاشی زاده و ممنون بابت آموزشهای خوبتون
من یه مشکلی دارم در اجرای اسلاید منوها؛ وقتی روی منوی سمت چپ کلیک میکنم خود به خود بسته میشه!
این طور امتحان کنید
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<include layout layout="@layout/main"/>
<include layout layout="@layout/menu"/>
</android.support.v4.widget.DrawerLayout>
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .