標籤:android drawerlayout 抽屜
如何?android中的抽屜效果?
1.建立xml檔案
其根視圖是<android.support.v4.widget.DrawerLayout/>
這個xml分為兩部分,一部分是主要內容的視圖,一部分是抽屜的視圖。
主要內容視圖一般是FrameLayout,一定要是DrawerLayout的第一個視圖,其高度和父視圖的高度匹配。
抽屜視圖一般是ListView,在寫抽屜視圖的時候要注意
1.寬度一般要小於320dp
2.android:layout_gravity屬性是確定抽屜的位置
當該屬性為left/start時,位於左邊
當該屬性為right/end時,位於右邊
推薦使用start/end
3.android:choiceMode = “singleChoice”
4.android:divider 以及 android:dividerHeight
<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" > </FrameLayout> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:background="#ffffcc" android:divider="@android:color/transparent" android:dividerHeight="0dp" > </ListView></android.support.v4.widget.DrawerLayout>
將這個xml檔案部署到模擬器上,就能看到一個簡單的效果:
2.為抽屜新增內容:
因為抽屜視圖裡是ListView,所以要用到Adapter
在Activity中聲明各種組件及所使用到的list,adapter
public class MainActivity extends Activity {private DrawerLayout mDrawerLayout;private ListView mDrawerList;private ArrayList<String> mList;private ArrayAdapter<String> adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);mDrawerList = (ListView) findViewById(R.id.left_drawer);// 初始化mlistmList = new ArrayList<String>();for (int i = 0; i < 5; i++) {mList.add("Item--->" + (i + 1));}// 初始化adapter// 適配器資料填充adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mList);mDrawerList.setAdapter(adapter);}}
3.監聽左側ListView
現在點擊左側抽屜欄沒有什麼效果,需要為左側的LiseView設定監聽器(onItemClickListener)並實現onItemClick方法
當點擊左側抽屜裡的功能表項目時,在右邊主視圖內動態插入一個Fragment
需要建立一個class content_fragment繼承Fragment,並重寫onCreateView方法,返回inflater.inflate 方法產生的view
public class content_fragment extends Fragment {private TextView textView;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// inflater.inflate(resource, root, attachToRoot)View view = inflater.inflate(R.layout.fragment_content, container,false);textView = (TextView) view.findViewById(R.id.textView);// 接收傳遞過來的參數,並顯示到textView中String text = getArguments().getString("text");textView.setText(text);return view;}}
inflater.inflate(resource, root, attachToRoot)
Inflate的作用只是將xml定義的一個布局找出來
參數1:要載入的xml資源檔,載入出錯拋出InflateException
參數2:新產生視圖的父層
如果第三個參數attachToRoot為true,就將這個root作為根對象返回,否則僅僅將這個root對象的LayoutParams屬性附加到resource對象的根布局對象上,也就是布局檔案resource的最外層的View上,比如是一個LinearLayout或者其它的Layout對象。
當點擊左側抽屜內的某一功能表項目的時候需要為將要填充到FragmentLayout中的Fragment傳遞資料,通過Fragment的setArguments (Bundle )方法。
建立的Fragment中調用getArguments.getXX()方法即可獲得傳遞過來的資料。
// 設定監聽器mDrawerList.setOnItemClickListener(this);@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// 動態插入一個Fragment到右側Fragment contentFragment = new content_fragment();Bundle bundle = new Bundle();bundle.putString("text", mList.get(position));// 傳遞資料contentFragment.setArguments(bundle);FragmentManager fm = getFragmentManager();fm.beginTransaction()// 開啟一個事務.replace(R.id.content_frame, contentFragment)// 建立的視圖替換掉原來的視圖,將contentFragment填充到右側.commit();// 當點擊了左側抽屜裡的某一功能表項目時,視圖會跳轉到右側顯示contentFragment,這時候,左側抽屜需要隱藏了mDrawerLayout.closeDrawer(mDrawerList);}
這時候在模擬器中啟動並執行話,點擊左側某一功能表項目就會在右側顯示相應的視圖。
點擊Item--->3
4.監聽抽屜的開啟關閉
為DrawerLayout設定監聽器,當抽屜開啟/關閉的時候頂部的title會出現變化。
通常設定監聽有兩種方法:
1.DrawerLayout.setDrawerListener (DrawerLayout.DrawerListener)
2.如果Activity中包含了ActionBar,可以直接使用ActionBarDrawerToggle這個類,這個類是DrawerListener的子類
a) 改變android.R.id.home表徵圖
b) Drawer拉出或隱藏的時候帶有動畫效果 (syncState())
c) 可以監聽Drawer拉出、隱藏事件
覆寫ActionBarDrawerToggle的onDrawerOpened()和onDrawerClosed()以監聽抽屜拉出或隱藏
當使用ActionBarDrawerToggle時 覆寫Activity的onPostCreate 和onConfigurationChanged方法
public class MainActivity extends Activity implements OnItemClickListener {private DrawerLayout mDrawerLayout;private ListView mDrawerList;private ArrayList<String> mList;private ArrayAdapter<String> adapter;private ActionBarDrawerToggle mDrawerToggle;private String mTitle;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTitle = (String) getTitle();mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);mDrawerList = (ListView) findViewById(R.id.left_drawer);// 初始化mlistmList = new ArrayList<String>();for (int i = 0; i < 5; i++) {mList.add("Item--->" + (i + 1));}// 初始化adapter// 適配器資料填充adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mList);mDrawerList.setAdapter(adapter);// 設定監聽器mDrawerList.setOnItemClickListener(this);mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer, // 應用左上方的表徵圖R.string.drawer_open, R.string.drawer_close) {// 覆寫 抽屜開啟/關閉時調用的方法@Overridepublic void onDrawerOpened(View drawerView) {super.onDrawerOpened(drawerView);// 當抽屜開啟的時候,頂部顯示的標題getActionBar().setTitle("請選擇");}@Overridepublic void onDrawerClosed(View drawerView) {super.onDrawerClosed(drawerView);// 當抽屜關閉的時候,顯示的標題getActionBar().setTitle(mTitle);}};mDrawerLayout.setDrawerListener(mDrawerToggle);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// 動態插入一個Fragment到右側Fragment contentFragment = new content_fragment();Bundle bundle = new Bundle();bundle.putString("text", mList.get(position));// 傳遞資料contentFragment.setArguments(bundle);FragmentManager fm = getFragmentManager();fm.beginTransaction()// 開啟一個事務.replace(R.id.content_frame, contentFragment)// 建立的視圖替換掉原來的視圖,將contentFragment填充到右側.commit();// 當點擊了左側抽屜裡的某一功能表項目時,視圖會跳轉到右側顯示contentFragment,這時候,左側抽屜需要隱藏了mDrawerLayout.closeDrawer(mDrawerList);}}
5.在右上方添加一個表徵圖,這個表徵圖其實是optionmenu
修改main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context="com.example.drawerlayoutbymyself.MainActivity" > <item android:id="@+id/action_websearch" android:icon="@drawable/web_search" android:showAsAction="ifRoom|withText" android:title="webSearch"/></menu>
當抽屜開啟或是隱藏的時候需要重繪功能表項目,需要有onCreateOptionsMenu方法
@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.getMenuInflater().inflate(R.menu.main, menu);return true;}
在mDrawerToggle的監聽事件中 添加invalidateOptionsMenu()方法
當調用該方法時,系統會自動調用onPrepareOptionsMenu方法,需要重寫該方法
@Overridepublic boolean onPrepareOptionsMenu(Menu menu) {// 抽屜是否被開啟boolean isDrawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);menu.findItem(R.id.action_websearch).setVisible(!isDrawerOpen);return super.onPrepareOptionsMenu(menu);}
這個時候,當抽屜開啟或隱藏的時候,螢幕右上方的表徵圖也會發生相應的變動。但是點擊這個表徵圖是沒有任何反應的。需要覆寫 onOptionsItemSelected方法
@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case R.id.action_websearch:Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");Uri uri = Uri.parse("http://www.baidu.com");intent.setData(uri);startActivity(intent);break;default:break;}return super.onOptionsItemSelected(item);}
這時候點擊右上方的表徵圖時,會呼叫瀏覽器開啟百度首頁。
完整代碼:
public class MainActivity extends Activity implements OnItemClickListener {private DrawerLayout mDrawerLayout;private ListView mDrawerList;private ArrayList<String> mList;private ArrayAdapter<String> adapter;private ActionBarDrawerToggle mDrawerToggle;private String mTitle;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTitle = (String) getTitle();mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);mDrawerList = (ListView) findViewById(R.id.left_drawer);// 初始化mlistmList = new ArrayList<String>();for (int i = 0; i < 5; i++) {mList.add("Item--->" + (i + 1));}// 初始化adapter// 適配器資料填充adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mList);mDrawerList.setAdapter(adapter);// 設定監聽器mDrawerList.setOnItemClickListener(this);mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer, // 應用左上方的表徵圖R.string.drawer_open, R.string.drawer_close) {// 覆寫 抽屜開啟/關閉時調用的方法@Overridepublic void onDrawerOpened(View drawerView) {super.onDrawerOpened(drawerView);// 當抽屜開啟的時候,頂部顯示的標題getActionBar().setTitle("請選擇");// 重繪功能表項目,會自動調用 onPrepareOptionsMenu(),要重寫該方法invalidateOptionsMenu();}@Overridepublic void onDrawerClosed(View drawerView) {super.onDrawerClosed(drawerView);// 當抽屜關閉的時候,顯示的標題getActionBar().setTitle(mTitle);// 重繪功能表項目invalidateOptionsMenu();}};mDrawerLayout.setDrawerListener(mDrawerToggle);}@Overridepublic boolean onPrepareOptionsMenu(Menu menu) {// 抽屜是否被開啟boolean isDrawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);menu.findItem(R.id.action_websearch).setVisible(!isDrawerOpen);return super.onPrepareOptionsMenu(menu);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// 動態插入一個Fragment到右側Fragment contentFragment = new content_fragment();Bundle bundle = new Bundle();bundle.putString("text", mList.get(position));// 傳遞資料contentFragment.setArguments(bundle);FragmentManager fm = getFragmentManager();fm.beginTransaction()// 開啟一個事務.replace(R.id.content_frame, contentFragment)// 建立的視圖替換掉原來的視圖,將contentFragment填充到右側.commit();// 當點擊了左側抽屜裡的某一功能表項目時,視圖會跳轉到右側顯示contentFragment,這時候,左側抽屜需要隱藏了mDrawerLayout.closeDrawer(mDrawerList);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case R.id.action_websearch:Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");Uri uri = Uri.parse("http://www.baidu.com");intent.setData(uri);startActivity(intent);break;default:break;}return super.onOptionsItemSelected(item);}}
6.在左上方添加一個表徵圖,當使用者點擊表徵圖時,能夠開啟抽屜
在MainActivity的onCreate方法中添加代碼:
// 開啟ActionBar上APP ICON功能getActionBar().setDisplayHomeAsUpEnabled(true);getActionBar().setHomeButtonEnabled(true);
這個時候如果部署到模擬器的話,就會發現在左上方有一個返回的表徵圖,但是點擊沒有任何效果
// 將ActionBar上的表徵圖與Drawer結合起來if (mDrawerToggle.onOptionsItemSelected(item)) {return true;}
在onOptionsItemSelected方法中添加一個判斷,左上方的表徵圖也是一個 menu item
這時候 點擊左上方的表徵圖 可以開啟抽屜,並且左上方表徵圖還有動畫效果
最終Activity代碼:
public class MainActivity extends Activity implements OnItemClickListener {private DrawerLayout mDrawerLayout;private ListView mDrawerList;private ArrayList<String> mList;private ArrayAdapter<String> adapter;private ActionBarDrawerToggle mDrawerToggle;private String mTitle;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mTitle = (String) getTitle();mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);mDrawerList = (ListView) findViewById(R.id.left_drawer);// 初始化mlistmList = new ArrayList<String>();for (int i = 0; i < 5; i++) {mList.add("Item--->" + (i + 1));}// 初始化adapter// 適配器資料填充adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mList);mDrawerList.setAdapter(adapter);// 設定監聽器mDrawerList.setOnItemClickListener(this);mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer, // 應用左上方的表徵圖R.string.drawer_open, R.string.drawer_close) {// 覆寫 抽屜開啟/關閉時調用的方法@Overridepublic void onDrawerOpened(View drawerView) {super.onDrawerOpened(drawerView);// 當抽屜開啟的時候,頂部顯示的標題getActionBar().setTitle("請選擇");// 重繪功能表項目,會自動調用 onPrepareOptionsMenu(),要重寫該方法invalidateOptionsMenu();}@Overridepublic void onDrawerClosed(View drawerView) {super.onDrawerClosed(drawerView);// 當抽屜關閉的時候,顯示的標題getActionBar().setTitle(mTitle);// 重繪功能表項目invalidateOptionsMenu();}};mDrawerLayout.setDrawerListener(mDrawerToggle);// 開啟ActionBar上APP ICON功能getActionBar().setDisplayHomeAsUpEnabled(true);getActionBar().setHomeButtonEnabled(true);}@Overridepublic boolean onPrepareOptionsMenu(Menu menu) {// 抽屜是否被開啟boolean isDrawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);menu.findItem(R.id.action_websearch).setVisible(!isDrawerOpen);return super.onPrepareOptionsMenu(menu);}@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {// 動態插入一個Fragment到右側Fragment contentFragment = new content_fragment();Bundle bundle = new Bundle();bundle.putString("text", mList.get(position));// 傳遞資料contentFragment.setArguments(bundle);FragmentManager fm = getFragmentManager();fm.beginTransaction()// 開啟一個事務.replace(R.id.content_frame, contentFragment)// 建立的視圖替換掉原來的視圖,將contentFragment填充到右側.commit();// 當點擊了左側抽屜裡的某一功能表項目時,視圖會跳轉到右側顯示contentFragment,這時候,左側抽屜需要隱藏了mDrawerLayout.closeDrawer(mDrawerList);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.main, menu);return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {// 將ActionBar上的表徵圖與Drawer結合起來if (mDrawerToggle.onOptionsItemSelected(item)) {return true;}switch (item.getItemId()) {case R.id.action_websearch:Intent intent = new Intent();intent.setAction("android.intent.action.VIEW");Uri uri = Uri.parse("http://www.baidu.com");intent.setData(uri);startActivity(intent);break;default:break;}return super.onOptionsItemSelected(item);}@Overrideprotected void onPostCreate(Bundle savedInstanceState) {super.onPostCreate(savedInstanceState);// 需要將ActionDrawerToggle與DrawerLayout的狀態同步// 將ActionBarDrawerToggle中的drawer表徵圖,設定為Home-Button iconmDrawerToggle.syncState();}@Overridepublic void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);mDrawerToggle.onConfigurationChanged(newConfig);}}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android---62---DrawerLayout實現抽屜效果