在官方文档中推荐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
需要重写这四个方法:
getCount()适配器中数据集中数据的个数getItem(int position)获取数据集中与指定索引对应的数据项getItemId(int position)获取指定行对应IDgetView(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;
}
//还可扩展其他方法
}
}
这边有涉及到抽象类与抽象方法,下面来复习一下抽象
- 使用场景:当父类的某些方法不确定时,用abstract关键字修饰方法【抽象方法】,用abstract修饰该类【抽象类】,在日后子类进行具体重用
- 定义:抽象类是为了把相同的但不确定的东西提取出来,为了在子类中实现该抽象类
- 特征:
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>