赞
踩
在项目的进展中使用了Gallery控件展示相册,由于Gallery控件已经被谷歌弃用,所以建议大家考虑使用新的控件来代替,及时跟上潮流。不过本篇的重点不是讨论被弃用的Gallery控件,而是来讨论怎么使用Gallery控件实现类似ListView控件的刷新和加载功能,因为项目里面使用的是PullToRefresh的库,但是该库好像并不支持Gallery的刷新和加载功能,所以只得自己参考别人的写法来实现该功能了。本文提供一种实现思路,希望可以帮到大家。(源码附在文后,欢迎大家下载,不要分!!)
先看下效果图(用的是在线GIF生成工具):
下面开始正文。首先讲一下实现的思路:Gallery是横向滑动的控件,我们类似ListView实现刷新一样,当滑动到第0项时候,开始刷新操作,滑动到最后一项的时候进行分页加载的操作。
顺着这个思路,我们开始编码了:首先是一头一尾两个界面,刷新界面和加载更多的界面,两个界面布局类似,就只贴一个布局文件了。
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <ProgressBar
- style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="124dp"
- android:id="@+id/progressBarLoadMore" />
-
- <TextView
- android:text="@string/loadMore"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_below="@+id/progressBarLoadMore"
- android:layout_marginTop="30dp"
- android:textSize="24sp"
- android:layout_centerHorizontal="true"
- android:id="@+id/textView2" />
- </RelativeLayout>
写完之后大概长这个样子,当然你可以根据自己的喜好去定制
原来的Gallery控件肯定不能实现我们想要的效果,所以下面我们来定制自己的Gallery,对原来的Galley稍稍动一些手脚改造一下。接着上代码:
- public class MyGallery extends Gallery implements android.widget.AdapterView.OnItemSelectedListener{
-
- private IGalleryEventListener mIGalleryEventListener; // 监听Gallery滑动
- private View refreshView ; // 刷新的缓冲界面
- private View loadMoreView ; // 加载更多缓冲的界面
-
- private int startIndex = 0 ; // 记录首项的索引
- private int endIndex = 0 ; // 记录最后一项的索引
-
- public MyGallery(Context context) {
- super(context);
- this.setOnItemSelectedListener(this); // 设置监听器
- }
-
- public MyGallery(Context context, AttributeSet attrs) {
- super(context, attrs);
- this.setOnItemSelectedListener(this); // 设置监听器
- }
-
- public MyGallery(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- this.setOnItemSelectedListener(this); // 设置监听器
- }
-
- /**
- * 对外提供设置监听器的方法
- * @param iGalleryEventListener Gallery的滑动监听器
- */
- public void setGalleryEventListerner(IGalleryEventListener iGalleryEventListener){
- this.mIGalleryEventListener = iGalleryEventListener;
- }
-
- /**
- * 刷新或加载结束的回调方法
- */
- public void onCompleted(){
- if(refreshView != null && refreshView.isShown()){
- refreshView.setVisibility(View.GONE); // 刷新页面不可见
- this.setSelection(startIndex+1); // 选中刷新页面的后一项
- }
-
- if(loadMoreView != null && loadMoreView.isShown()){
- loadMoreView.setVisibility(View.GONE); // 加载更多页面不可见
- if(this.getChildAt(endIndex) != null ) this.setSelection(endIndex) ; // 有数据就选中刚刚加载的一项
- else this.setSelection(endIndex-1); // 否则就选中加载更多页面的前面一项
- }
- }
-
- @Override
- public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
- startIndex = 0 ; // 首项
- endIndex = adapterView.getCount() - 1 ; // 最后一项
-
- if(position == startIndex ){ // 表示滑动到了最前面一页,刷新操作
- refreshView = view ; // 刷新页面保存
- if(!refreshView.isShown()) refreshView.setVisibility(View.VISIBLE);
- mIGalleryEventListener.onRefresh(); // 回调刷新的方法
- }
-
- if(position == endIndex){ // 表示滑动到了最后一页,加载操作
- loadMoreView = view ;
- if(!loadMoreView.isShown()) loadMoreView.setVisibility(View.VISIBLE);
- mIGalleryEventListener.onLoadMore(); // 回调加载的方法
- }
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> adapterView) {
-
- }
- }
- public interface IGalleryEventListener {
- public void onLoadMore(); // 加载更多的回调函数
- public void onRefresh(); // 刷新的回调函数
- }
上面是监听的接口,包含两个待实现的方法,后面再要使用的地方实现该接口即可。下面写一下Gallery的适配器
- public class MyGalleryAdapter extends BaseAdapter {
-
- private Context mContext ; // 运行的上下文
- private List<PictureBean> mPictureList ; // 实体类数据集合
- private LayoutInflater mInfalter ; // 界面渲染器
- private View refreshView, loadMoreView; // 一头一尾
-
- public MyGalleryAdapter(){
- }
-
- /**
- * 构造方法
- * @param context 上下文
- * @param pictureList 实体类数据集合
- */
- public MyGalleryAdapter(Context context , List<PictureBean> pictureList){
- this.mContext = context ;
- this.mPictureList = pictureList ;
- }
-
- @Override
- public int getCount() {
- return mPictureList.size() + 2; // 这里多加了两个是因为我们多加了两个界面,分别是加载和刷新的界面,在数据集合中一头一尾
- }
-
- @Override
- public PictureBean getItem(int position) {
- if(position==0 || position== getCount()-1) return null;
- return mPictureList.get(position-1) ;
- }
-
- @Override
- public long getItemId(int i) {
- return i;
- }
-
-
- @Override
- public View getView(int position, View view, ViewGroup viewGroup) {
- mInfalter = LayoutInflater.from(mContext);
- if(position == 0 ){ // 第一页
- refreshView = mInfalter.inflate(R.layout.refresh_layout ,null);
- refreshView.setVisibility(View.GONE); // 默认设置刷新页面不可见
- return refreshView; // 返回刷新页面
- }else if(position == this.getCount() - 1){ // 最后一页
- loadMoreView = mInfalter.inflate(R.layout.loadmore_layout ,null);
- loadMoreView.setVisibility(View.GONE); // 默认设置加载更多不可见
- return loadMoreView; // 返回加载更多页面
- }else{
- if(view == null) view = mInfalter.inflate(R.layout.content_layout, null);
- ImageView imageView = ViewHolder.get(view,R.id.image);
- TextView describeTv = ViewHolder.get(view,R.id.describeTv);
- imageView.setImageResource(getItem(position).getPictureResId()); // 设置相片资源ID
- describeTv.setText(getItem(position).getPictureName()); // 设置相片名称
- return view ; // 返回内容页面
- }
- }
- }
蓝色部分也很好理解,初始的时候让一头一尾的两个界面都隐藏起来,该显示的时候才让其显示。
这里有一个R.layout.content_layout的布局,如下,包含一个ImageView和一个TextView
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="10dp"
- android:gravity="center">
-
- <TextView
- android:id="@+id/describeTv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@+id/image"
- android:layout_centerHorizontal="true"
- android:layout_marginTop="20dp"
- android:text="TextView"
- android:textSize="24sp" />
-
- <ImageView
- android:id="@+id/image"
- android:layout_width="300dp"
- android:layout_height="360dp"
- android:src="@mipmap/ic_launcher"
- android:layout_centerInParent="true" />
-
- </RelativeLayout>
下面开始看MainActivity的布局界面
- <?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:id="@+id/activity_main"
- 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.cjt.galleryrefreshdemo.MainActivity">
-
- <com.cjt.galleryrefreshdemo.view.MyGallery
- android:id="@+id/myGallery"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:spacing="15dp"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_marginRight="17dp"
- android:layout_marginEnd="17dp">
- </com.cjt.galleryrefreshdemo.view.MyGallery>
-
- </RelativeLayout>
- public class MainActivity extends AppCompatActivity implements IGalleryEventListener{
-
- private MyGallery myGallery ; // 自定义Gallery控件
- private MyGalleryAdapter myGalleryAdapter ; // 适配器
- private List<PictureBean> pictureList = new ArrayList<>(); // 数据集合,使用前要先转换为List的子类
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- myGallery = (MyGallery) findViewById(R.id.myGallery); /// 获取界面自定义的Gallery控件
- myGallery.setGalleryEventListerner(this); // 为Gallery设置滑动监听器
-
- // 准备数据
- PictureBean bean ;
- for (int i = 1; i <= 7 ; i++) {
- bean = new PictureBean();
- // 下面一句是获取mipmap中对应的图片名称的资源ID
- int picResId = this.getResources().getIdentifier("pic"+i,"mipmap",getPackageName());
- bean.setPictureResId(picResId);
- bean.setPictureName("照片--"+i);
- pictureList.add(bean);
- }
-
- // 设置适配器
- myGalleryAdapter = new MyGalleryAdapter(this,pictureList) ;
- myGallery.setAdapter(myGalleryAdapter);
- myGallery.setSelection(1); // 默认选中第一项,跳过第0项
- }
-
- @Override
- public void onLoadMore() {
- // 在这里处理加载更多的事件
- taskThread(0);
- }
-
- @Override
- public void onRefresh() {
- // 在这里处理刷新的事件
- taskThread(1);
- }
-
- /**
- * 一般新开一个线程用于加载或刷新操作
- * @param type 这里的type用于区分是刷新还是加载操作
- */
- private void taskThread(final int type){
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- Log.e("CJT","这里可以新建加载或刷新的任务");
- getLoad(type); // 这里是模拟加载更多的任务
- }
- }).start();
- }
-
- // 模拟获取数据的方法,这里一般是网络请求加载数据
- private void getLoad(int type){
- if(type == 0){ // 加载操作
- mHandler.sendEmptyMessage(0x01); // 加载完毕之后,发送消息,更新界面
-
- // 这里模拟加载更多数据
- // 准备数据
- PictureBean bean ;
- for (int i = 1; i <= 4 ; i++) {
- bean = new PictureBean();
- int picResId = this.getResources().getIdentifier("m"+i,"mipmap",getPackageName());
- bean.setPictureResId(picResId);
- bean.setPictureName("美女--"+i);
- pictureList.add(bean);
- }
- }else{
- mHandler.sendEmptyMessage(0x02); // 刷新完毕之后,发送消息,更新界面
- }
- }
-
- // 一般使用Handler来更新界面
- private Handler mHandler = new Handler(){
- @Override
- public void handleMessage(Message msg) {
- if(msg.what == 0x01){
- // 更新界面
- if(myGalleryAdapter != null )
- myGalleryAdapter.notifyDataSetChanged();
- }else if(msg.what == 0x02){
- // 更新界面
-
- }
- myGallery.onCompleted(); // 同时调用加载结束的回调函数,停止转圈圈
- }
- };
- }
这里有一个测试用的实体类,也一并贴上来,显得文章长一些…………
- public class PictureBean {
- private int pictureResId ; // 图片资源的ID
- private String pictureName ; // 图片的名称描述
-
- public int getPictureResId() {
- return pictureResId;
- }
-
- public void setPictureResId(int pictureResId) {
- this.pictureResId = pictureResId;
- }
-
- public String getPictureName() {
- return pictureName;
- }
-
- public void setPictureName(String pictureName) {
- this.pictureName = pictureName;
- }
-
- @Override
- public String toString() {
- return "PictureBean{" +
- "pictureResId=" + pictureResId +
- ", pictureName='" + pictureName + '\'' +
- '}';
- }
- }
总结一下:其实实现可滑动控件的刷新或加载也不难,定义好接口以及相应的待实现的方法,在要使用的地方实现该接口,并填充方法,在方法里面做刷新或加载的操作。另外刷新或加载完了之后,推荐使用Handler来更新界面,至于转圈圈的界面,控制好时机,该出现的时候让他出现,不该出现的时候坚决将他干掉就行了。
参考: 感谢网上的资料,下次记得把链接和名字一并奉上,这次就低调些。
想要源码的可以去这两个地方,不要分,拿走不谢。我也是个菜鸟,希望跟大家共同探讨人生,哈哈哈。
Git地址:https://github.com/1989Jiangtao/GalleryRefresh
代码下载:http://download.csdn.net/detail/u010898329/9750269
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。