当前位置:   article > 正文

安卓之Gallery实现刷新加载和分页加载_gradio 怎么创建的网页怎么动态刷新空间

gradio 怎么创建的网页怎么动态刷新空间

   在项目的进展中使用了Gallery控件展示相册,由于Gallery控件已经被谷歌弃用,所以建议大家考虑使用新的控件来代替,及时跟上潮流。不过本篇的重点不是讨论被弃用的Gallery控件,而是来讨论怎么使用Gallery控件实现类似ListView控件的刷新和加载功能,因为项目里面使用的是PullToRefresh的库,但是该库好像并不支持Gallery的刷新和加载功能,所以只得自己参考别人的写法来实现该功能了。本文提供一种实现思路,希望可以帮到大家。(源码附在文后,欢迎大家下载,不要分!!)

  先看下效果图(用的是在线GIF生成工具):

 

下面开始正文。首先讲一下实现的思路:Gallery是横向滑动的控件,我们类似ListView实现刷新一样,当滑动到第0项时候,开始刷新操作,滑动到最后一项的时候进行分页加载的操作

顺着这个思路,我们开始编码了:首先是一头一尾两个界面,刷新界面和加载更多的界面,两个界面布局类似,就只贴一个布局文件了。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <ProgressBar
  6. style="?android:attr/progressBarStyleLarge"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:layout_alignParentTop="true"
  10. android:layout_centerHorizontal="true"
  11. android:layout_marginTop="124dp"
  12. android:id="@+id/progressBarLoadMore" />
  13. <TextView
  14. android:text="@string/loadMore"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:layout_centerVertical="true"
  18. android:layout_below="@+id/progressBarLoadMore"
  19. android:layout_marginTop="30dp"
  20. android:textSize="24sp"
  21. android:layout_centerHorizontal="true"
  22. android:id="@+id/textView2" />
  23. </RelativeLayout>

写完之后大概长这个样子,当然你可以根据自己的喜好去定制


     原来的Gallery控件肯定不能实现我们想要的效果,所以下面我们来定制自己的Gallery,对原来的Galley稍稍动一些手脚改造一下。接着上代码:

  1. public class MyGallery extends Gallery implements android.widget.AdapterView.OnItemSelectedListener{
  2. private IGalleryEventListener mIGalleryEventListener; // 监听Gallery滑动
  3. private View refreshView ; // 刷新的缓冲界面
  4. private View loadMoreView ; // 加载更多缓冲的界面
  5. private int startIndex = 0 ; // 记录首项的索引
  6. private int endIndex = 0 ; // 记录最后一项的索引
  7. public MyGallery(Context context) {
  8. super(context);
  9. this.setOnItemSelectedListener(this); // 设置监听器
  10. }
  11. public MyGallery(Context context, AttributeSet attrs) {
  12. super(context, attrs);
  13. this.setOnItemSelectedListener(this); // 设置监听器
  14. }
  15. public MyGallery(Context context, AttributeSet attrs, int defStyleAttr) {
  16. super(context, attrs, defStyleAttr);
  17. this.setOnItemSelectedListener(this); // 设置监听器
  18. }
  19. /**
  20. * 对外提供设置监听器的方法
  21. * @param iGalleryEventListener Gallery的滑动监听器
  22. */
  23. public void setGalleryEventListerner(IGalleryEventListener iGalleryEventListener){
  24. this.mIGalleryEventListener = iGalleryEventListener;
  25. }
  26. /**
  27. * 刷新或加载结束的回调方法
  28. */
  29. public void onCompleted(){
  30. if(refreshView != null && refreshView.isShown()){
  31. refreshView.setVisibility(View.GONE); // 刷新页面不可见
  32. this.setSelection(startIndex+1); // 选中刷新页面的后一项
  33. }
  34. if(loadMoreView != null && loadMoreView.isShown()){
  35. loadMoreView.setVisibility(View.GONE); // 加载更多页面不可见
  36. if(this.getChildAt(endIndex) != null ) this.setSelection(endIndex) ; // 有数据就选中刚刚加载的一项
  37. else this.setSelection(endIndex-1); // 否则就选中加载更多页面的前面一项
  38. }
  39. }
  40. @Override
  41. public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
  42. startIndex = 0 ; // 首项
  43. endIndex = adapterView.getCount() - 1 ; // 最后一项
  44. if(position == startIndex ){ // 表示滑动到了最前面一页,刷新操作
  45. refreshView = view ; // 刷新页面保存
  46. if(!refreshView.isShown()) refreshView.setVisibility(View.VISIBLE);
  47. mIGalleryEventListener.onRefresh(); // 回调刷新的方法
  48. }
  49. if(position == endIndex){ // 表示滑动到了最后一页,加载操作
  50. loadMoreView = view ;
  51. if(!loadMoreView.isShown()) loadMoreView.setVisibility(View.VISIBLE);
  52. mIGalleryEventListener.onLoadMore(); // 回调加载的方法
  53. }
  54. }
  55. @Override
  56. public void onNothingSelected(AdapterView<?> adapterView) {
  57. }
  58. }

