Android视图控件:AdapterView类视图控件的使用,Fragment,ViewPager2视图控件的使用

目录

一,Adapter

1.什么是Adapter?

 2.Android中的常用Adapter

二,AdapterView

1.AdapterView简介

 2.AdapterView的子视图对象 

三,ListView滑动列表形式

四, GridView网格形式显示

 五,Fragment和ViewPager2视图控件的使用

1.什么是Fragment?

2.ViewPager2

3.TabLayout+ViewPager2+Fragment实现微信滑动界面

 4.一些小优化


一,Adapter

1.什么是Adapter?

        Adapter(适配器)是连接后端数据与前端视图的接口,是数据与视图之间交互的中介。众所周知,Android用户界面采用MVC框架,即model-view-controller,model和view可理解为是数据和视图,而Adapter就属于中间的controller部分。

        用Adapter作为数据和视图之间交互的中介,就可以将这两部分分开操作:数据改变时,不需要修改视图组件,只需更新Adapter;视图组件改变时,不需要修改数据,只需绑定Adapter即可。

 2.Android中的常用Adapter

  1. BaseAdapter:用于自定义适配器,数据源由用户决定,使用时会被继承并重写方法,最常用也是最灵活的一个adapter;
  2. ArrayAdapter:最简单的适配器,数据源为文本字符,只能显示一行文本;
  3. SimpleAdapter:简单适配器,数据源结构比较复杂,一般为List<Map>类型对象;
  4. SimpleCursorAdapter:游标适配器,用于显示简单文本类型的listview,数据源一般为数据库中的数据;

二,AdapterView

1.AdapterView简介

        AdapterView:容器控件,整体由一个个子元素item组成,子元素的内容与数据由Adapter决定。如下图所示:整体容器框架是AdapterView,其中的每个小元素就是item。

 2.AdapterView的子视图对象 

ListView以垂直滑动列表形式显示一组数据。
GridView以网格形式显示一组数据。
Spinner以下拉列表形式显示一组数据。

三,ListView滑动列表形式

ListView:以垂直可滑动列表形式显示子项目的视图容器,如下图所示:

 ListView使用的基本流程(实现简单的微信界面):

(1)准备ListView整体布局以及每一个子项的视图布局(可以使用内置的布局,也可以自定义布局,我们这里使用自定义布局):

整体布局:

<?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"
    >
   <ListView
       android:id="@+id/lv_wechat"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:visibility="invisible">
   </ListView>
</RelativeLayout>

子元素布局(头像+昵称+聊天信息): 

<?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">

    <ImageView
        android:id="@+id/iv_avatar1"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:src="@mipmap/liyue"
        >
    </ImageView>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_weight="5"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tv_nickname1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:text="璃月"
            ></TextView>
        <TextView
            android:id="@+id/tv_endmessage1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="10sp"
            android:text="114514"
            ></TextView>
    </LinearLayout>

</LinearLayout>

效果预览:

(2)创建Adapter(连接数据源和子元素视图布局,这里使用继承BaseAdapter的自定义适配器):

public class PracticeAdapter extends BaseAdapter {

    private Context context; //上下文
    private Integer layoutId; //布局子控件id
    private List<Practice> list; //数据源

    public PracticeAdapter(){}
    //构造器
    public PracticeAdapter(Context context, Integer layoutId, List<Practice> list){
        this.context = context;
        this.layoutId = layoutId;
        this.list = list;
    }
    //继承BaseAdapter需重写的四个方法
    public int getCount() {return list.size();}//数据个数
    public Object getItem(int position) {return list.get(position);}//对应位置的item
    public long getItemId(int position) {return position;}//返回item下标位置
    //getView最重要的一个函数,position当前item的下标,convertView当前的视图,parent当前视图的父视图
    public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null){
            convertView = LayoutInflater.from(context).inflate(layoutId, null);
        }
        //获取列表项中的控件
        ImageView iv_avatar1 = convertView.findViewById(R.id.iv_avatar1);
        TextView tv_nickname1 = convertView.findViewById(R.id.tv_nickname1);
        TextView tv_endmessage1 = convertView.findViewById(R.id.tv_endmessage1);
        //给数据项填充数据
        Practice practice = list.get(position);
        iv_avatar1.setImageResource(practice.getAvatar());
        tv_nickname1.setText(practice.getNickName());
        tv_endmessage1.setText(practice.getEndMessage());
        //返回列表项
        return convertView;
    }
}

 为Adapter准备数据源:

public class Practice {
    private Integer avatar;//头像
    private String nickName;//昵称
    private String endMessage;//聊天信息

    public Practice(){}
    //构造器
    public Practice(Integer avatar, String nickName, String endMessage){
        this.avatar = avatar;
        this.nickName = nickName;
        this.endMessage = endMessage;
    }
    //数据源 包括头像,昵称,聊天信息
    public static List<Practice> getPractice(){
        List<Practice> list = new ArrayList<>();
        list.add(new Practice(R.mipmap.liyue, "cxk", "师傅!救我口牙!"));
        list.add(new Practice(R.mipmap.liyue, "cxk1", "2333333"));
        list.add(new Practice(R.mipmap.liyue, "cxk2", "[语音聊天]"));
        return list;
    }
}

