最近在开发一个小软件,在需要用到图片列表的时候,突然觉得,我好像从来都没有用过recyclerView的瀑布流,于是记下了这篇使用方法
布局
主布局
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12
| <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
|
item布局
item.xml,在item布局中,设置RelativeLayout完全适应ImageView的布局大小,而ImageView的布局大小,将会在显示的过程中动态的计算出来
1 2 3 4 5 6 7 8 9 10 11
| <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/transparent"> <ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
|
创建图片实体类
file用来储存本地图片的文件对象,不用多说;
imgWidth和imgHeight用来储存这个图片的px宽度和高度,在后面适配器中需要结合这两个值去计算图片显示在屏幕上的px高度;
showHeight用来储存图片显示在屏幕上的高度,由屏幕宽度、图片真实高度、图片真实宽度计算得出,当它的值为-1时,说明该对象的显示高度已经计算过了(如果我们的列表是纵向的,那么它显示的宽度是直接通过屏幕宽度计算的,所以不需要在实体类中再对它的显示宽度做记录);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class ImgEntity { private File file; private int imgWidth; private int imgHeight; private int showHeight = -1;
public void setFile(File file) { this.file = file; }
public void setImgWidth(int imgWidth) { this.imgWidth = imgWidth; }
public void setImgHeight(int imgHeight) { this.imgHeight = imgHeight; }
public void setShowHeight(int showHeight) { this.showHeight = showHeight; }
public File getFile() { return file; }
public int getImgWidth() { return imgWidth; }
public int getImgHeight() { return imgHeight; }
public int getShowHeight() { return showHeight; } }
|
适配器
图片显示在屏幕的宽度和高度都是在适配器中动态计算的,由于例子中是垂直方向的瀑布流,所以宽度应该是一个固定值,故没有在图片实体中对其属性定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> { private Context context; private List<ImgEntity> photoList; private int spanCount; private int itemRound; private int marginLeft; private int marginTop; private int marginRight; private int marginBottom;
private int showWidth;
public RecyclerAdapter(Context context, List<ImgEntity> photoList, int spanCount, int itemRound, int marginLeft, int marginTop, int marginRight, int marginBottom) { this.context = context; this.photoList = photoList; this.spanCount = spanCount; this.itemRound = itemRound; this.marginLeft = marginLeft; this.marginTop = marginTop; this.marginRight = marginRight; this.marginBottom = marginBottom;
int screenWidthPx = context.getResources().getDisplayMetrics().widthPixels; showWidth = (screenWidthPx - (marginLeft + marginRight) * spanCount) / spanCount; }
@NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(context).inflate(R.layout.item, parent, false); return new ViewHolder(view); }
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { ImgEntity imgEntity = photoList.get(position); if (imgEntity.getShowHeight() == -1){ int showHeight = (int) (imgEntity.getImgHeight() * (1.0f * showWidth / imgEntity.getImgWidth())); imgEntity.setShowHeight(showHeight); }
holder.imageView.getLayoutParams().height = imgEntity.getShowHeight();
RoundedCorners roundedCorners = new RoundedCorners(itemRound); RequestOptions override = RequestOptions.bitmapTransform(roundedCorners).override(300, 300); Glide.with(context).load(photoList.get(position).getFile()).apply(override).into(holder.imageView); }
@Override public int getItemCount() { return photoList.size(); }
public class ViewHolder extends RecyclerView.ViewHolder { private final ImageView imageView; public ViewHolder(@NonNull View itemView) { super(itemView); imageView = itemView.findViewById(R.id.imageView); } } }
|
使用时
代码中用到的FileUtils.getPathBitmap(path)是封装的一个方法,具体使用为通过图片文件的地址,获取图片的bitmap
1 2 3 4 5 6 7 8 9 10 11 12
| public class FileUtils{ public static Bitmap getPathBitmap(String filePath){ File file = new File(filePath); try { FileInputStream fileInputStream = new FileInputStream(file); return BitmapFactory.decodeStream(fileInputStream); } catch (FileNotFoundException e) { e.printStackTrace(); } return null; } }
|
实战开发中图片的长宽大都由服务器提供
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public class MainActivity extends AppCompatActivity { private int spanCount = 2; private int itemRound = 6; private int marginLeft = 10; private int marginTop = 10; private int marginRight = 10; private int marginBottom = 10; private RecyclerView recyclerView; private List<ImgEntity> photoList = new ArrarList<>(); @Override protect void onCreate(Bundle bundle) { super.onCreate(bundle); recyclerView = findViewById(R.id.recyclerView); File folder = new File("图片文件所在的文件夹地址"); File[] files = folder.listFiles(); if (files != null && files.length > 0){ for (File file : files){ if (FileUtils.getFileType(file).equals("png")){ ImgEntity imgEntity = new ImgEntity(); imgEntity.setFile(file);
Bitmap pathBitmap = FileUtils.getPathBitmap(file.getPath()); int imgWidth = pathBitmap == null ? 0 : pathBitmap.getWidth(); int imgHeight = pathBitmap == null ? 0 : pathBitmap.getHeight(); imgEntity.setImgWidth(imgWidth); imgEntity.setImgHeight(imgHeight);
photoList.add(imgEntity); } } } StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.VERTICAL); FlashRecyclerAdapter flashRecyclerAdapter = new FlashRecyclerAdapter( this, photoList, spanCount, itemRound, marginLeft, marginTop, marginRight, marginBottom ); recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.set(marginLeft, marginTop, marginRight, marginBottom); } }); recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(flashRecyclerAdapter); } }
|
效果
不要在意其它细节,实现完成后大概就是这个样子了