注释已经写得很清楚了, 红色部分是我们自己定义的一个接口,有两个待实现的方法(加载更多和刷新), 红色部分的方法给当前的Gallery提供设置这个接口的方法,后面要用到。 蓝色部分是结束时候的回调方法, 紫色部分是当前的Gallery实现了 OnItemSelectedListener接口的一些处理,当滑动到最前面一页的时候让刷新界面出现,当滑动到最后一页的时候让加载更多的界面出现

  1. public interface IGalleryEventListener {
  2. public void onLoadMore(); // 加载更多的回调函数
  3. public void onRefresh(); // 刷新的回调函数
  4. }
上面是监听的接口,包含两个待实现的方法,后面再要使用的地方实现该接口即可。下面写一下Gallery的适配器

  1. public class MyGalleryAdapter extends BaseAdapter {
  2. private Context mContext ; // 运行的上下文
  3. private List<PictureBean> mPictureList ; // 实体类数据集合
  4. private LayoutInflater mInfalter ; // 界面渲染器
  5. private View refreshView, loadMoreView; // 一头一尾
  6. public MyGalleryAdapter(){
  7. }
  8. /**
  9. * 构造方法
  10. * @param context 上下文
  11. * @param pictureList 实体类数据集合
  12. */
  13. public MyGalleryAdapter(Context context , List<PictureBean> pictureList){
  14. this.mContext = context ;
  15. this.mPictureList = pictureList ;
  16. }
  17. @Override
  18. public int getCount() {
  19. return mPictureList.size() + 2; // 这里多加了两个是因为我们多加了两个界面,分别是加载和刷新的界面,在数据集合中一头一尾
  20. }
  21. @Override
  22. public PictureBean getItem(int position) {
  23. if(position==0 || position== getCount()-1) return null;
  24. return mPictureList.get(position-1) ;
  25. }
  26. @Override
  27. public long getItemId(int i) {
  28. return i;
  29. }
  30. @Override
  31. public View getView(int position, View view, ViewGroup viewGroup) {
  32. mInfalter = LayoutInflater.from(mContext);
  33. if(position == 0 ){ // 第一页
  34. refreshView = mInfalter.inflate(R.layout.refresh_layout ,null);
  35. refreshView.setVisibility(View.GONE); // 默认设置刷新页面不可见
  36. return refreshView; // 返回刷新页面
  37. }else if(position == this.getCount() - 1){ // 最后一页
  38. loadMoreView = mInfalter.inflate(R.layout.loadmore_layout ,null);
  39. loadMoreView.setVisibility(View.GONE); // 默认设置加载更多不可见
  40. return loadMoreView; // 返回加载更多页面
  41. }else{
  42. if(view == null) view = mInfalter.inflate(R.layout.content_layout, null);
  43. ImageView imageView = ViewHolder.get(view,R.id.image);
  44. TextView describeTv = ViewHolder.get(view,R.id.describeTv);
  45. imageView.setImageResource(getItem(position).getPictureResId()); // 设置相片资源ID
  46. describeTv.setText(getItem(position).getPictureName()); // 设置相片名称
  47. return view ; // 返回内容页面
  48. }
  49. }
  50. }


