在以前ActionBar是Android 4.0的獨有的,後來的ActionBarSherlock的獨步武林,對了還有SlidingMenu,但是這個可以對4.0下的可以做很好的適配。自從Google Io大會(去年的,今年過幾天也要開始了)。
看知乎日報,豆瓣這些應用明顯感覺到Android Design的風格。
效果
image
左側是可以滑出來的SlidingMenu,後面的則是我們的內容視圖,這樣可以吧我們的常用的一些操作放到這個Navigation Drawer.不過這個交互有個比較別扭的是Navigation打開時必須手指貼著最左側,不過這也增加了和IOS的差異。
對於開發者而言,這些都是浮雲。對我們最大的好處就是,我們的V4已經開始支持這個Navigation Drawer。由於我是後知者,所以寫的一些東西可能是基礎的東西,不過我會把我認識的一些東西都做個分享。
使用
由於google被zf給牆了,Android Developer訪問不太穩定,我就將就著用本地的Doc文檔來處理做一個簡單的翻譯吧。
文檔地址{Sdk目錄}/docs/training/implementing-navigation/nav-drawer.html
這個Demo使用是在剛才就是知乎日報的一個Demo版:
view plaincopy to clipboardprint?
public class MainActivity extends Activity {
private String[] mPlanetTitles;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set the adapter for the list view
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
// Set the list's click listener
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
...
}
}
附上布局文件:
view plaincopy to clipboardprint?
<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">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
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>
其中content_frame是個內容面板,我們可以從Fragmeng來填充。而這個listVIew就是我們左側可以滑動的抽屜視圖(現在是一個ListView)。
注意事項:
1 內容視圖必須是DrawerLayout的第一個子視圖。原因在於 XML 布局文件中的View順序為Android系統中的 z-ordering順序,而Navigation Drawer必須出現在內容之上。
2 內容視圖必須填充父組件填充這個視圖,因為當Drawer隱藏時,所展示的就是我們的內容視圖。
3、Navigation Drawer 必須使用android:layout_gravity屬性設置水平的 gravity值 .如果要支持 right-to-left (RTL,從右向左閱讀)語言 用 "start" 代替 "left" (當在 RTL語言運行時候,菜單出現在右側)。
4、抽屜菜單的寬度為 dp 單位而高度和父View一樣。抽屜菜單的寬度應該不超過320dp,這樣用戶可以在菜單打開的時候看到部分內容界面。
由於Navigation Drawer展開和關閉時,有相關的toggle,這個是由DrawerLayout.DrawerListener來處理的。
view plaincopy to clipboardprint?
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
/* Called whenever we call invalidateOptionsMenu() */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// If the nav drawer is open, hide action items related to the content view
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
展開和關閉時的圖標又不太一樣:
view plaincopy to clipboardprint?
public void onCreate(Bundle savedInstanceState) {
...
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(
this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
R.string.drawer_open, /* "open drawer" description */
R.string.drawer_close /* "close drawer" description */
) {
/** Called when a drawer has settled in a completely closed state. */
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
}
/** Called when a drawer has settled in a completely open state. */
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
@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);
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Pass the event to ActionBarDrawerToggle, if it returns
// true, then it has handled the app icon touch event
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
對了,漏了一段翻譯,就是左側的為啥是listview,這個問題不是問題,那需要填充一個view,這個view可以使GridView,scrollview等,隨意吧,只要有內容就行。