http://xiaok.me/2015/04/28/material-design-navigation-drawer/
android 5.0发布的时候,其新的UI设计Material Design让人眼前一亮。在它演示Demo中有一个新型侧边栏很漂亮,虽然github上已经有人做了这个控件了,但是本着知其所以然的理念,我就照着样子自己模仿了一个,不算是控件啦。
加入一个圆形图片控件 CircleImageView
compile 'de.hdodenhof:circleimageview:1.2.2'
添加 RecyclerView
compile 'com.android.support:recyclerview-v7:21.0.+'
google在support.v4中有一个 DrawerLayout
控件,该控件用来建立侧边栏:
<android.support.v4.widget.DrawerLayout>
设为根节点activity_main.xml
中将根节点替换为 DrawerLayout
然后加入两个子节点:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/draw_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!--主内容--> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <include android:id="@+id/toolbar" layout="@layout/toolbar"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello World"/> </LinearLayout> <!--侧边栏内容--> <android.support.v7.widget.RecyclerView android:id="@+id/RecyclerView" android:layout_width="320dp" android:layout_height="match_parent" android:layout_gravity="start" android:background="#ffffff" android:scrollbars="vertical"> </android.support.v7.widget.RecyclerView> </android.support.v4.widget.DrawerLayout>
其中关于ToolBar的建立可以参考 Toolbar使用小结
然后创建一个布局文件 item_nav.xml
用来显示 RecyclerView
的每一项布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:layout_marginBottom="8dp" android:background="#ffffff"> <ImageView android:id="@+id/nav_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingStart="16dp" /> <TextView android:id="@+id/nav_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center_vertical" android:paddingStart="16dp" android:textAppearance="?android:attr/textAppearanceMedium"/> </LinearLayout>
然后创建 header.xml
布局文件,其中我们显示头像,名称,邮箱。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="178dp" android:background="@mipmap/mat3" android:weightSum="1"> <LinearLayout android:layout_width="match_parent" android:layout_height="56dp" android:orientation="vertical" android:layout_alignParentBottom="true" android:layout_alignParentStart="true"> <TextView android:id="@+id/header_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:textColor="#ffffff" android:textSize="14sp" android:textStyle="bold" android:text="GeeKaven"/> <TextView android:id="@+id/header_email" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginTop="5dp" android:textColor="#ffffff" android:textSize="14sp" android:textStyle="normal" android:text="[email protected]"/> </LinearLayout> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/header_avatar" android:layout_width="76dp" android:layout_height="76dp" android:layout_marginStart="16dp" android:layout_marginTop="38dp" android:src="@mipmap/avatar"/> </RelativeLayout>
现在我们布局文件已经写好了,下面就开始写主代码了。 在MainActivity.java
中看看如下代码,比较好理解。
public class MainActivity extends ActionBarActivity { //item名称 private String[] titles = {"Home","Calendar","Setting"}; //item图标 private int[] icons = {R.mipmap.ic_home,R.mipmap.ic_cal,R.mipmap.ic_setting}; private String name = "Geekaven"; private String email = "[email protected]"; //头像 private int avatar = R.mipmap.avatar; private RecyclerView mRecyclerView; //RecyclerVie布局管理器 private RecyclerView.LayoutManager mLayoutManager; //RecyclerView配饰器 private RecyclerView.Adapter mAdapter; private Toolbar mToolbar; private DrawerLayout mDrawerLayout; //抽屉开关,注意是v7的包 private ActionBarDrawerToggle mDrawerToggle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //将toolbar设置为ActionBar mToolbar = (Toolbar)findViewById(R.id.toolbar); setSupportActionBar(mToolbar); mRecyclerView = (RecyclerView)findViewById(R.id.RecyclerView); mRecyclerView.setHasFixedSize(true); //初始化Adapter,布局管理器 mAdapter = new NavAdapter(this,titles,icons,name,email,avatar); mRecyclerView.setAdapter(mAdapter); mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mDrawerLayout = (DrawerLayout)findViewById(R.id.draw_layout); mDrawerToggle = new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar,R.string.openDrawer,R.string.closeDrawer); mDrawerLayout.setDrawerListener(mDrawerToggle); //DrawerListener监听DrawerToggle mDrawerToggle.syncState();//同步 } }
下面创建一个 NavAdapter.java
,这个类是RecyclerView的配饰器。以前的ListView中有addHeader()方法可以添加header,但是RecyclerView没有,因此我们需要自己写。这也是RecyclerView坑的地方。
public class NavAdapter extends RecyclerView.Adapter<NavAdapter.ViewHolder> { //不同的类型标志 private static final int TYPE_HEADER = 0; private static final int TYPE_ITEM = 1; private String[] mNavTitle; private int[] mIcons; private String mName; private String mEmail; private int mAvatar; private LayoutInflater mInflater; private Context context; public NavAdapter(Context context, String[] navTitle,int[] icons, String name, String email, int avatar) { this.context = context; this.mInflater = LayoutInflater.from(context); this.mNavTitle = navTitle; this.mIcons = icons; this.mName = name; this.mEmail = email; this.mAvatar = avatar; } @Override public void onBindViewHolder(ViewHolder holder, int position) { if (holder.HolderId == 1) { holder.mItemText.setText(mNavTitle[position-1]); holder.mIcon.setImageResource(mIcons[position-1]); } else { holder.mName.setText(mName); holder.mAvatar.setImageResource(mAvatar); holder.mEmail.setText(mEmail); } } @Override public NavAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //根据不同的类型创建不同的布局 if (viewType == TYPE_ITEM) { View v = mInflater.inflate(R.layout.item_nav,parent,false); ViewHolder vhItem = new ViewHolder(v,viewType); return vhItem; } else if (viewType == TYPE_HEADER){ View v = mInflater.inflate(R.layout.header, parent, false); ViewHolder vhHeader = new ViewHolder(v,viewType); return vhHeader; } return null; } @Override public long getItemId(int position) { return super.getItemId(position); } @Override public int getItemCount() { //这里加了一个Header所有要+1 return mNavTitle.length + 1; } @Override public int getItemViewType(int position) { //如果item为第一个就为Header类型 if (isPositionHeader(position)) { return TYPE_HEADER; } else { return TYPE_ITEM; } } private boolean isPositionHeader(int position) { return position == 0; } public static class ViewHolder extends RecyclerView.ViewHolder { int HolderId; private ImageView mAvatar; private ImageView mIcon; private TextView mItemText; private TextView mEmail; private TextView mName; public ViewHolder(View itemView, int ViewType) { super(itemView); if (ViewType == NavAdapter.TYPE_ITEM) { mIcon = (ImageView)itemView.findViewById(R.id.nav_icon); mItemText = (TextView)itemView.findViewById(R.id.nav_text); HolderId = 1; } else { mAvatar = (CircleImageView)itemView.findViewById(R.id.header_avatar); mEmail = (TextView)itemView.findViewById(R.id.header_email); mName = (TextView)itemView.findViewById(R.id.header_name); HolderId = 0; } } } }
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="windowActionBar">false</item> <item name="android:windowNoTitle">true</item> <item name="colorPrimary">@color/light_blue_500</item> <item name="colorPrimaryDark">@color/light_blue_700</item> //状态栏透明 <item name="android:windowTranslucentStatus">true</item> </style> </resources>
由于状态栏透明,Toolbar可能与状态了重叠,所以我们在v19以上的版本中设置:
<dimen name="tool_bar_top_padding">24dp</dimen>
最后运行一下就可以看见效果了,很漂亮啊!
到这里一个Material Design风格的抽屉就OK了,Recyclerview还有一些坑爹的地方就是它的点击事件,长点击事件都要自己写,还要多学习啊。