• Android Studio精彩案例(四)《DrawerLayout使用详解仿网易新闻客户端侧边栏 》


    转载本专栏文章,请注明出处,尊重原创 。文章博客地址:道龙的博客

    为了提高兴趣,咱们开头先看看最终要实现什么样的效果:


    侧拉菜单在Android应用中非常常见,它的实现方式太多了,今天我们就说说使用Google提供的DrawerLayout来实现侧拉菜单效果。简单模仿一下网易客户端的侧边栏。

    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/drawerlayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <!--中间布局-->
    
        <RelativeLayout
            android:id="@+id/fragment_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <RelativeLayout
                android:id="@+id/title_bar"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:background="#0cbfe8">
    
                <ImageView
                    android:id="@+id/leftmenu"
                    android:layout_width="48dp"
                    android:layout_height="48dp"
                    android:padding="12dp"
                    android:src="@drawable/menu"/>
    
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="48dp"
                    android:layout_centerInParent="true"
                    android:gravity="center"
                    android:text="网易"/>
    
                <ImageView
                    android:id="@+id/rightmenu"
                    android:layout_width="48dp"
                    android:layout_height="48dp"
                    android:layout_alignParentRight="true"
                    android:padding="12dp"
                    android:src="@drawable/ic_action_user"/>
            </RelativeLayout>
    
            <LinearLayout
                android:id="@+id/content"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@id/title_bar"
                android:orientation="vertical"/>
        </RelativeLayout>
    
        <!--左侧的布局-->
        <RelativeLayout
            android:id="@+id/left"
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="left"
            android:background="@android:color/white">
    
            <!--这里通过listview放其他控件-->
            <ListView
                android:id="@+id/left_listview"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
            </ListView>
        </RelativeLayout>
    
        <!--右侧布局-->
        <RelativeLayout
            android:id="@+id/right"
            android:layout_width="260dp"
            android:layout_height="match_parent"
            android:layout_gravity="right"
            android:background="#62dec9">
    
            <ImageView
                android:id="@+id/p_pic"
                android:layout_width="72dp"
                android:layout_height="72dp"
                android:layout_centerInParent="true"
                android:src="@drawable/ic_action_user"/>
    
            <TextView
                android:id="@+id/right_textview"
                android:layout_width="wrap_content"
                android:layout_height="48dp"
                android:layout_below="@id/p_pic"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="12dp"
                android:text="个人中心"
                android:textColor="@android:color/black"
                android:textSize="14sp"/>
        </RelativeLayout>
    
    </android.support.v4.widget.DrawerLayout>

    首先,根布局就是DrawerLayout,在根布局之后又主要分为三大块(代码中描述了),第一块就是主界面的内容,第二块是左边拉出来的布局,第三块是右边拉出来的布局(一般应用只需要左侧布局)。那么系统怎么知道我们这个布局是主布局还是侧拉菜单的布局?请注意左边侧拉菜单布局android:layout_gravity="left"这个属性和右边菜单布局的android:layout_gravity="right"这个属性,我们必须指定这两个值才可以实现效果,系统通过layout_gravity属性的值来判断这个布局是左边菜单的布局还是右边菜单的布局,如果没有这个属性,只显示主界面的布局。

    这个时候,让我们来运行一下程序看看效果:


    布局文件写好之后,我们的侧拉效果其实就已经可以实现了,但是你发现左边拉出来什么东西都没有,那是因为还没有数据,所以我们要在MainActivity中初始化左边布局的ListView,给ListView赋值简直不能再简单的了,直接贴代码吧:

    modeo类:

    package com.itydl.drawerlayoutdemo;
    
    public class ContentModel {
    
       private int imageView;
       private String text;
       private int id;
    
    
       public int getId() {
          return id;
       }
    
       public void setId(int id) {
          this.id = id;
       }
    
       public ContentModel() {
       }
    
       public ContentModel(int imageView, String text, int id) {
          this.imageView = imageView;
          this.text = text;
          this.id = id;
       }
    
       public int getImageView() {
          return imageView;
       }
    
       public void setImageView(int imageView) {
          this.imageView = imageView;
       }
    
       public String getText() {
          return text;
       }
    
       public void setText(String text) {
          this.text = text;
       }
    
    }
    
    Adapter适配器:

    package com.itydl.drawerlayoutdemo;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    import java.util.List;
    
    public class ContentAdapter extends BaseAdapter {
    
       private Context context;
       private List<ContentModel> list;
    
       public ContentAdapter(Context context, List<ContentModel> list) {
          super();
          this.context = context;
          this.list = list;
       }
    
       @Override
       public int getCount() {
          if (list != null) {
             return list.size();
          }
          return 0;
       }
    
       @Override
       public Object getItem(int position) {
          if (list != null) {
             return list.get(position);
          }
          return null;
       }
    
       @Override
       public long getItemId(int position) {
          return list.get(position).getId();
       }
    
       @Override
       public View getView(int position, View convertView, ViewGroup parent) {
          ViewHold hold;
          if (convertView == null) {
             hold = new ViewHold();
             convertView = LayoutInflater.from(context).inflate(
                   R.layout.content_item, null);
             convertView.setTag(hold);
          } else {
             hold = (ViewHold) convertView.getTag();
          }
    
          hold.imageView = (ImageView) convertView
                .findViewById(R.id.item_imageview);
          hold.textView = (TextView) convertView.findViewById(R.id.item_textview);
    
          hold.imageView.setImageResource(list.get(position).getImageView());
          hold.textView.setText(list.get(position).getText());
          return convertView;
       }
    
       class ViewHold {
          public ImageView imageView;
          public TextView textView;
       }
    
    }  

    ListView子项布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" 
        android:paddingTop="20dp"
        android:paddingBottom="20dp"
        android:gravity="center">
        
        <ImageView 
            android:id="@+id/item_imageview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"/>
        
        <TextView 
            android:id="@+id/item_textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="aa"
            android:textSize="20dp"/>
    
    </LinearLayout>
    
    主活动代码。

    public class MainActivity extends AppCompatActivity {
    
        private List<ContentModel> mList = new ArrayList<ContentModel>();;
        private ListView mListView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initData();
    
            mListView = (ListView) findViewById(R.id.left_listview);
            ContentAdapter adapter = new ContentAdapter(this,mList);
            mListView.setAdapter(adapter);
    
        }
    
        private void initData() {
    
            mList.add(new ContentModel(R.drawable.doctoradvice2, "新闻", 1));
            mList.add(new ContentModel(R.drawable.infusion_selected, "订阅", 2));
            mList.add(new ContentModel(R.drawable.mypatient_selected, "图片", 3));
            mList.add(new ContentModel(R.drawable.mywork_selected, "视频", 4));
            mList.add(new ContentModel(R.drawable.nursingcareplan2, "跟帖", 5));
            mList.add(new ContentModel(R.drawable.personal_selected, "投票", 6));
        }
    }
    


    以上操作十分简单,就不想多做口舌了~

    好了,给左边的侧拉菜单中的ListView赋值之后,把它拉出来,这下就全都有数据了。我们可以运行看看效果了:


    模拟器运行测拉并不好控制,真机测试是比较完美的。同时,我们看到标题栏上边我加了一个按钮,那么我们能不能点击让左侧菜单拉出来呢?还有,我能不能给左侧的每一项item加上点击事假呢?答案是肯定的,最后,就让我们实现点击打开测拉菜单,以及实现左侧测拉菜单item的点击事件吧、

    首先通过点击menu打开左侧边栏,点击个人图片打开个人中心。我们只需要给按钮添加点击事件就可以了:

    menu事件

    findViewById(R.id.leftmenu).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mDrawerLayout.openDrawer(Gravity.LEFT);
        }
    });

    个人事件:

    findViewById(R.id.rightmenu).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mDrawerLayout.openDrawer(Gravity.RIGHT);
        }
    });

    其实很简单,直接调用DrawerLayout的openDrawer方法,参数传Gravity.LEFT表示让左边的侧拉菜单出来,参数如果传Gravity.RIGHT,则表示让右边的侧拉菜单出来。

    完成了点击事件,我们就要想着点击item后要处理的事件了:

    在这里再加入点击按钮切换指定页面的功能。即当我点击“新闻”,主界面显示新闻内容,当我点击”订阅“,主界面显示订阅的内容。这个也很好实现,首先,点击事件不用说,就是ListView的setOnItemClickListener,点击之后,我们的主界面会显示相应的Fragment。即,如果点击了新闻,则主界面显示新闻的Fragment,如果点击了订阅,则主界面显示订阅的Fragment,代码写了出来

    mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            switch (position) {
                //模拟两条数据
    
                case 0://新闻
                    //切换新闻的Fragment
                    replaceFragment(new NewsFargment());
                    break;
                case 1://订阅
                    //切换订阅的Fragment
                    replaceFragment(new SubscibeFragment());
                    break;
    
                default:
                    break;
                }
            //点击任一项item项,都关闭左侧菜单
            mDrawerLayout.closeDrawer(Gravity.LEFT);
        }
    });
    因为多个地方会用到切换Fragment,因此我又把这个功能封装了一个公共方法
    public void replaceFragment(Fragment fragment){
        //1、拿到FragmentManager管理器
        FragmentManager manager = getSupportFragmentManager();
    
        //2、获取事物
        FragmentTransaction transaction = manager.beginTransaction();
    
        //3fragment的替换
        transaction.replace(R.id.content,fragment);
    
        //4、提交事物
        transaction.commit();
    }

    每次点击之后,就用相应的Fragment替换主界面的LinearLayout,当然,替换完成之后要记得关闭左边的侧拉菜单,传入的参数为Gravity.LEFT表示关闭左边的侧拉菜单,如果传入的菜单为Gravity.RIGHT表示关闭右边的侧拉菜单。这里两个Fragment都太简单了,我就不贴源码了。

    我们还可以针对左侧测拉布局做一些效果,比如说是,点击选中色,不点击为默认色。以及加入一些其它的更绚丽的设置等。我这里就做简单的设置。更多的效果,大家可根据自己兴趣来。


    针对这个需求我加入了下面的代码:

    /**切换listviewitem背景色,选中为红色;否则为黑色的方式二。当点击item的时候,就会触发子项item的焦点*/
    mListView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if(hasFocus == true){
                //获得焦点
                mListView.setSelector(android.R.color.holo_red_light) ;
            }   else{
                //失去焦点
                mListView.setSelector(android.R.color.black) ;
            }
        }
    });


    项目开发完毕了,咱们来看看最终效果吧:



    模仿网易新闻客户端测拉框架完毕,喜欢我的朋友可以关注我。

    本文参考博客:1、http://blog.csdn.net/u012702547/article/details/49562747

                              2、http://www.cnblogs.com/mengdd/p/3213378.html

    也可以打开微信搜索公众号  Android程序员开发指南  或者手机扫描下方二维码 在公众号阅读更多Android文章。

    微信公众号图片:









  • 相关阅读:
    Richardson成熟度模型:关于REST的不同风格
    领域驱动设计
    dubbo初探
    pom使用异常问题
    [转]解决BootStrap validator验证的图标错位问题
    万恶的360浏览器
    利用Barcode4j实现输出ean13条形码到文件、流的工具类
    使用hibernate中的hql进行分页设置setMaxResults(int a)出错,索引1越界,hql执行不了等等问题
    Mysql 5.6以上版本zip安装方法
    Hibernate5生成的映射文件导致findByExample无法正确查询到结果
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299473.html
Copyright © 2020-2023  润新知