DrawerLayout的简单使用 [学习菜鸟教程笔记][abstract]

在官方文档中推荐DrawerLayout最好作为界面的根布局,否则可能会出现触摸事件被屏蔽的问题。
DrawerLayout中主内容区的布局要放到最顶层,接着放置左边侧滑界面布局,最后放置右边侧滑界面布局。

Item实体类,封装了图标id以及图标名称

package com.example.drawerlayoutdemo;

public class Item {

    private int iconId;
    private String iconName;

    public Item(int iconId, String iconName) {
        this.iconId = iconId;
        this.iconName = iconName;
    }

    public int getIconId() {
        return iconId;
    }

    public void setIconId(int iconId) {
        this.iconId = iconId;
    }

    public String getIconName() {
        return iconName;
    }

    public void setIconName(String iconName) {
        this.iconName = iconName;
    }
}
package com.example.drawerlayoutdemo;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class ContentFragment extends Fragment {

    private TextView tv_content;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fg_content,container,false);
        tv_content = view.findViewById(R.id.tv_content);
        String text = getArguments().getString("text");
        tv_content.setText(text);
        return view;
    }
}

MyAdapter
a.myAdapter继承BaseAdapter
需要重写这四个方法:

  1. getCount() 适配器中数据集中数据的个数
  2. getItem(int position) 获取数据集中与指定索引对应的数据项
  3. getItemId(int position) 获取指定行对应ID
  4. getView(int position, View convertView, ViewGroup parent) 获取每一个Item的显示内容
package com.example.drawerlayoutdemo;


import android.content.Context;
import android.util.SparseArray;
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.ArrayList;


public abstract class MyAdapter<T> extends BaseAdapter {

    private ArrayList<T> mData;
    private int mLayoutRes;   //布局id

    public MyAdapter(ArrayList<T> mData, int mLayoutRes) {
        this.mData = mData;
        this.mLayoutRes = mLayoutRes;
    }

    /**
     * 填充的数据集数
     * @return
     */
    @Override
    public int getCount() {
        return mData != null ? mData.size():0;
    }

    /**
     * 数据集中指定索引对应的数据项
     * @param position
     * @return
     */
    @Override
    public Object getItem(int position) {
        return mData.get(position);
    }

    /**
     * 指定行对应ID
     * @param position
     * @return
     */
    @Override
    public long getItemId(int position) {
        return position;
    }

    /**
     * 每个Item所显示的内容
     * @param position
     * @param convertView
     * @param parent
     * @return
     */
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder = ViewHolder.bind(parent.getContext(),convertView,parent,mLayoutRes,position);
        bindView(holder, (T) getItem(position));
        return holder.getItemView();
    }

    //抽象方法
    protected abstract void bindView(ViewHolder holder, T obj);

/**

    //添加一个元素
    public  void add(T data){
        if (mData == null){
            mData = new ArrayList<>();
        }
        mData.add(data);
        notifyDataSetChanged();
    }

    //往特定位置,添加一个元素
    public void add(int position,T data){
        if (mData == null){
            mData = new ArrayList<>();
        }
        mData.add(position,data);
        notifyDataSetChanged();
    }

   public void remove(T data){
        if (mData !=null){
            mData.remove(data);
        }
        notifyDataSetChanged();
   }

   public void remove(int position){
        if (mData != null){
            mData.remove(position);
        }
        notifyDataSetChanged();
   }

   public  void clear(){
        if (mData !=null){
            mData.clear();
        }
        notifyDataSetChanged();
   }
*/