上面代码注意红色加粗的部分,在原来的数据集合长度上在加上2,表示一头一尾各加了一个布局占位。

蓝色部分也很好理解,初始的时候让一头一尾的两个界面都隐藏起来,该显示的时候才让其显示。

这里有一个R.layout.content_layout的布局,如下,包含一个ImageView和一个TextView

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:padding="10dp"
  6. android:gravity="center">
  7. <TextView
  8. android:id="@+id/describeTv"
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:layout_below="@+id/image"
  12. android:layout_centerHorizontal="true"
  13. android:layout_marginTop="20dp"
  14. android:text="TextView"
  15. android:textSize="24sp" />
  16. <ImageView
  17. android:id="@+id/image"
  18. android:layout_width="300dp"
  19. android:layout_height="360dp"
  20. android:src="@mipmap/ic_launcher"
  21. android:layout_centerInParent="true" />
  22. </RelativeLayout>

下面开始看MainActivity的布局界面

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:id="@+id/activity_main"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. android:paddingBottom="@dimen/activity_vertical_margin"
  8. android:paddingLeft="@dimen/activity_horizontal_margin"
  9. android:paddingRight="@dimen/activity_horizontal_margin"
  10. android:paddingTop="@dimen/activity_vertical_margin"
  11. tools:context="com.cjt.galleryrefreshdemo.MainActivity">
  12. <com.cjt.galleryrefreshdemo.view.MyGallery
  13. android:id="@+id/myGallery"
  14. android:layout_width="match_parent"
  15. android:layout_height="match_parent"
  16. android:spacing="15dp"
  17. android:layout_alignParentTop="true"
  18. android:layout_alignParentRight="true"
  19. android:layout_alignParentEnd="true"
  20. android:layout_marginRight="17dp"
  21. android:layout_marginEnd="17dp">
  22. </com.cjt.galleryrefreshdemo.view.MyGallery>
  23. </RelativeLayout>

这里使用的是我们刚刚自定义的Gallery布局,那么 MainActivity要使用刷新和加载的功能,就不得不实现我们刚刚定义的接口了,代码如下

  1. public class MainActivity extends AppCompatActivity implements IGalleryEventListener{
  2. private MyGallery myGallery ; // 自定义Gallery控件
  3. private MyGalleryAdapter myGalleryAdapter ; // 适配器
  4. private List<PictureBean> pictureList = new ArrayList<>(); // 数据集合,使用前要先转换为List的子类
  5. @Override
  6. protected void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.activity_main);
  9. myGallery = (MyGallery) findViewById(R.id.myGallery); /// 获取界面自定义的Gallery控件
  10. myGallery.setGalleryEventListerner(this); // 为Gallery设置滑动监听器
  11. // 准备数据
  12. PictureBean bean ;
  13. for (int i = 1; i <= 7 ; i++) {
  14. bean = new PictureBean();
  15. // 下面一句是获取mipmap中对应的图片名称的资源ID
  16. int picResId = this.getResources().getIdentifier("pic"+i,"mipmap",getPackageName());
  17. bean.setPictureResId(picResId);
  18. bean.setPictureName("照片--"+i);
  19. pictureList.add(bean);
  20. }
  21. // 设置适配器
  22. myGalleryAdapter = new MyGalleryAdapter(this,pictureList) ;
  23. myGallery.setAdapter(myGalleryAdapter);
  24. myGallery.setSelection(1); // 默认选中第一项,跳过第0项
  25. }
  26. @Override
  27. public void onLoadMore() {
  28. // 在这里处理加载更多的事件
  29. taskThread(0);
  30. }
  31. @Override
  32. public void onRefresh() {
  33. // 在这里处理刷新的事件
  34. taskThread(1);
  35. }
  36. /**
  37. * 一般新开一个线程用于加载或刷新操作
  38. * @param type 这里的type用于区分是刷新还是加载操作
  39. */
  40. private void taskThread(final int type){
  41. new Thread(new Runnable() {
  42. @Override
  43. public void run() {
  44. try {
  45. Thread.sleep(2000);
  46. } catch (InterruptedException e) {
  47. e.printStackTrace();
  48. }
  49. Log.e("CJT","这里可以新建加载或刷新的任务");
  50. getLoad(type); // 这里是模拟加载更多的任务
  51. }
  52. }).start();
  53. }
  54. // 模拟获取数据的方法,这里一般是网络请求加载数据
  55. private void getLoad(int type){
  56. if(type == 0){ // 加载操作
  57. mHandler.sendEmptyMessage(0x01); // 加载完毕之后,发送消息,更新界面
  58. // 这里模拟加载更多数据
  59. // 准备数据
  60. PictureBean bean ;
  61. for (int i = 1; i <= 4 ; i++) {
  62. bean = new PictureBean();
  63. int picResId = this.getResources().getIdentifier("m"+i,"mipmap",getPackageName());
  64. bean.setPictureResId(picResId);
  65. bean.setPictureName("美女--"+i);
  66. pictureList.add(bean);
  67. }
  68. }else{
  69. mHandler.sendEmptyMessage(0x02); // 刷新完毕之后,发送消息,更新界面
  70. }
  71. }
  72. // 一般使用Handler来更新界面
  73. private Handler mHandler = new Handler(){
  74. @Override
  75. public void handleMessage(Message msg) {
  76. if(msg.what == 0x01){
  77. // 更新界面
  78. if(myGalleryAdapter != null )
  79. myGalleryAdapter.notifyDataSetChanged();
  80. }else if(msg.what == 0x02){
  81. // 更新界面
  82. }
  83. myGallery.onCompleted(); // 同时调用加载结束的回调函数,停止转圈圈
  84. }
  85. };
  86. }