(3)为ListView绑定Adapter:

//获取ListView控件
ListView lv_practice = findViewById(R.id.lv_practice);
//获取数据源
List<Practice> list = Practice.getPractice();
//创建Adapter
PracticeAdapter adapter = new PracticeAdapter(
         TabPracticeActivity.this,
         R.layout.item_practice, //子控件id
         list
);
//为ListView绑定Adapter
lv_practice.setAdapter(adapter);

(4)为ListView绑定事件监听器:

//使用匿名内部类的方式绑定事件监听器
lv_practice.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Toast.makeText(
            TabPracticeActivity.this, 
            list.get(position).getNickName(), 
            Toast.LENGTH_SHORT
        ).show();
    }
});

最终效果:

四, GridView网格形式显示

GridView:以网格形式显示子项目的视图容器:

GridView使用的基本流程:

GridView使用的流程与ListView基本一致,同样分为四步:

  1. 准备GridView每一个子项的视图布局。( 可以使用内置的布局,也可以用户自定义布局);
  2. 创建Adapter(连接数据源和视图布局);
  3. 为GridView绑定Adapter;
  4. 为GridView绑定事件监听器;

 在这里我们可以直接将上面ListView的Adapter绑定给GridView,也就是同一份数据对应不同的视图。首先需要将布局文件中的ListView换成GridView:

<?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"
    >
   <GridView
        android:id="@+id/gv_product"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:horizontalSpacing="2dp"
        android:verticalSpacing="2dp"
        android:numColumns="2">
    </GridView>
</RelativeLayout>

然后将上面步骤三四中的ListView全部换成GridView即可:

//获取GridView控件
GridView gv_product = findViewById(R.id.gv_product);
//获取数据源
List<Practice> list = Practice.getPractice();
//创建适配器
PracticeAdapter adapter = new PracticeAdapter(
    TabPracticeActivity.this,
    R.layout.item_practice, //子控件id
    list
);
//绑定适配器
gv_product.setAdapter(adapter);
//设置事件监听器
gv_product.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Toast.makeText(
            TabPracticeActivity.this, 
            list.get(position).getNickName(),                                                     
            Toast.LENGTH_SHORT
        ).show();
    }
});

最终效果如下,可以看到滑动列表效果变为了网格形式效果:

 

 五,Fragment和ViewPager2视图控件的使用

1.什么是Fragment?

        Fragment意为”片段“,是为了解决安卓app运行的设备大小不一而提出的,Fragment将屏幕分成了几组,进行模块化管理,可以将Fragment当成Activity界面的一个组成部分,一个Activity可以包含很多Fragment。

        Fragment拥有自己的生命周期,可接收、处理用户的事件。 Activity中可以动态的添加、替换和移除某个Fragment。

2.ViewPager2

        ViewPager2(视图控件)基于RecycleView实现,可以实现类似抖音的上下滑动,也可以实现左右滑动,通常配合Fragment一起使用,需要借助FragmentStateAdapter,从而将Fragment和Activity关联在一起。

3.TabLayout+ViewPager2+Fragment实现微信滑动界面

        使用TabLayout可以实现微信底部导航栏,但是界面之间的跳转只能是点击跳转,如果想要实现滑动跳转效果,需要使用ViewPager2+Fragment,因为点击跳转时,两个界面不会同时出现,使用事件监听器设置View是否显示就可实现,但滑动跳转时,两个界面会同时存在。因此需要ViewPager2和Fragment一起使用。

具体实现步骤如下:

(1)设计布局文件(TabLayout+ViewPager2):

<?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">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp_context"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </androidx.viewpager2.widget.ViewPager2>

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tb_nav"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">
    </com.google.android.material.tabs.TabLayout>

</RelativeLayout>

(2)定义Fragment的item子布局(取名fragment_wechat)以及对应的Fragment,因为微信界面有四个(微信,通讯录,发现,我的),因此item子布局和对应的Fragment也要定义四个(实际开发中由四个人分别定义):

<?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">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="微信界面"
        android:textSize="60sp">
    </TextView>

</LinearLayout>
public class WechatFragment extends Fragment {
    @Nullable
    @Override
    //inflater布局加载器 container是否为父子容器 savedInstanceState保存实例状态
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_wechat, null);
        return view;
    }
}

(3)自定义FragmentStateAdapter,联系Fragment和Activity:

public class WechatFragmentAdapter extends FragmentStateAdapter {

    private List<Fragment> fragmentList;//Fragment数据源,存放定义的四个Fragment

    public WechatFragmentAdapter(List<Fragment> fragmentList, @NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);//调用Activity,因为Fragment最终必须要和Activity联系,因此构造器必须实现;
        this.fragmentList = fragmentList;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {return fragmentList.get(position);}
    @Override
    public int getItemCount() {return fragmentList.size();}
}

(4)给ViewPager2设定适配器:

//获取activity中的控件
TabLayout tb_nav = findViewById(R.id.tb_nav);
ViewPager2 vp_context = findViewById(R.id.vp_context);
//创建fragment数据源
List<Fragment> fragmentList = new ArrayList<>();
fragmentList.add(new WechatFragment());
fragmentList.add(new ContractFragment());
fragmentList.add(new FindFragment());
fragmentList.add(new MineFragment());
//创建适配器
WechatFragmentAdapter adapter = new WechatFragmentAdapter(
    fragmentList, this
);
//viewpager2绑定适配器
vp_context.setAdapter(adapter);

(5)关联TabLayout与ViewPager2(使用TabLayoutMediator):

//TabLayout和ViewPager2关联 通过TabLayoutMediator
TabLayoutMediator mediator = new TabLayoutMediator(
    tb_nav,//TabLayout
    vp_context,//ViewPager2
    new TabLayoutMediator.TabConfigurationStrategy() {
        @Override
        //设置每个tab位置的属性(图标,名称等)
        public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
            switch(position){
                case 0:
                    tab.setText("微信");
                    tab.setIcon(R.mipmap.message);
                    break;
                case 1:
                    tab.setText("联系人");
                    tab.setIcon(R.mipmap.contract);
                    break;
                case 2:
                    tab.setText("发现");
                    tab.setIcon(R.mipmap.find);
                    break;
                case 3:
                    tab.setText("我的");
                    tab.setIcon(R.mipmap.mine);
                    break;
            }
        }
    }
);
//使效果生效
mediator.attach();

最终效果如下:

 4.一些小优化

        在最终效果中,我们发现底部导航与Fragment中的内容正好是对应的,但是我们并没有进行相关操作。实际上,Fragment的内容是按照加入fragmentList的顺序出现的,那么在设置每个tab位置的图标和名称时,我们可以直接按照顺序设置图标和名称。

 首先定义两个List,分别存放名称和图标id,注意顺序必须一一对应:

List<String> tabNameList = new ArrayList<>();
tabNameList.add("微信");
tabNameList.add("联系人");
tabNameList.add("发现");
tabNameList.add("我的");

List<Integer> tabImageList = new ArrayList<>();
tabImageList.add(R.mipmap.message);
tabImageList.add(R.mipmap.contract);
tabImageList.add(R.mipmap.find);
tabImageList.add(R.mipmap.mine);

 然后在设置tab位置的属性时替换掉switch,这样就可以对代码进行优化:

//TabLayout和ViewPager2关联 通过TabLayoutMediator
TabLayoutMediator mediator = new TabLayoutMediator(
    tb_nav,//TabLayout
    vp_context,//ViewPager2
    new TabLayoutMediator.TabConfigurationStrategy() {
        @Override
        //设置每个tab位置的属性(图标,名称等)
        public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
            //替换掉switch,直接按顺序设置
            tab.setText(tabNameList.get(position));
            tab.setIcon(tabImageList.get(position));
        }
    }
);
//使效果生效
mediator.attach();
  • 20
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在一个Fragment实例中使用底部导航栏,你可以按照以下步骤进行: 1. 在你的布局文件中,添加一个BottomNavigationView控件。例如: ``` <android.support.design.widget.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" app:menu="@menu/bottom_navigation_menu" /> ``` 2. 在你的Fragment中,获取这个BottomNavigationView控件,并设置它的监听器。例如: ``` public class MyFragment extends Fragment { private BottomNavigationView bottomNavigationView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_my, container, false); bottomNavigationView = (BottomNavigationView) rootView.findViewById(R.id.bottom_navigation); bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_home: // 处理“首页”选项的操作 return true; case R.id.action_search: // 处理“搜索”选项的操作 return true; case R.id.action_profile: // 处理“个人资料”选项的操作 return true; } return false; } }); return rootView; } } ``` 3. 在你的Fragment的宿主Activity中,重写onCreateOptionsMenu方法,并inflate你的菜单布局。例如: ``` public class MainActivity extends AppCompatActivity { ... @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main_menu, menu); return true; } ... } ``` 4. 在你的菜单布局中,添加一个菜单项,用于切换到你的Fragment。例如: ``` <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_my_fragment" android:title="我的" android:icon="@drawable/ic_person" android:showAsAction="always" /> </menu> ``` 5. 在你的宿主Activity中,处理这个菜单项的点击事件,并打开你的Fragment。例如: ``` public class MainActivity extends AppCompatActivity { ... @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_my_fragment: getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new MyFragment()).commit(); return true; default: return super.onOptionsItemSelected(item); } } ... } ``` 这样,你就可以在你的Fragment实例中使用底部导航栏了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值