Material Design风格的侧边抽屉栏

原文

  http://xiaok.me/2015/04/28/material-design-navigation-drawer/

前言

android 5.0发布的时候,其新的UI设计Material Design让人眼前一亮。在它演示Demo中有一个新型侧边栏很漂亮,虽然github上已经有人做了这个控件了,但是本着知其所以然的理念,我就照着样子自己模仿了一个,不算是控件啦。

准备

  1. Android Studio 1.1.0
  2. 加入一个圆形图片控件 CircleImageView

    compile 'de.hdodenhof:circleimageview:1.2.2'
    
  3. 添加 RecyclerView

    compile 'com.android.support:recyclerview-v7:21.0.+'
    

侧边栏工作方式

google在support.v4中有一个 DrawerLayout 控件,该控件用来建立侧边栏:

  1. 首先将 <android.support.v4.widget.DrawerLayout> 设为根节点
  2. 它的第一个子节点为主要内容
  3. 第二个子节点为侧边栏内容

创建侧边栏

  • 首先在 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="xiaokang_show@live.com"/>
        </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 = "xiaokang_show@live.com";
        //头像
        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;
            }
        }
    }
}
  • 最后一步将状态栏调制透明,只有在V19以上才支持。
    <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还有一些坑爹的地方就是它的点击事件,长点击事件都要自己写,还要多学习啊。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Material Design是谷歌推出的一种设计语言,旨在为移动设备和Web应用提供统一、现代、直观的用户界面设计。它强调了动效、3D效果、触摸反馈等交互体验,同时也提出了一系列设计原则和指导方针,以保证界面的整体美观、一致性和可用性。Material Design通过结合传统的设计元素和现代的数字技术,打造出一种简洁而充满活力的设计风格。 ### 回答2: Material Design 风格是一种由Google推出的设计风格,旨在为移动设备和web应用程序提供一致且有吸引力的用户界面设计。它的设计理念主要基于实物(material)的触感和运动效果,并将这些概念应用到数字界面设计中。 Material Design 风格具有以下特点: 1. 平面化设计:Material Design 风格强调简洁和平面化的界面设计,使用户界面看起来更加清晰和易于理解。 2. 实物模拟:Material Design 风格通过使用阴影、动画和过渡效果等,营造出实物在数字界面上的触感和运动效果,使用户界面更加生动和自然。 3. 定义规范:Material Design 风格为开发者提供了一系列严格的设计规范和指导,包括颜色、字体、图标和布局等,以确保应用程序的一致性和美观性。 4. 多平台适配:Material Design 风格可以在各种平台上使用,包括Android设备、iOS设备以及Web应用程序,实现了跨平台的一致性设计。 5. 响应式布局:Material Design 风格提倡使用响应式设计,使应用程序能够自动适应不同设备的屏幕大小和分辨率,提供更好的用户体验。 总而言之,Material Design 风格以其清晰、简洁和生动的设计风格,以及严格的规范和跨平台适配能力,成为了现代应用程序设计中非常流行的一种设计风格。通过使用Material Design 风格,开发者可以为用户提供更好的用户体验,同时也能够提高应用程序的品质和使用效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值