转载

InstaMaterial概念设计第七部分-实现Navigation-Drawer

准备

在我们开始之前,让我们先做一些资源文件上的准备.

首先添加app的menu中需要用到的所有icon:

InstaMaterial概念设计第七部分-实现Navigation-Drawer

每一个都长得像概念视频中的样子,但其实他们都是从谷歌的Material 设计图标 中获取的。

我们的菜单是基于ListView实现的,因此我们需要为list的item准备好布局。下面是三种不同的布局:

带有用户头像与昵称的头部

InstaMaterial概念设计第七部分-实现Navigation-Drawer

菜单按钮

InstaMaterial概念设计第七部分-实现Navigation-Drawer

分割线(用在菜单按钮之间)

<br /><?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="wrap_content">       <View         android:layout_width="match_parent"         android:layout_height="1dp"         android:background="#dddddd" /> </FrameLayout>

这里是

带有所有新源码的一个完整提交

GlobalMenuView

现在我们来为全局菜单准备布局。总的来说他就是个简单的ListView,我们本可以把它放在xml中,但是考虑到我们希望将这个view注入(嵌入)到更多的Activity中,还是用纯代码更好些。

这个View的需求很简单 – 只要显示菜单项与用户的简单介绍就可以了。因此实现并不是太复杂:

GlobalMenuView.java

public class GlobalMenuView extends ListView implements View.OnClickListener {       private OnHeaderClickListener onHeaderClickListener;     private GlobalMenuAdapter globalMenuAdapter;     private ImageView ivUserProfilePhoto;     private int avatarSize;     private String profilePhoto;       public GlobalMenuView(Context context) {         super(context);         init();     }       private void init() {         setChoiceMode(CHOICE_MODE_SINGLE);         setDivider(getResources().getDrawable(android.R.color.transparent));         setDividerHeight(0);         setBackgroundColor(Color.WHITE);           setupHeader();         setupAdapter();     }       private void setupAdapter() {         globalMenuAdapter = new GlobalMenuAdapter(getContext());         setAdapter(globalMenuAdapter);     }       private void setupHeader() {         this.avatarSize = getResources().getDimensionPixelSize(R.dimen.global_menu_avatar_size);         this.profilePhoto = getResources().getString(R.string.user_profile_photo);           setHeaderDividersEnabled(true);         View vHeader = LayoutInflater.from(getContext()).inflate(R.layout.view_global_menu_header, null);         ivUserProfilePhoto = (ImageView) vHeader.findViewById(R.id.ivUserProfilePhoto);         Picasso.with(getContext())                 .load(profilePhoto)                 .placeholder(R.drawable.img_circle_placeholder)                 .resize(avatarSize, avatarSize)                 .centerCrop()                 .transform(new CircleTransformation())                 .into(ivUserProfilePhoto);         addHeaderView(vHeader);         vHeader.setOnClickListener(this);     }       @Override     public void onClick(View v) {         if (onHeaderClickListener != null) {             onHeaderClickListener.onGlobalMenuHeaderClick(v);         }     }       public interface OnHeaderClickListener {         public void onGlobalMenuHeaderClick(View v);     }       public void setOnHeaderClickListener(OnHeaderClickListener onHeaderClickListener) {         this.onHeaderClickListener = onHeaderClickListener;     } }

正如你看到的,用户介绍的view作为ListView的头部被使用。这就是为什么需要添加一个自定义的监听者来处理onClick。其余的都很简单。

GlobalMenuAdapter更简单,因此就不粘贴代码在这里了。不过,你还是可以点这里:

commit

with GlobalMenuView

implementation

¡£

Navigation Drawer

是建立Navigation Drawer的时候了,首先准备DrawerLayout的根View布局:

drawer_root.xml

<?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:id="@+id/drawerLayout"     android:layout_width="match_parent"     android:layout_height="match_parent">       <FrameLayout         android:id="@+id/vContentFrame"         android:layout_width="match_parent"         android:layout_height="match_parent" />       <FrameLayout         android:id="@+id/vLeftDrawer"         android:layout_width="280dp"         android:layout_height="match_parent"         android:layout_gravity="start" /> </android.support.v4.widget.DrawerLayout>

这个基本的布局包含了自定义的根view(在vContentFrame 元素中)以及左边的drawer(vLeftDrawer 元素)。

DrawerLayoutInstaller

现在该来准备将DrawerLayout注入到Activit布局树中的工具了。未来很可能要对DrawerLayoutInstaller做一些改进,但是目前的需求很简单:

1.在不接触xml文件的情况下将DrawerLayout注入到已有的Activity中。

2.可以自定义DrawerLayout的xml根view以及左item的view。

3.一些自定义(左item的宽度,自定义打开/关闭drawer的toggle)

The first point is done with three simple steps:

第一点通过三个简单的步骤完成:

得到Activity的根View(使用activity.findViewById(android.R.id.content)获得)同时将它的唯一子view拿掉

将抽屉布局作为孩子放入到根View中

将从根View中拿掉的子View放到抽屉的content view中

实现:

DrawerLayoutInstaller_drawerinject.java
private void addDrawerToActivity(DrawerLayout drawerLayout) {     ViewGroup rootView = (ViewGroup) activity.findViewById(android.R.id.content);     ViewGroup drawerContentRoot = (ViewGroup) drawerLayout.getChildAt(0);     View contentView = rootView.getChildAt(0);       rootView.removeView(contentView);       drawerContentRoot.addView(contentView, new ViewGroup.LayoutParams(             ViewGroup.LayoutParams.MATCH_PARENT,             ViewGroup.LayoutParams.MATCH_PARENT     ));       rootView.addView(drawerLayout, new ViewGroup.LayoutParams(             ViewGroup.LayoutParams.MATCH_PARENT,             ViewGroup.LayoutParams.MATCH_PARENT     )); }
其余的代码你可以在这里找到

DrawerLayoutInstaller

µÄʵÏÖ

¡£

我们终于可以将所有这些东西放在一起了,首先在BaseActivity中我们需要构建我们的GlobalMenuView ,然后将它放在DrawerLayout中。然后将所有东西注入到Activity布局中:

BaseActivity_setupDrawer.java

private void setupDrawer() {     GlobalMenuView menuView = new GlobalMenuView(this);     menuView.setOnHeaderClickListener(this);       drawerLayout = DrawerLayoutInstaller.from(this)             .drawerRoot(R.layout.drawer_root)             .drawerLeftView(menuView)             .drawerLeftWidth(Utils.dpToPx(300))             .withNavigationIconToggler(getToolbar())             .build(); }

最后一件事 – 实现打开ProfileAcitivty的onGlobalMenuHeaderClick()方法:

BaseActivity_globalMenuHeaderClick.java

@Override public void onGlobalMenuHeaderClick(final View v) {     drawerLayout.closeDrawer(Gravity.START);     new Handler().postDelayed(new Runnable() {         @Override         public void run() {             int[] startingLocation = new int[2];             v.getLocationOnScreen(startingLocation);             startingLocation[0] += v.getWidth() / 2;             UserProfileActivity.startUserProfileFromLocation(startingLocation, BaseActivity.this);             overridePendingTransition(0, 0);         }     }, 200); }

这里handler将打开动作延迟到DrawerLayout关闭之后。下面是最终的效果

InstaMaterial概念设计第七部分-实现Navigation-Drawer

项目的完整代码 : repository

作者: Miroslaw Stanek

译文链接

正文到此结束
Loading...