Android控件——RecycleView
RecycleView:是加强版的ListView。解决了提升ListView运行效率的问题还实现了横向滚动(ListView)做不到
实现刚才ListView的功能
1、也是建Fruits类和子项布局布局,这里都是复制ListView的代码。一模一样(RecyclerView需要导包)
2、适配器的构建
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {
private List<Fruits>mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder{
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view){
super(view);
fruitImage=(ImageView)view.findViewById(R.id.fruit_image);
fruitName=(TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruits>fruitList){
mFruitList=fruitList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
ViewHolder viewHolder=new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
Fruits fruit=mFruitList.get(position);
viewHolder.fruitImage.setImageResource(fruit.imageId());
viewHolder.fruitName.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}
(1)这个适配器继承于ReclcyerView.Adapter。并且泛型指定为FruitAdapter.ViewHolder(就是它自己类下的一个内部类,用于对控件的实进行缓存)
(2)新建一个ViewHolder继承于RecyclerView本来的ViewHolder。然后在这里实例化控件。
(3)这里的构造函数不需要三个参数,只需要传入要适配的数据就好了。因为引入布局的事情在FruitAdapter的三个方法重写中办了
(4)由于FruitAdapter是继承于RecyclerView.Adapter,那么就需要重写下面三个函数(我也不知道这个因果关系)
onCreateViewHolder()引入子项布局并创建实例,把引入的布局送给构造函数
onBindViewHolder()获取位置显示图片和文字
getItemCount()返回子项数目
总结:相比于ListView的适配器。没有getView()方法,但是却把getView()实现的功能都分散开分别在适配器的重写函数以及ViewHolder函数中中进行了。还有就是这里的适配器的构造函数只传要适配的数据
3、主活动
public class MainActivity extends AppCompatActivity {
private List<Fruits> fruitList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruits();
RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view);
LinearLayoutManager layoutManager=new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter=new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruits(){
for(int i=0;i<2;i++)
{
Fruits apple=new Fruits("Apple",R.drawable.apple_pic);
fruitList.add(apple);
Fruits banana=new Fruits("Banana",R.drawable.banana_pic);
fruitList.add(banana);
Fruits orange=new Fruits("Apple",R.drawable.orange_pic);
fruitList.add(orange);
Fruits watermelon=new Fruits("Watermelon",R.drawable.watermelon_pic);
fruitList.add(watermelon);
Fruits pear=new Fruits("Pear",R.drawable.pear_pic);
fruitList.add(pear);
Fruits grape=new Fruits("Grape",R.drawable.grape_pic);
fruitList.add(grape);
Fruits pineapple=new Fruits(" Pineapple",R.drawable. pineapple_pic);
fruitList.add( pineapple);
Fruits strawberry=new Fruits("Strawberry",R.drawable.strawberry_pic);
fruitList.add(strawberry);
Fruits cherry=new Fruits("Cherry",R.drawable.cherry_pic);
fruitList.add(cherry);
Fruits mango=new Fruits("Mango",R.drawable.mango_pic);
fruitList.add(mango);
}
}
LinearLayoutManager layoutManager=new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
意思是线性布局。
4、关于纵向滚动和瀑布排序
(1)纵向:需要改一下子项布局中的参数,让布局更合理.
LinearLayoutManager layoutManager=new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
可以看出只需加一行layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
(2)瀑布
RecyclerView recyclerView=(RecyclerView)findViewById(R.id.recycler_view);
StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter=new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
创建一个StaggeredGridLayoutManager实例并且构造函数两个参数
第一个是布局的列数,第二个式布局的排序方式,这里的布局时纵向排列。然后文字用了随机生成,这样就会使名字参差不齐,更显瀑布的美观
具体随机函数
private String getRandomLengthName(String name){
Random random=new Random();
int length=random.nextInt(20)+1;
StringBuilder builder=new StringBuilder();
for(int i=0;i<length;i++)
{
builder.append(name);
}
return builder.toString();
}
利用随机函数(举一例)
Fruits apple=new Fruits(getRandomLengthName("Apple"),R.drawable.apple_pic);
fruitList.add(apple);
5、关于RecycleView的点击事件
首先说一下RecycleView的点击事件与ListView的不同。
(1)RecycleView并没有提供类似于ListView的setOnItemClickListeener()这样的监听方法,而是需要我们给子项具体的View去注册点击事件,这样做的优势是在RecycleView中的子项布局中,无论是点击图片,文字还是整体布局都会有不同的响应。
(2)RecycleView的响应事件不是在主活动中加的。因为他要为每一个子项View添加响应,所以是在适配器的onCreateViewHolder中添加的
代码
static class ViewHolder extends RecyclerView.ViewHolder{
View fruitView;
ImageView fruitImage;
TextView fruitName;
public ViewHolder(View view){
super(view);
fruitView=view;
fruitImage=(ImageView)view.findViewById(R.id.fruit_image);
fruitName=(TextView) view.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List<Fruits>fruitList){
mFruitList=fruitList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item,parent,false);
final ViewHolder viewHolder=new ViewHolder(view);
viewHolder.fruitImage.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
int position=viewHolder.getAdapterPosition();
Fruits fruit=mFruitList.get(position);
Toast.makeText(v.getContext(),"You clicked image"+ fruit.getName(),Toast.LENGTH_SHORT).show();
}
});
viewHolder.fruitView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
int position=viewHolder.getAdapterPosition();
Fruits fruit=mFruitList.get(position);
Toast.makeText(v.getContext(),"You clicked view"+ fruit.getName(),Toast.LENGTH_SHORT).show();
}
});
return viewHolder;
}
这里改变:
(1)定义了View fruitView用于保存最外层的View
(2)响应事件的时候,首先获取用户点击的位置,然后通过位置拿到相应的Fruits实例(因为onCreateViewHolder函数没有直接传进来position参数,所以需要自己获得,而onBindViewHolder就不需要自己获得)
(3)此时点击图片和整体的响应是不同的,同样点击字体的时候,由于字体没有写点击事件,所以他响应的是最外层的。