Header Ads

[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:

Powered by Blogger.