# PagerGalleryLoadoreDemo **Repository Path**: jeff0213/pager-gallery-loadore-demo ## Basic Information - **Project Name**: PagerGalleryLoadoreDemo - **Description**: 网络相册,有java版本和KT版本,B站学习,https://www.bilibili.com/video/BV1m7411v75b - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-02-09 - **Last Updated**: 2023-02-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 底部加载 - 创建底部界面gallery_footer 让他们都居中 ![页脚布局](https://images.gitee.com/uploads/images/2021/0302/143740_29f58964_5475989.png "image-20210226151530825.png") - 修改Gallery适配器 因为底部都一个就 +1 ![getItemCount重写](https://images.gitee.com/uploads/images/2021/0302/143900_2a1683c4_5475989.png "image-20210226151636304.png") 创建常量 ![创建常量](https://images.gitee.com/uploads/images/2021/0302/144001_ffbd3b3e_5475989.png "image-20210226151729490.png") 重写 ![重写](https://images.gitee.com/uploads/images/2021/0302/144102_dc0e5dc7_5475989.png "image-20210226152226765.png") 根据ViewType来是否加载底部 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/144421_b22f3d3f_5475989.png "image-20210226152341818.png") obBindViewType也要修改 ![obBindViewType](https://images.gitee.com/uploads/images/2021/0302/144543_62bbaf68_5475989.png "image-20210226152425797.png") 设置加载到中间 ![设置加载到中间](https://images.gitee.com/uploads/images/2021/0302/144644_21f853c2_5475989.png "image-20210226152544955.png") - 滑动到底部对齐进行监听 在GalleryFramgent中对recyclerView监听 出现最后一行 ![出现最后一行](https://images.gitee.com/uploads/images/2021/0302/144749_44096a87_5475989.png "image-20210226154548461.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/144832_1b2b17b2_5475989.png "image-20210226154607974.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/144936_7ea03007_5475989.png "image-20210226154754563.png") ViewModel重写 !ViewModel重写](https://images.gitee.com/uploads/images/2021/0302/145022_76ff659d_5475989.png "image-20210226162448966.png") 全部加载完毕 ![全部加载完毕](https://images.gitee.com/uploads/images/2021/0302/145102_761fd94d_5475989.png "image-20210226155113232.png") 然后GalleryAdapter就修改TextView ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/145137_3e9975e8_5475989.png "image-20210226155243968.png") 网络故障 ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/145227_2c68967f_5475989.png "image-20210226161905463.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/145255_3723957a_5475989.png "image-20210226162009926.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/145326_def48b2a_5475989.png "image-20210226162131916.png") ![输入图片说明](https://images.gitee.com/uploads/images/2021/0302/145358_654fd6d6_5475989.png "image-20210226162219530.png") # Java版本 - 创建fooer页脚界面、 ![fooer页脚界面](https://images.gitee.com/uploads/images/2021/0302/145439_e148cfe6_5475989.png "image-20210302114310211.png") - 修改GalleryViewModel ```java package com.zyl.pagergallerymoredemo_java.viewModel; import android.app.Application; import android.util.Log; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.google.gson.Gson; import com.zyl.pagergallerymoredemo_java.pojo.Pixabay; import com.zyl.pagergallerymoredemo_java.volley.VolleyUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; public class GalleryViewModel extends AndroidViewModel { public static final int DATA_STATUS_CAN_LOAD_MODE = 0;//加载 public static final int DATA_STATUS_NO_MODE = 1;//数据加载完毕 public static final int DATA_STATUS_NETWORK_ERROR = 2;//网络异常 private MutableLiveData statusLiveData = new MutableLiveData<>();//存储状态 public LiveData getStatusLiveData() { return statusLiveData; } boolean needToScrollToTop = true; //回到顶部 private int perPage = 100; //每页100个图片 String[] keyWorks = {"usa", "chain", "uk", "dog", "load", "sky"}; private String keyWork = keyWorks[new Random().nextInt(keyWorks.length)]; private int currentPage = 1;//当前页码 private int totalPage = 1;//总页数 private String currentKey = "cat";//当前关键词 private boolean isNewQuery = true; //是否是新请求 private boolean isLoading = false; //是否在加载中 { resetQuery(); } public void resetQuery() { currentPage = 1; totalPage = 1; currentKey = keyWork; isNewQuery = true; needToScrollToTop = true; fetchData(); } public GalleryViewModel(@NonNull Application application) { super(application); } private MutableLiveData> listLiveData = new MutableLiveData<>(); public LiveData> getListLiveData() { return listLiveData; } public void fetchData() { if (isLoading) return; //加载中,不可以加载其他 if (currentPage > totalPage) {//数据加载完毕 statusLiveData.postValue(DATA_STATUS_NO_MODE); return; } isLoading = true; //加载中 StringRequest stringRequest = new StringRequest( Request.Method.GET, getUrl(), new Response.Listener() { @Override public void onResponse(String response) { Pixabay pixabay = new Gson().fromJson(response, Pixabay.class); totalPage = (int) Math.ceil((double) pixabay.getTotalHits() / perPage); if (isNewQuery) {//重新加载 listLiveData.postValue(pixabay.getHits()); } else { //将前面的数据和现在的一起放到LiveData中 ArrayList arrayList = new ArrayList<>(pixabay.getHits()); arrayList.add((Pixabay.PhotoItem) listLiveData.getValue()); listLiveData.postValue(arrayList); } statusLiveData.postValue(DATA_STATUS_CAN_LOAD_MODE); //还可以加载图片 isLoading = false; //没有在加载中了 isNewQuery = false;//不是重新加载 currentPage++; } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { statusLiveData.postValue(DATA_STATUS_NETWORK_ERROR); //网络错误 Log.d("myTAG", "onErrorResponse: JSON加载失败", error); } } ); VolleyUtils.getInstance(getApplication()).getRequestQueue().add(stringRequest); } private String getUrl() { return "https://pixabay.com/api/?key=20367884-4ff0b66c3d8b80b87f646de62&q=" + currentKey + "&per_page=" + perPage + "&page=" + currentPage; } } ``` - 修改GalleryAdapter ```java package com.zyl.pagergallerymoredemo_java.adapter; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.navigation.NavController; import androidx.navigation.Navigation; import androidx.recyclerview.widget.DiffUtil; import androidx.recyclerview.widget.ListAdapter; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import com.bumptech.glide.Glide; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.Target; import com.zyl.pagergallerymoredemo_java.R; import com.zyl.pagergallerymoredemo_java.pojo.Pixabay; import com.zyl.pagergallerymoredemo_java.viewModel.GalleryViewModel; import java.util.ArrayList; import io.supercharge.shimmerlayout.ShimmerLayout; public class GalleryAdapter extends ListAdapter { public static final String PHOTO_LIST = "photo_list"; public static final String PHOTO_POSITION = "photo_position"; public int footerViewStatus = 0; private static final int NORMAL_VIEW_TYPE = 0; private static final int FOOTER_VIEW_TYPE = 1; private GalleryViewModel galleryViewModel; public GalleryAdapter(GalleryViewModel galleryViewModel) { super(new DiffUtil.ItemCallback() { @Override public boolean areItemsTheSame(@NonNull Pixabay.PhotoItem oldItem, @NonNull Pixabay.PhotoItem newItem) { return oldItem.getPhotoId() == newItem.getPhotoId(); } @Override public boolean areContentsTheSame(@NonNull Pixabay.PhotoItem oldItem, @NonNull Pixabay.PhotoItem newItem) { return oldItem.getFullUrl().equals(newItem.getFullUrl()) && oldItem.getPreviewUrl().equals(newItem.getPreviewUrl()); } }); this.galleryViewModel = galleryViewModel; } @Override public int getItemCount() { return super.getItemCount() + 1; } @Override public int getItemViewType(int position) { if (position == getItemCount() - 1) { return FOOTER_VIEW_TYPE; } else { return NORMAL_VIEW_TYPE; } } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == NORMAL_VIEW_TYPE) { View inflate = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_gallery, parent, false); final GalleryViewHolder galleryViewHolder = new GalleryViewHolder(inflate); galleryViewHolder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Bundle bundle = new Bundle(); bundle.putParcelableArrayList(PHOTO_LIST, new ArrayList(getCurrentList())); bundle.putInt(PHOTO_POSITION, galleryViewHolder.getAdapterPosition()); NavController navController = Navigation.findNavController(v); navController.navigate(R.id.action_galleryFragment_to_photoFragment, bundle); } }); return galleryViewHolder; } else { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_gallery, parent, false); final FooterViewHolder footerViewHolder = new FooterViewHolder(view); ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).setFullSpan(true); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { footerViewHolder.progressBar.setVisibility(View.VISIBLE); footerViewHolder.tvStatus.setText("正在加载"); galleryViewModel.fetchData(); } }); return footerViewHolder; } } @Override public void onBindViewHolder(@NonNull final RecyclerView.ViewHolder holder, int position) { if (position == getItemCount() - 1) { FooterViewHolder footerViewHolder = (FooterViewHolder) holder; switch (footerViewStatus) { case GalleryViewModel.DATA_STATUS_CAN_LOAD_MODE: footerViewHolder.progressBar.setVisibility(View.VISIBLE); footerViewHolder.tvStatus.setText("正在加载"); footerViewHolder.itemView.setClickable(false); break; case GalleryViewModel.DATA_STATUS_NETWORK_ERROR: footerViewHolder.progressBar.setVisibility(View.GONE); footerViewHolder.tvStatus.setText("网络异常,点击重试"); footerViewHolder.itemView.setClickable(true); break; case GalleryViewModel.DATA_STATUS_NO_MODE: footerViewHolder.progressBar.setVisibility(View.GONE); footerViewHolder.tvStatus.setText("全部加载完毕"); footerViewHolder.itemView.setClickable(false); break; } return; } final GalleryViewHolder galleryViewHolder = (GalleryViewHolder) holder; galleryViewHolder.shimmerLayout.setShimmerAngle(30); galleryViewHolder.shimmerLayout.setShimmerColor(0x55ffffff); galleryViewHolder.shimmerLayout.startShimmerAnimation(); Pixabay.PhotoItem item = getItem(position); galleryViewHolder.tvUser.setText(item.getPhotoUser()); galleryViewHolder.tvFavorites.setText(String.valueOf(item.getFavorites())); galleryViewHolder.tvLikes.setText(String.valueOf(item.getLikes())); galleryViewHolder.imageView.getLayoutParams().height = item.getPhotoHeight(); Glide.with(holder.itemView) .load(item.getPreviewUrl()) .placeholder(R.drawable.ic_baseline_photo_24) .listener(new RequestListener() { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { Log.d("myTAG", "onLoadFailed: 图片加载失败", e); return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { galleryViewHolder.shimmerLayout.stopShimmerAnimation(); return false; } }) .into(galleryViewHolder.imageView); } class GalleryViewHolder extends RecyclerView.ViewHolder { public ShimmerLayout shimmerLayout; public ImageView imageView; public TextView tvUser; public TextView tvLikes; public TextView tvFavorites; public GalleryViewHolder(@NonNull View itemView) { super(itemView); shimmerLayout = itemView.findViewById(R.id.shimmerLayoutGallery); imageView = itemView.findViewById(R.id.imageViewGallery); tvUser = itemView.findViewById(R.id.tv_user); tvLikes = itemView.findViewById(R.id.tv_likes); tvFavorites = itemView.findViewById(R.id.tv_favorites); } } class FooterViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public TextView tvStatus; public FooterViewHolder(@NonNull View itemView) { super(itemView); progressBar = itemView.findViewById(R.id.progressBar); tvStatus = itemView.findViewById(R.id.tv_status); } } } ``` - 修改GalleryFragment ```java package com.zyl.pagergallerymoredemo_java.fragment; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.StaggeredGridLayoutManager; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.zyl.pagergallerymoredemo_java.R; import com.zyl.pagergallerymoredemo_java.adapter.GalleryAdapter; import com.zyl.pagergallerymoredemo_java.pojo.Pixabay; import com.zyl.pagergallerymoredemo_java.viewModel.GalleryViewModel; import java.util.List; public class GalleryFragment extends Fragment { private SwipeRefreshLayout swipeRefreshLayout; private RecyclerView recyclerView; private GalleryViewModel galleryViewModel; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_gallery, container, false); swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout); recyclerView = view.findViewById(R.id.recyclerView); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); galleryViewModel = new ViewModelProvider(this, new ViewModelProvider.AndroidViewModelFactory(requireActivity().getApplication())) .get(GalleryViewModel.class); final GalleryAdapter galleryAdapter = new GalleryAdapter(galleryViewModel); recyclerView.setAdapter(galleryAdapter); recyclerView.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)); galleryViewModel.getListLiveData().observe(this, new Observer>() { @Override public void onChanged(List photoItems) { if (galleryViewModel.needToScrollToTop) { recyclerView.scrollToPosition(0); galleryViewModel.needToScrollToTop = false; } galleryAdapter.submitList(photoItems); swipeRefreshLayout.setRefreshing(false); } }); if (galleryViewModel.getListLiveData().getValue() == null) { galleryViewModel.fetchData(); } swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { galleryViewModel.resetQuery(); } }); galleryViewModel.getStatusLiveData().observe(getViewLifecycleOwner(), new Observer() { @Override public void onChanged(Integer integer) { galleryAdapter.footerViewStatus = integer; galleryAdapter.notifyItemChanged(galleryAdapter.getItemCount() - 1); if (integer == GalleryViewModel.DATA_STATUS_NO_MODE) {//网络错误 swipeRefreshLayout.setRefreshing(false); } } }); //recycler滚动监听 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); if (dy < 0) { Log.d("myTAG", "onScrolled: 往上划"); return; } //说明是往上划 StaggeredGridLayoutManager layoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager(); int[] ints = new int[2]; layoutManager.findLastVisibleItemPositions(ints); if (ints[0] == galleryAdapter.getItemCount() - 1) { galleryViewModel.fetchData(); } } }); } } ```