一、前期基础知识储备
笔者在前面两篇文章《图片加载库Glide精炼详解》、《最强大的列表滚动控件RecyclerView精炼详解》分别介绍了图片加载库Glide和列表滚动控件的常用用法,那么今天本节文章,就开始把两者组合在一起,用Glide请求网络图片,请求完之后将图片用RecyclerView显示出来。
先分析一下思路:单独使用Glide和RecyclerView相信读者都没有问题,那么两者联合使用,关键的联合点在什么地方?——Glide请求的图片相当于RecyclerView中的数据,那么数据的装载发生在什么地方?——数据的装载在适配器中的onBindViewHolder方法里——那么我们就可以得出,关键的联合点在适配器的方法中。
二、上代码,具体实现
第一步:build.gradle文件中添加依赖;
compile'com.github.bumptech.glide:glide:3.7.0'
compile'com.android.support:recyclerview-v7:23.2.1'
compile'com.android.support:cardview-v7:23.3.0'
因为单独的RecyclerView没有默认的分隔线,所以这里我们采用CardView的方式去填充Item子布局,这样得到的显示效果更好。
第二步:主布局文件中添加RecyclerView控件;
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.administrator.glideandrecyclerview.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycley_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
第三步:新建Bird实体类,注意里面加入图片名字和图片Url地址两种属性;
public class Bird { private String name; private String imageUrl; //这里注意做一个无参数的构造器 public Bird() { } public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getImageUrl() { return imageUrl; } }
第四步:创建RecyclerView中的子项布局,这里我们依据实体类中定义的属性,放入一个文本控件和ImageView控件,用CardView作为父容器进行包裹;
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:layout_marginTop="5dp" card_view:cardCornerRadius="5dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="20dp" android:layout_marginLeft="20dp" android:layout_marginTop="20dp"> <ImageView android:id="@+id/bird_image" android:layout_width="120dp" android:layout_height="60dp" android:layout_marginRight="20dp" /> <TextView android:id="@+id/bird_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@id/bird_image" android:textSize="18sp" android:textStyle="bold" /> </RelativeLayout> </android.support.v7.widget.CardView>
第五步:创建适配器类——核心步骤:
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> { public Context mContext; public ArrayList<Bird> mBirdsList; //我们在适配器中传入两个参数——当前上下文+数据列表 public DataAdapter(Context context,ArrayList<Bird> birdList){ mContext = context; mBirdsList = birdList; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout,parent,false); return new ViewHolder(view); } //使用Glide的地方——onBindViewHolder方法内部,这个方法适配器用于赋值数据 @Override public void onBindViewHolder(ViewHolder holder, int position) { holder.textView.setText(mBirdsList.get(position).getName()); Glide.with(mContext) .load(mBirdsList.get(position).getImageUrl()) .into(holder.imageView); } @Override public int getItemCount() { return mBirdsList.size(); } public class ViewHolder extends RecyclerView.ViewHolder { public ImageView imageView; public TextView textView; public ViewHolder(View itemView) { super(itemView); //适配器构造时只会用到实体类的get方法,用以获取相应的属性 imageView = (ImageView) itemView.findViewById(R.id.bird_image); textView = (TextView) itemView.findViewById(R.id.bird_name); } } }
第六步:主Activity代码中为RecyclerView绑定适配器,同时初始化网络图片数据;
public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private ArrayList<Bird> birdList; private DataAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = (RecyclerView) findViewById(R.id.recycley_view); recyclerView.setHasFixedSize(true); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); recyclerView.setLayoutManager(layoutManager); birdList = initData(); adapter = new DataAdapter(getApplicationContext(), birdList); recyclerView.setAdapter(adapter); } private final String names[] = { "Eclair", "Froyo", "Gingerbread", "Honeycomb", "Ice Cream Sandwich", "Jelly Bean", "KitKat", "Lollipop", "Marshmallow" }; private final String imageUrls[] = { "http://hawksaloft.org/wp-content/uploads/2012/08/614612316_20090805-_mg_3411-rufous-hummingbird-5x7.jpg", "http://www.gregscott.com/gjs_2007_spring/hummingbird/20070311_1948_100_0560.rufous_humminbird.jpg", "http://mosthdwallpapers.com/wp-content/uploads/2016/06/Flying-Hummingbird-Pictures.jpg", "https://wallpapercave.com/wp/alkKAoC.jpg", "http://mosthdwallpapers.com/wp-content/uploads/2016/06/Gorgeous-Hummingbird-Wallpapers-For-Desktop.jpg", "http://naturecanada.ca/wp-content/uploads/2014/07/Ruby-throat-Hummingbird-shutterstock_1953533.jpg", "http://images5.fanpop.com/image/photos/26100000/Hummingbird-hummingbirds-26167630-1024-740.jpg\n", "https://farm5.staticflickr.com/4065/4698051727_5024cd4e6c_b.jpg", "http://mosthdwallpapers.com/wp-content/uploads/2016/06/Beautiful-Hummingbird-HD-Photography.jpg", }; private ArrayList<Bird> initData() { ArrayList<Bird> birds = new ArrayList<>(); for (int i = 0; i < names.length; ++i) { Bird bird = new Bird(); bird.setImageUrl(imageUrls[i]); bird.setName(names[i]); birds.add(bird); } return birds; } }
运行效果如下图:
(网络有点波动,有些图片加载较慢)
小结:其实Glide和RecyclerView单独使用都不难,两者联合起来使用实际上也不难,关键是找到二者的联合点,本例中Glide加载的是网络图片,相当于用于填充RecyclerView的数据,那么绑定数据的逻辑是实现在适配器方法中的。想到这一点之后,我们就可以进行处理了。
————————————————————我是分隔线————————————————————
三、二者联合使用的延伸用法
我们已经实现了上面的基础运用,接下来讨论一下一些有用的延伸用法:
(1)运用Glide加载图片的方法,我们要得到圆形图片的效果;
①builde.gradle文件中添加glide-transformations依赖库
compile'jp.wasabeef:glide-transformations:2.0.2'
②在适配器中调用Glide的bitmapTransform方法,将图片变换成圆形;
Glide.with(mContext) .load(mBirdsList.get(position).getImageUrl()) .bitmapTransform(new CropCircleTransformation(mContext)) .into(holder.imageView);
运行效果如图:
其他的更加丰富的图片的处理方法如裁剪、变换、高斯模糊都是一样在适配器内部中实现的。
(2)运用RecyclerView的方法,我们得到瀑布流布局的效果;
①Item_layout布局中,改变文本控件和ImageView的摆放位置;
<TextView android:id="@+id/bird_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_below="@id/bird_image" android:textSize="12sp" android:textStyle="bold" />
②主Activity代码中,改变RecyclerView的布局方式为瀑布流;
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
运行效果如图:
总结:Glide和RecyclerView的联合使用其实并不复杂,各自做各自的事,找到二者的联合点,然后要实现不一样的布局方式或者展示方式,只需要调用各自的逻辑即可。