//ViewHolder重用组件
//加静态是为了在多个地方使用这个 Holder的时候,类只需加载一次
    public static class ViewHolder{
        private SparseArray<View> mViews;//稀疏数组存储ListView的item中的View
        private View item;  //存放convertView;
        private int position;//游标
        private Context context;


        //构造方法完成相关初始化
        private ViewHolder(Context context,ViewGroup parent,int layoutRes){
            mViews = new SparseArray<>();
            this.context = context;
            View contertView = LayoutInflater.from(context).inflate(layoutRes,parent,false);
            contertView.setTag(this);
            item = contertView;
        }

        public static ViewHolder bind(Context context,View convertView,ViewGroup parent,int layoutRes,int position){
            ViewHolder holder;
            if (convertView == null){
                holder = new ViewHolder(context,parent,layoutRes);
            }else{
                holder = (ViewHolder) convertView.getTag();
                holder.item = convertView;
            }
            holder.position = position;
            return holder;
        }

        //@SuppressWarnings("uncheckecd")告诉编译器忽略 unchecked 警告信息,如使用List,ArrayList等未进行参数化产生的警告信息。
        @SuppressWarnings("uncheckecd")
        public  <T extends View> T getView(int id){
            T t = (T) mViews.get(id);
            if (t==null){
                t=item.findViewById(id);
                mViews.put(id,t);
            }
            return t;
        }


        /**
         * 获取当前条目
         *
         */
         public View getItemView(){
             return item;
         }

        /**
         * 获取条目位置
         */
        public int getItemPosition(){
            return position;
        }

        /**
         * 设置文字
         */
        public ViewHolder setText(int id,CharSequence text){
            /*   CharSequence是一个描述字符串结构的接口
                 CharSequence描述的就是一个字符串
                 它下面有StringBuilder,String ,StringBuffer三个子类
             */
            View view = getView(id);
            if (view instanceof TextView){
                ((TextView) view).setText(text);
            }
            return this;
        }

        /**
         * 设置图片
         */

        public  ViewHolder setImageResource(int id,int drawablesRes){
            View view = getView(id);
            if (view instanceof ImageView){
                ((ImageView) view).setImageResource(drawablesRes);
            }else{
                view.setBackgroundResource(drawablesRes);
            }
            return this;
        }

        /**
         * 设置点击监听
         */
        public ViewHolder setOnClickListener(int id,View.OnClickListener listener){
            getView(id).setOnClickListener(listener);
            return this;
        }

        /**
         * 设置可见
         */

        public ViewHolder setVisibility(int id,int visible){
            getView(id).setVisibility(visible);
            return this;
        }

        /**
         * 设置标签
         */

        public ViewHolder setTag(int id,Object obj){
            getView(id).setTag(obj);
            return this;
        }
        //还可扩展其他方法
    }
}

这边有涉及到抽象类与抽象方法,下面来复习一下抽象

  1. 使用场景:当父类的某些方法不确定时,用abstract关键字修饰方法【抽象方法】,用abstract修饰该类【抽象类】,在日后子类进行具体重用
  2. 定义:抽象类是为了把相同的但不确定的东西提取出来,为了在子类中实现该抽象类
  3. 特征:
    a.抽象方法在父类中不能实现,所以没有函数体,无法被实例化
    b.用abstract修饰的类为抽象类,用abstract修饰的方法为抽象方法
    c.抽象类中不一定包含abstract方法
    d.一旦类中包含abstract方法,那么该类必须声明为abstract类
    e.子类继承抽象类后可实例化子类
    d。子类继承抽象类必须实现抽象类中所有方法
public abstract class MyAdapter<T> extends BaseAdapter 
protected abstract void bindView(ViewHolder holder, T obj);

MainActivity

知识点:
1.Activity与Fragment之间的传值
a.组件获取:
Fragment获得Activity中的组件:getActivity().findViewById();
Activity获得Fragment中的组件(根据id和tag都可以):getFragmentManager.findFragmentById(R.id.fragment);
b.Activity传递数据给Fragment:
主要步骤(该步骤必须在fragmentTraction.commit()在这里插入代码片之前完成)
1.创建fragment实例 ContentFragment contentFragment = new ContentFragment();
2.创建Bundle对象(其为键值对存储,可以理解为一个Map<K,V>)
3.通过bundle.putString("str","这是MainActivity传来的值~");传值
4.将bundle通过setArgument(bundle)方法设置进contentfragment:: contentFragment.setArguments(args);
b.Fragment传递数据给Activity:

package com.example.drawerlayoutdemo;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import java.util.ArrayList;