首先实现了我们自定义的接口,并且重写了两个方法(刷新和加载),在刷新和加载中我们开启了一个新的线程,模拟在后台实现的网络请求过程, 加入线程休眠 Thread.sleep(2000) 主要是让刷新界面或者加载界面都能出来露个脸,就是让圈圈出来转一下。getLoad()方法就是模拟我们的后台请求数据,我这里使用一个int类型用来区分是刷新请求还是加载更多的请求,当然你们可以根据自己的需要去增加相应的请求的参数,比如分页加载需要页码(pageNum)等。推荐使用Handler来更新界面,如果是加载更多的话,只需要调用Adapter的 notifyDataSetChanged()方法,如果是刷新的话根据业务需求来更新,比如我是将数据集合清空,然后在填充一次,这样避免了数据重复。最后别忘了回调加载结束的方法,不然那个刷新或加载更多的圈圈会一直不停的转、不停的转、不停的转……。

这里有一个测试用的实体类,也一并贴上来,显得文章长一些…………

  1. public class PictureBean {
  2. private int pictureResId ; // 图片资源的ID
  3. private String pictureName ; // 图片的名称描述
  4. public int getPictureResId() {
  5. return pictureResId;
  6. }
  7. public void setPictureResId(int pictureResId) {
  8. this.pictureResId = pictureResId;
  9. }
  10. public String getPictureName() {
  11. return pictureName;
  12. }
  13. public void setPictureName(String pictureName) {
  14. this.pictureName = pictureName;
  15. }
  16. @Override
  17. public String toString() {
  18. return "PictureBean{" +
  19. "pictureResId=" + pictureResId +
  20. ", pictureName='" + pictureName + '\'' +
  21. '}';
  22. }
  23. }

好像也没见得有多长。


总结一下:其实实现可滑动控件的刷新或加载也不难,定义好接口以及相应的待实现的方法,在要使用的地方实现该接口,并填充方法,在方法里面做刷新或加载的操作。另外刷新或加载完了之后,推荐使用Handler来更新界面,至于转圈圈的界面,控制好时机,该出现的时候让他出现,不该出现的时候坚决将他干掉就行了。


参考: 感谢网上的资料,下次记得把链接和名字一并奉上,这次就低调些大笑


想要源码的可以去这两个地方,不要分,拿走不谢。我也是个菜鸟,希望跟大家共同探讨人生,哈哈哈得意


Git地址:https://github.com/1989Jiangtao/GalleryRefresh

代码下载:http://download.csdn.net/detail/u010898329/9750269


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/500675
推荐阅读
相关标签
  

闽ICP备14008679号