[Android] Drawer Layout - Sliding menu
Tạo project và layout
1. Tạo
Project với tên “NavigationDrawerTest” và nên chọn version từ 4.0 trở lên như
hình
2.
Mở file layout chính lên và thay layout ngoài
cùng bằng DrawerLayout từ thư viện v4 (nếu chưa có thư viện thì chép thư viện
vào libs). Bên trong DrawerLayout sẽ có
một FrameLayout (làm phần nội dung chính để hiển thị ) và một ListView (dùng
làm phần bên trái) như source bên dưới.
<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">
<!-- View chinh chua noi dung
-->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- view ben trai, navigation
drawer, la listview -->
<ListView android:id="@+id/drawer_list"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
Trong giao diện trên ta phải lưu
ý 1 số điểm sau:
View chính chứa nội dung (Frame
Layout) cần phải là con đầu tiên trong DrawerLayout vì theo xml
thì thứ tự xml là thứ tự z (trên dưới) và nó phải nằm trên. Và nó có chiều rộng
và chiều cao là match_parent để khi phần drawer bị ẩn thì phần Frame Layout này
sẽ chiếm toàn bộ màn hình.
Phần Drawer view (ListView) cần
phải chỉnh layout_gravity theo horizontal. Để chạy từ Right-to-Left ta sẽ cho
giá trị của nó là “start”, để chạy từ Left-to-Right ta cho giá trị của nó là
“left”. Nó phải có thuộc tính layout_width là một số theo dp. Số này không lớn
hơn 320dp để người dùng luôn thấy một phần của view chính khi Drawer view hiện
ra.
Tạo nội dung cho Drawer List (ListView)
Phần Drawer List là phần listview ta có thể tạo nội dung
theo kiểu thông thường dùng dùng Adapter như ArrayAdapter, SimpleCursorAdapter…
. Ở đây để đơn giản ta dùng string array
3. Thêm
vào file “res/values/strings.xml” một string-array như bên dưới:
<string-array name="thanhpho">
<item>Sai Gon</item>
<item>Hue</item>
<item>Da Nang</item>
<item>Da Lat</item>
<item>Nha Trang</item>
</string-array>
4. Tạo
một file layout mới tên “drawer_list_item.xml” (trong thư mục layout). Đây dùng
làm layout cho một mục con trong listview. Có nội dung như sau:
<?xml version="1.0"
encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="#f00"
android:text="test ne"
/>
5. Mở
file java chính (MainActivity.java) khai báo các biến toàn cục. Chú ý: nhúng
thư viện android.support.v4.widget.DrawerLayout
String
[] danhsach;
DrawerLayout
drawerlayout;
ListView
listview;
6 . Trong
hàm onCreate ta ánh xạ các view, lấy tài nguyên, tạo adapter và gán vào
listview như sau:
drawerlayout= (DrawerLayout)findViewById(R.id.drawer_layout);
listview=(ListView)findViewById(R.id.drawer_list);
danhsach=getResources().getStringArray(R.array.thanhpho);
ArrayAdapter<String>
adapter =
new ArrayAdapter<String>(this,R.layout.drawer_list_item,danhsach);
listview.setAdapter(adapter);
Bắt sự kiện mở , đóng drawer
7. Chép
hình ic_drawer.png vào thư mục drawable. Đây là hình để click vào đóng/mở
drawer.
8. Mở
file “res/values/strings.xml” và bổ xung thêm 2 chuỗi dùng để làm text trên
actionbar.
<string name="drawer_open">Mo menu</string>
<string name="drawer_close">Dong menu</string>
9. Mở
file java chính khai báo thêm các biến toàn cục
ActionBarDrawerToggle
drawertoggle;
String
drawertitle;
String title;
10. Sau
lệnh setadapter trong onCreate viết thêm như bên dưới.
title=drawertitle=(String) getTitle();
drawertoggle=new ActionBarDrawerToggle(
this, //ap vao activity nao
drawerlayout, //drawerlayout
R.drawable.ic_drawer,//icon
R.string.drawer_open, //chuoi mo
R.string.drawer_close
/*chuoidong*/
)
{
//goi khi drawer da
hoan tat close
@Override
public void onDrawerClosed(View drawerView)
{
// TODO Auto-generated method stub
super.onDrawerClosed(drawerView);
getActionBar().setTitle(title);
}
//goi khi drawer da
hoan tat open
@Override
public void onDrawerOpened(View drawerView)
{
// TODO Auto-generated method stub
super.onDrawerOpened(drawerView);
getActionBar().setTitle("chon thanh pho");
}
};
//co lenh nay moi
thuc hien duoc ham onDrawerClosed va onDrawerOpened
drawerlayout.setDrawerListener(drawertoggle);
11. Chạy
chương trình, dùng chuột đưa gần cạnh trái và kéo qua phải để thấy kết quả
(hình đã sửa text của listview thành màu trắng cho đẹp).
Điều khiển menu khi drawer open/close
Ta có thể điều khiển menu tùy
theo trạng thái của drawer là mở hay đóng
12.
Mở file res/menu/main.xml bổ sung thêm 1 item
như sau:
<item
android:id="@+id/action_test"
android:orderInCategory="100"
android:showAsAction="never"
android:title="action_test"/>
13.
Trong 2 hàm onDrawerClosed và onDrawerOpened bổ
sung thêm lệnh invalidateOptionsMenu, lệnh này báo rằng menu cần phải thay đổi
và nó sẽ chạy hàm onPrepareOptionsMenu.
public void onDrawerClosed(View drawerView)
{
// ………………………………………
//bao menu da thay
doi can tao lai
//no se goi
onPrepareOptionsMenu
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView)
{
//…………………………
invalidateOptionsMenu();
}
14.
Bên ngoài hàm onCreate , override lên phương thức
onPrepareOptionsMenu. Tạo ra biến boolean và đọc trạng thái của Drawer xem đang
mở hay đóng. Sau đó kiếm đến menu Setting bằng hàm findItem và setVisible để ẩn/hiện
menu đó.
@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
// TODO Auto-generated method stub
boolean dangmo=drawerlayout.isDrawerOpen(listview);
menu.findItem(R.id.action_test).setVisible(!dangmo);
return super.onPrepareOptionsMenu(menu);
}
15. Chạy
chương trình, nhấn nút menu để thấy có menu có mục “action_test” hiện ra. Kéo
Drawer và nhấn nút menu để thấy không có menu “action_test”.
Ẩn hiện Drawer bằng icon của chương trình
Ta
thấy rằng có thể kéo Drawer nhưng chưa nhấn icon để ẩn hiện Drawer được. Thực
hiện tiếp
16. Trong onCreate dưới cùng viết thêm lệnh bên dưới, 2 lệnh
này giúp cho nút home hiện ra trên thanh actionbar (có thể nhấn vào nó).
//hien nut home len
goc trai cua actionbar
getActionBar().setHomeButtonEnabled(true);
//nhan nut home tra ve 1 level chu khong
ve top level
getActionBar().setDisplayHomeAsUpEnabled(true);
17. Bên
ngoài hàm onCreate, override lên hàm onOptionsItemSelected để điều khiển các
item của actionbar.
@Override
public boolean onOptionsItemSelected(MenuItem
item) {
// TODO Auto-generated method stub
if(drawertoggle.onOptionsItemSelected(item))
return true;
//....dieu kien cac
action bar item khac
return super.onOptionsItemSelected(item);
}
Tạo fragment cho listview item
Tiếp
theo ta xây fragment để khi click vào các listview item sẽ đổi fragment.
18. Tạo một layout mới cho fragment tên
“fragment_layout.xml” trong thư mục “/res/layout/” như sau:
<?xml version="1.0"
encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<TextView
android:id="@+id/tv_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:textSize="40sp"
android:text="test"
/>
</LinearLayout>
19. Tạo một file java mới tên CityFragment.java. Cho Class
kế thừa từ Fragment, nhúng thư viện support.v4
. Trong class ta override lên
onCreateView như sau:
public class CityFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater
inflater,
ViewGroup container,Bundle savedInstanceState)
{
// TODO Auto-generated method stub
return super.onCreateView(inflater,
container, savedInstanceState);
}
}
20. Trong
hàm onCreate viết như sau:
@Override
public View onCreateView(LayoutInflater
inflater, ViewGroup container,
Bundle
savedInstanceState) {
// TODO Auto-generated method stub
//lay doi so co
key la "vitri" (ben ngoai truyen vo)
chinh la item
//tren listview duoc
chon
int vitri =getArguments().getInt("vitri");
String
[] dsthanhpho= getResources().getStringArray(R.array.thanhpho);
View
view=inflater.inflate(R.layout.fragment_layout,container, false);
TextView
tv=(TextView)view.findViewById(R.id.tv_content);
tv.setText(dsthanhpho[vitri]);
getActivity().getActionBar().setTitle(dsthanhpho[vitri]);
return view;
}
21. Quay
về file java chính. Sửa MainActivity kế thừa từ FragmentActivity
public class MainActivity extends
FragmentActivity {
22. Trong
hàm onCreate cuối cùng bắt thêm sự kiện khi click vào mục con của listview như
sau:
listview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?>
arg0, View arg1, int position,
long arg3) {
// TODO Auto-generated method stub
String []
dstp=getResources().getStringArray(R.array.thanhpho);
title=dstp[position];
CityFragment
fragment=new CityFragment();
Bundle
data=new Bundle();
data.putInt("vitri", position);
fragment.setArguments(data);
FragmentManager
manager=getSupportFragmentManager();
FragmentTransaction
tran=manager.beginTransaction();
tran.replace(R.id.content_frame, fragment);
tran.commit();
drawerlayout.closeDrawer(listview);
}
});
23. Chạy
chương trình, kéo drawer click vào các item để xem kết quả.
No comments: