这次实验基于上次的Andriod实验一完成 实验(一) 传送门
这次是要在之前实现的Fragment框架中添加RecycleView控件,用于实现下拉列表、瀑布流、上拉下拉刷新的功能。
先来介绍一下什么是RecycleView:
【Android 控件 RecyclerView】
概述
从Android 5.0开始,谷歌公司推出了一个用于大量数据展示的新控件RecylerView,可以用来代替传统的ListView,更加强大和灵活。RecyclerView的官方定义如下:
A flexible view for providing a limited window into a large data set.
从定义可以看出,flexible(可扩展性)是RecyclerView的特点。
RecyclerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字Recyclerview即回收view也可以看出。
RecyclerView的优点
RecyclerView并不会完全替代ListView(这点从ListView没有被标记为@Deprecated可以看出),两者的使用场景不一样。但是RecyclerView的出现会让很多开源项目被废弃,例如横向滚动的ListView, 横向滚动的GridView, 瀑布流控件,因为RecyclerView能够实现所有这些功能。
比如:有一个需求是屏幕竖着的时候的显示形式是ListView,屏幕横着的时候的显示形式是2列的GridView,此时如果用RecyclerView,则通过设置LayoutManager一行代码实现替换。
RecylerView相对于ListView的优点罗列如下:
RecyclerView封装了viewholder的回收复用,也就是说RecyclerView标准化了ViewHolder,编写Adapter面向的是ViewHolder而不再是View了,复用的逻辑被封装了,写起来更加简单。
直接省去了listview中convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
提供了一种插拔式的体验,高度的解耦,异常的灵活,针对一个Item的显示RecyclerView专门抽取出了相应的类,来控制Item的显示,使其的扩展性非常强。
设置布局管理器以控制Item的布局方式,横向、竖向以及瀑布流方式
例如:你想控制横向或者纵向滑动列表效果可以通过LinearLayoutManager这个类来进行控制(与GridView效果对应的是GridLayoutManager,与瀑布流对应的还StaggeredGridLayoutManager等)。也就是说RecyclerView不再拘泥于ListView的线性展示方式,它也可以实现GridView的效果等多种效果。
可设置Item的间隔样式(可绘制)
通过继承RecyclerView的ItemDecoration这个类,然后针对自己的业务需求去书写代码。
可以控制Item增删的动画,可以通过ItemAnimator这个类进行控制,当然针对增删的动画,RecyclerView有其自己默认的实现。
但是关于Item的点击和长按事件,需要用户自己去实现。
了解了RecycleView的基本功能,再对自己的程序加以调整适应,就能实现一个很简单的列表下拉功能。
其中有几个重要的文件需要添加
( 一定是添加 ,我之前莫名其妙在MainActivity中修改了很多代码,然后就死活运行不出来! 写好的MainActivity除了代码结构发生改变,否则不要轻易去动他!)。
HomeAdapter.java (新建适配器,以便在界面中添加控件)
package com.example.jay10_8;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder> {
private List<String> mList;
private Context mContext;
public HomeAdapter(Context mContext, List<String> mList) {
this.mContext = mContext;
this.mList = mList;
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.tab01_recycle_item,parent,false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.nametv.setText(mList.get(position));
final String content = mList.get(position);
String stickyData = mList.get(position);
holder.nametv.setText(stickyData);
if (position == 0) {
holder.nametv.setVisibility(View.VISIBLE);
holder.nametv.setText(stickyData);
holder.itemView.setTag(1);
} else {
if (!TextUtils.equals(stickyData, mList.get(position - 1))) {
holder.nametv.setVisibility(View.VISIBLE);
holder.nametv.setText(stickyData);
holder.itemView.setTag(2);
} else {
holder.nametv.setVisibility(View.GONE);
holder.itemView.setTag(3);
}
}
holder.itemView.setContentDescription(stickyData);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "你选中的是: " + content, Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
return mList.size();
}
static class MyViewHolder extends RecyclerView.ViewHolder {
private TextView nametv;
public MyViewHolder(View itemView) {
super(itemView);
nametv = itemView.findViewById(R.id.tab01_header_view);
}
}
public interface OnItemClickListener {
void OnItemClick(View view, List<String> mList);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
// 供外部访问
}
}
item.xml (用以显示新建的RecycleView)
<?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="wrap_content"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:layout_gravity="center_vertical"
/>
</LinearLayout>
item_include.xml (单独显示顶部磁吸的标题栏)
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tab01_header_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="@string/Hearthstone"
android:textColor="#BC1212"
android:textStyle="italic"
android:textSize="25sp"
android:background="#E0F8EB">
</TextView>
item_recycle_item (一个可以被选择的LinearLayout,添加列表显示数据)
<?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="wrap_content"
android:orientation="vertical">
<include layout="@layout/tab01_include" />
</LinearLayout>
然后就是需要修改一下你说需要修改的tab中的Fragment.java文件了,我这里以WeixinFragment为例:
package com.example.jay10_8;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {@link Fragment} subclass.
* Use the {@link WeixinFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class WeixinFragment extends Fragment {
private List<String> mList;
private View view;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public WeixinFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment BlankFragment.
*/
// TODO: Rename and change types and number of parameters
public static WeixinFragment newInstance(String param1, String param2) {
WeixinFragment fragment = new WeixinFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
private void InitRecyclerView(){
RecyclerView mRecyclerView = view.findViewById(R.id.tab01_1);
HomeAdapter mHomeAdapter = new HomeAdapter(getActivity(), mList);
mRecyclerView.setAdapter(mHomeAdapter);
// 设置布局管理器
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL,false);
mRecyclerView.setLayoutManager(linearLayoutManager);
// 设置 item 增加和删除时的动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
// mHomeAdapter.setOnItemClickListener(new HomeAdapter.OnItemClickListener(){
// @Override
// public void OnItemClick(View view, List<String> mList) {
// //此处进行监听事件的业务处理
// Toast.makeText(getActivity(),"我是item",Toast.LENGTH_SHORT).show();
// }
//
// });
}
private List<String> getList() {
List<String> list = new ArrayList<>();
List<String> list1 = new ArrayList<>();
list.add("吉安娜");
list.add("陈康王");
list.add("麦格尼");
list.add("卡德加");
list.add("安度因");
list.add("ddg");
list.add("陈凯歌");
list.add("玛法里奥");
list.add("乌瑟尔");
list.add("吉安娜");
list.add("陈康王");
list.add("麦格尼");
list.add("卡德加");
list.add("安度因");
list.add("ddg");
list.add("陈凯歌");
list.add("玛法里奥");
list.add("乌瑟尔");
list.add("吉安娜");
list.add("陈康王");
list.add("麦格尼");
list.add("卡德加");
list.add("安度因");
list.add("ddg");
list.add("陈凯歌");
list.add("玛法里奥");
list.add("乌瑟尔");
list.add("吉安娜");
list.add("陈康王");
list.add("麦格尼");
list.add("卡德加");
list.add("安度因");
list.add("ddg");
list.add("陈凯歌");
list.add("玛法里奥");
list.add("乌瑟尔");
for (int i =0;i<list.size();i++){
list1.add((i+1)+":"+list.get(i));
}
return list1;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mList = getList();
view = inflater.inflate(R.layout.tab01, container, false);
//对recycleview进行配置
InitRecyclerView();
return view;
}
}
调这个代码真的不是一蹴而就的事,花了我两天时间来看懂和适配自己文件中的参数,一定要注意函数之间的传参对应,在其他函数中如果要调用到主函数中的this.context,记得用getActivity()函数替换。。。
给一个简陋的运行结果康康:(确实很丑,懒得调了)
调bug调的心累。。。。8说了 下把棋歇会 ~~
ψ(*`ー´)ψ
源码我放在下面了,需要的朋友可以自行下载来对照看看,如果实在有解决不了的问题,可以私信我。
源码地址:https://gitee.com/jia_jie_wang/My_RecyclerView/tree/master