/**
 * 实现步骤
 * 1.创建实体类与布局
 * 2.创建可复用的碎片,点击item实现切换
 * 3.创建MyAdapter
 * 4.MainActivity实现
 */
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {

     private DrawerLayout drawer_Layout;
     private ListView list_left_drawer;
     private ArrayList<Item> menuLists;
     private MyAdapter<Item> myAdapter = null;



    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        drawer_Layout = findViewById(R.id.drawer_layout);
        list_left_drawer = findViewById(R.id.list_left_drawer);

        menuLists = new ArrayList<Item>();
        menuLists.add(new Item(R.mipmap.iv_menu_realtime,"实时信息"));
        menuLists.add(new Item(R.mipmap.iv_menu_alert,"提醒通知"));
        menuLists.add(new Item(R.mipmap.iv_menu_trace,"活动路线"));
        menuLists.add(new Item(R.mipmap.iv_menu_settings,"相关设置"));


       myAdapter = new MyAdapter<Item>(menuLists,R.layout.item_list) {
           @Override
           protected void bindView(ViewHolder holder, Item obj) {
                 holder.setImageResource(R.id.img_icon,obj.getIconId());
                 holder.setText(R.id.txt_content,obj.getIconName());
           }
       };
       list_left_drawer.setAdapter(myAdapter);
       list_left_drawer.setOnItemClickListener(this);

    }


    /**
     * Activity与Fragment之间的传值
     * 主要步骤(该步骤必须在fragmentTransaction.commit()之前完成):
     * 1.创建一个fragment实例
     * 2.创建一个Bundle对象()(其为键值对存储,可以理解为一个Map<K,V>)
     * 3.向bundle中传值:bundle.putString("str","这是MainActivity传来的值~");
     * 4.将bundle通过setArguments(bundle)方法设置进fragment01:fragment01.setArguments(bundle);
     *
     * @param parent
     * @param view
     * @param position
     * @param id
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        ContentFragment contentFragment = new ContentFragment();
        Bundle args = new Bundle();
        args.putString("text",menuLists.get(position).getIconName());
        contentFragment.setArguments(args);
        FragmentManager fm = getSupportFragmentManager();
        fm.beginTransaction().replace(R.id.ly_content,contentFragment).commit();
        drawer_Layout.closeDrawer(list_left_drawer);

    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.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"
>
    <FrameLayout
        android:id="@+id/ly_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <ListView
        android:id="@+id/list_left_drawer"
        android:layout_width="180dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#080808"
        android:choiceMode="singleChoice"
        android:divider="#FFFFFF"
        android:dividerHeight="2dp"/>
</androidx.drawerlayout.widget.DrawerLayout>

fg_content.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="25sp"/>
</RelativeLayout>

item_list.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
    <ImageView
        android:id="@+id/img_icon"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:focusable="false"
        />
    <TextView
        android:id="@+id/txt_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:layout_toRightOf="@+id/img_icon"
        android:textColor="#ffffff"
        android:textSize="18sp"
        android:text="gehgerhr"/>


</RelativeLayout>

接下来是另一例子 左边右边侧滑

MainActivity

package com.example.drawerlayoutdemo2;

import androidx.appcompat.app.AppCompatActivity;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentManager;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;


/**
 * 在官方文档中推荐DrawerLayout最好作为界面的根布局,否则可能会出现触摸事件被屏蔽的问题。
 * DrawerLayout中主内容区的布局要放到最顶层,接着放置左边侧滑界面布局,最后放置右边侧滑界面布局。
 */
public class MainActivity1 extends AppCompatActivity implements View.OnClickListener {

    private RightFragment fg_right_menu;
    private LeftFragment fg_left_menu;
    private DrawerLayout drawer_layout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main1);

        FragmentManager fragmentManager = getSupportFragmentManager();
        //Activity获取Fragment中的组件:
        //getFragmentManager.findFragmentById(R.id.xxx)
        fg_right_menu = (RightFragment) fragmentManager.findFragmentById(R.id.fg_right_menu);
        fg_left_menu =(LeftFragment)  fragmentManager.findFragmentById(R.id.fg_left_menu);
        initView();
    }

    private void initView() {

        drawer_layout = findViewById(R.id.drawer_layout);
        Button btn_right = findViewById(R.id.btn_right);
        btn_right.setOnClickListener(this);


        //设置右面的侧滑菜单只能通过编程打开
        drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);


        //为DrawerLayout添加监听器的方法
        drawer_layout.addDrawerListener(new DrawerLayout.DrawerListener() {
            @Override
            public void onDrawerSlide(View view, float v) {
                /**
                 * 抽屉滑动时,调用此方法
                 */
            }

            @Override
            public void onDrawerOpened(View view) {
                /**
                 * 抽屉被完全展开时,调用此方法
                 */
            }

            @Override
            public void onDrawerClosed(View view) {
                /**
                 * 抽屉被完全关闭时,调用此方法
                 */
                drawer_layout.setDrawerLockMode(
                        DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.RIGHT);
            }

            @Override
            public void onDrawerStateChanged(int i) {
                /**
                 * 抽屉状态改变时,调用此方法
                 */

            }
        });

        fg_right_menu.setDrawerLayout(drawer_layout);
        fg_left_menu.setDrawerLayout(drawer_layout);

    }




    @Override
    public void onClick(View v) {
        drawer_layout.openDrawer(Gravity.RIGHT);
        drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED,
                Gravity.RIGHT);    //解除锁定
    }
}

LeftFragment

package com.example.drawerlayoutdemo2;

import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;


public class LeftFragment extends Fragment {

   private ImageView imageView;
   private DrawerLayout drawer_layout;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fg_left,container,false);
        imageView = view.findViewById(R.id.img_bg);
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               // getActivity().startActivity(new Intent(getActivity(),OtherActivity.class));
                Intent intent = new Intent(getActivity(),OtherActivity.class);
                startActivity(intent);
                //自动关闭侧边栏
                drawer_layout.closeDrawer(Gravity.LEFT);
            }
        });

        return  view;

    }

    //暴露给Activity,用于传入DrawerLayout,因为点击后想关掉DrawerLayout
    public void setDrawerLayout(DrawerLayout drawer_layout)
    {
        this.drawer_layout = drawer_layout;
    }

}

RightFragment

package com.example.drawerlayoutdemo2;


import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;

public class RightFragment extends Fragment implements View.OnClickListener{
    private DrawerLayout drawer_layout;
    private FragmentManager fManager;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fg_right,container,false);
        Button btn1 = view.findViewById(R.id.btn_one);
        Button btn2 = view.findViewById(R.id.btn_two);
        Button btn3 = view.findViewById(R.id.btn_three);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        btn3.setOnClickListener(this);
        fManager = getActivity().getSupportFragmentManager();//获得FragmentManager对象
        return view;


    }

    @Override
    public void onClick(View v) {

        switch(v.getId()){
            case R.id.btn_one:
                ContentFragment cFragment1 = new ContentFragment("1.点击了右侧菜单项一", R.color.colorAccent);
                fManager.beginTransaction().replace(R.id.fly_content,cFragment1).commit();
                drawer_layout.closeDrawer(Gravity.RIGHT);
                break;
            case R.id.btn_two:
                ContentFragment cFragment2 = new ContentFragment("2.点击了右侧菜单二",R.color.colorPrimary);
                fManager.beginTransaction().replace(R.id.fly_content,cFragment2).commit();
                drawer_layout.closeDrawer(Gravity.RIGHT);
                break;
            case R.id.btn_three:
                ContentFragment cFragment3 = new ContentFragment("3.点击了右侧菜单三",R.color.colorPrimaryDark);
                fManager.beginTransaction().replace(R.id.fly_content,cFragment3).commit();
                drawer_layout.closeDrawer(Gravity.RIGHT);
                break;

        }

    }

    public void setDrawerLayout(DrawerLayout drawer_layout){
        this.drawer_layout = drawer_layout;
    }
}

ContentFragment

package com.example.drawerlayoutdemo2;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

public class ContentFragment extends Fragment {
    private  TextView tv_content;
    private String strContent;
    private int bgColor;

    public ContentFragment(String strContent, int bgColor) {
        this.strContent = strContent;
        this.bgColor = bgColor;
    }


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fg_content,container,false);
         view.setBackgroundColor(getResources().getColor(bgColor));
         tv_content = view.findViewById(R.id.tv_content);
         tv_content.setText(strContent);
         return view;

    }
}

OtherActivity

package com.example.drawerlayoutdemo2;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;


public class OtherActivity extends AppCompatActivity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_other);

    }
}

主布局,其他布局未贴代码

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <include
            android:id="@+id/topbar"
            layout="@layout/view_topbar"
            android:layout_width="wrap_content"
            android:layout_height="48dp"/>

        <FrameLayout
            android:id="@+id/fly_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    </LinearLayout>

    <fragment
        android:id="@+id/fg_left_menu"
        android:name="com.example.drawerlayoutdemo2.LeftFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:tag="Left"
        tools:layout="@layout/fg_left"
        />

    <fragment
        android:id="@+id/fg_right_menu"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:name="com.example.drawerlayoutdemo2.RightFragment"
        android:layout_gravity="end"
        android:tag="RIGHT"
        tools:layout="@layout/fg_right"/>

</androidx.drawerlayout.widget.DrawerLayout>

DrawerLayout侧滑菜单


版权声明:本文为qq_43552518原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。