在項(xiàng)目的進(jìn)展中使用了Gallery控件展示相冊(cè),由于Gallery控件已經(jīng)被谷歌棄用,所以建議大家考慮使用新的控件來(lái)代替,及時(shí)跟上潮流。不過(guò)本篇的重點(diǎn)不是討論被棄用的Gallery控件,而是來(lái)討論怎么使用Gallery控件實(shí)現(xiàn)類似ListView控件的刷新和加載功能,因?yàn)轫?xiàng)目里面使用的是PullToRefresh的庫(kù),但是該庫(kù)好像并不支持Gallery的刷新和加載功能,所以只得自己參考別人的寫法來(lái)實(shí)現(xiàn)該功能了。本文提供一種實(shí)現(xiàn)思路,希望可以幫到大家。(源碼附在文后,歡迎大家下載,不要分!?。?/p>
先看下效果圖(用的是在線GIF生成工具):
![]()
下面開始正文。首先講一下實(shí)現(xiàn)的思路:Gallery是橫向滑動(dòng)的控件,我們類似ListView實(shí)現(xiàn)刷新一樣,當(dāng)滑動(dòng)到第0項(xiàng)時(shí)候,開始刷新操作,滑動(dòng)到最后一項(xiàng)的時(shí)候進(jìn)行分頁(yè)加載的操作。
順著這個(gè)思路,我們開始編碼了:首先是一頭一尾兩個(gè)界面,刷新界面和加載更多的界面,兩個(gè)界面布局類似,就只貼一個(gè)布局文件了。
<?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>寫完之后大概長(zhǎng)這個(gè)樣子,當(dāng)然你可以根據(jù)自己的喜好去定制
原來(lái)的Gallery控件肯定不能實(shí)現(xiàn)我們想要的效果,所以下面我們來(lái)定制自己的Gallery,對(duì)原來(lái)的Galley稍稍動(dòng)一些手腳改造一下。接著上代碼:
public class MyGallery extends Gallery implements android.widget.AdapterView.OnItemSelectedListener{ private IGalleryEventListener mIGalleryEventListener; // 監(jiān)聽(tīng)Gallery滑動(dòng) private View refreshView ; // 刷新的緩沖界面 private View loadMoreView ; // 加載更多緩沖的界面 private int startIndex = 0 ; // 記錄首項(xiàng)的索引 private int endIndex = 0 ; // 記錄最后一項(xiàng)的索引 public MyGallery(Context context) { super(context); this.setOnItemSelectedListener(this); // 設(shè)置監(jiān)聽(tīng)器 } public MyGallery(Context context, AttributeSet attrs) { super(context, attrs); this.setOnItemSelectedListener(this); // 設(shè)置監(jiān)聽(tīng)器 } public MyGallery(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.setOnItemSelectedListener(this); // 設(shè)置監(jiān)聽(tīng)器 } /** * 對(duì)外提供設(shè)置監(jiān)聽(tīng)器的方法 * @param iGalleryEventListener Gallery的滑動(dòng)監(jiān)聽(tīng)器 */ public void setGalleryEventListerner(IGalleryEventListener iGalleryEventListener){ this.mIGalleryEventListener = iGalleryEventListener; } /** * 刷新或加載結(jié)束的回調(diào)方法 */ public void onCompleted(){ if(refreshView != null && refreshView.isShown()){ refreshView.setVisibility(View.GONE); // 刷新頁(yè)面不可見(jiàn) this.setSelection(startIndex+1); // 選中刷新頁(yè)面的后一項(xiàng) } if(loadMoreView != null && loadMoreView.isShown()){ loadMoreView.setVisibility(View.GONE); // 加載更多頁(yè)面不可見(jiàn) if(this.getChildAt(endIndex) != null ) this.setSelection(endIndex) ; // 有數(shù)據(jù)就選中剛剛加載的一項(xiàng) else this.setSelection(endIndex-1); // 否則就選中加載更多頁(yè)面的前面一項(xiàng) } } @Override public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) { startIndex = 0 ; // 首項(xiàng) endIndex = adapterView.getCount() - 1 ; // 最后一項(xiàng) if(position == startIndex ){ // 表示滑動(dòng)到了最前面一頁(yè),刷新操作 refreshView = view ; // 刷新頁(yè)面保存 if(!refreshView.isShown()) refreshView.setVisibility(View.VISIBLE); mIGalleryEventListener.onRefresh(); // 回調(diào)刷新的方法 } if(position == endIndex){ // 表示滑動(dòng)到了最后一頁(yè),加載操作 loadMoreView = view ; if(!loadMoreView.isShown()) loadMoreView.setVisibility(View.VISIBLE); mIGalleryEventListener.onLoadMore(); // 回調(diào)加載的方法 } } @Override public void onNothingSelected(AdapterView<?> adapterView) { }}注釋已經(jīng)寫得很清楚了,紅色部分是我們自己定義的一個(gè)接口,有兩個(gè)待實(shí)現(xiàn)的方法(加載更多和刷新),紅色部分的方法給當(dāng)前的Gallery提供設(shè)置這個(gè)接口的方法,后面要用到。藍(lán)色部分是結(jié)束時(shí)候的回調(diào)方法,紫色部分是當(dāng)前的Gallery實(shí)現(xiàn)了OnItemSelectedListener接口的一些處理,當(dāng)滑動(dòng)到最前面一頁(yè)的時(shí)候讓刷新界面出現(xiàn),當(dāng)滑動(dòng)到最后一頁(yè)的時(shí)候讓加載更多的界面出現(xiàn)。public interface IGalleryEventListener { public void onLoadMore(); // 加載更多的回調(diào)函數(shù) public void onRefresh(); // 刷新的回調(diào)函數(shù)}上面是監(jiān)聽(tīng)的接口,包含兩個(gè)待實(shí)現(xiàn)的方法,后面再要使用的地方實(shí)現(xiàn)該接口即可。下面寫一下Gallery的適配器public class MyGalleryAdapter extends BaseAdapter { private Context mContext ; // 運(yùn)行的上下文 private List<PictureBean> mPictureList ; // 實(shí)體類數(shù)據(jù)集合 private LayoutInflater mInfalter ; // 界面渲染器 private View refreshView, loadMoreView; // 一頭一尾 public MyGalleryAdapter(){ } /** * 構(gòu)造方法 * @param context 上下文 * @param pictureList 實(shí)體類數(shù)據(jù)集合 */ public MyGalleryAdapter(Context context , List<PictureBean> pictureList){ this.mContext = context ; this.mPictureList = pictureList ; } @Override public int getCount() { return mPictureList.size() + 2; // 這里多加了兩個(gè)是因?yàn)槲覀兌嗉恿藘蓚€(gè)界面,分別是加載和刷新的界面,在數(shù)據(jù)集合中一頭一尾 } @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 ){ // 第一頁(yè) refreshView = mInfalter.inflate(R.layout.refresh_layout ,null); refreshView.setVisibility(View.GONE); // 默認(rèn)設(shè)置刷新頁(yè)面不可見(jiàn) return refreshView; // 返回刷新頁(yè)面 }else if(position == this.getCount() - 1){ // 最后一頁(yè) loadMoreView = mInfalter.inflate(R.layout.loadmore_layout ,null); loadMoreView.setVisibility(View.GONE); // 默認(rèn)設(shè)置加載更多不可見(jiàn) return loadMoreView; // 返回加載更多頁(yè)面 }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()); // 設(shè)置相片資源ID describeTv.setText(getItem(position).getPictureName()); // 設(shè)置相片名稱 return view ; // 返回內(nèi)容頁(yè)面 } }}上面代碼注意紅色加粗的部分,在原來(lái)的數(shù)據(jù)集合長(zhǎng)度上在加上2,表示一頭一尾各加了一個(gè)布局占位。藍(lán)色部分也很好理解,初始的時(shí)候讓一頭一尾的兩個(gè)界面都隱藏起來(lái),該顯示的時(shí)候才讓其顯示。
這里有一個(gè)R.layout.content_layout的布局,如下,包含一個(gè)ImageView和一個(gè)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>這里使用的是我們剛剛自定義的Gallery布局,那么MainActivity要使用刷新和加載的功能,就不得不實(shí)現(xiàn)我們剛剛定義的接口了,代碼如下public class MainActivity extends AppCompatActivity implements IGalleryEventListener{ private MyGallery myGallery ; // 自定義Gallery控件 private MyGalleryAdapter myGalleryAdapter ; // 適配器 private List<PictureBean> pictureList = new ArrayList<>(); // 數(shù)據(jù)集合,使用前要先轉(zhuǎn)換為L(zhǎng)ist的子類 @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設(shè)置滑動(dòng)監(jiān)聽(tīng)器 // 準(zhǔn)備數(shù)據(jù) PictureBean bean ; for (int i = 1; i <= 7 ; i++) { bean = new PictureBean(); // 下面一句是獲取mipmap中對(duì)應(yīng)的圖片名稱的資源ID int picResId = this.getResources().getIdentifier("pic"+i,"mipmap",getPackageName()); bean.setPictureResId(picResId); bean.setPictureName("照片--"+i); pictureList.add(bean); } // 設(shè)置適配器 myGalleryAdapter = new MyGalleryAdapter(this,pictureList) ; myGallery.setAdapter(myGalleryAdapter); myGallery.setSelection(1); // 默認(rèn)選中第一項(xiàng),跳過(guò)第0項(xiàng) } @Override public void onLoadMore() { // 在這里處理加載更多的事件 taskThread(0); } @Override public void onRefresh() { // 在這里處理刷新的事件 taskThread(1); } /** * 一般新開一個(gè)線程用于加載或刷新操作 * @param type 這里的type用于區(qū)分是刷新還是加載操作 */ 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","這里可以新建加載或刷新的任務(wù)"); getLoad(type); // 這里是模擬加載更多的任務(wù) } }).start(); } // 模擬獲取數(shù)據(jù)的方法,這里一般是網(wǎng)絡(luò)請(qǐng)求加載數(shù)據(jù) private void getLoad(int type){ if(type == 0){ // 加載操作 mHandler.sendEmptyMessage(0x01); // 加載完畢之后,發(fā)送消息,更新界面 // 這里模擬加載更多數(shù)據(jù) // 準(zhǔn)備數(shù)據(jù) 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); // 刷新完畢之后,發(fā)送消息,更新界面 } } // 一般使用Handler來(lái)更新界面 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(); // 同時(shí)調(diào)用加載結(jié)束的回調(diào)函數(shù),停止轉(zhuǎn)圈圈 } };}首先實(shí)現(xiàn)了我們自定義的接口,并且重寫了兩個(gè)方法(刷新和加載),在刷新和加載中我們開啟了一個(gè)新的線程,模擬在后臺(tái)實(shí)現(xiàn)的網(wǎng)絡(luò)請(qǐng)求過(guò)程,加入線程休眠Thread.sleep(2000)主要是讓刷新界面或者加載界面都能出來(lái)露個(gè)臉,就是讓圈圈出來(lái)轉(zhuǎn)一下。getLoad()方法就是模擬我們的后臺(tái)請(qǐng)求數(shù)據(jù),我這里使用一個(gè)int類型用來(lái)區(qū)分是刷新請(qǐng)求還是加載更多的請(qǐng)求,當(dāng)然你們可以根據(jù)自己的需要去增加相應(yīng)的請(qǐng)求的參數(shù),比如分頁(yè)加載需要頁(yè)碼(pageNum)等。推薦使用Handler來(lái)更新界面,如果是加載更多的話,只需要調(diào)用Adapter的notifyDataSetChanged()方法,如果是刷新的話根據(jù)業(yè)務(wù)需求來(lái)更新,比如我是將數(shù)據(jù)集合清空,然后在填充一次,這樣避免了數(shù)據(jù)重復(fù)。最后別忘了回調(diào)加載結(jié)束的方法,不然那個(gè)刷新或加載更多的圈圈會(huì)一直不停的轉(zhuǎn)、不停的轉(zhuǎn)、不停的轉(zhuǎn)……。這里有一個(gè)測(cè)試用的實(shí)體類,也一并貼上來(lái),顯得文章長(zhǎng)一些…………
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 + '/'' + '}'; }}好像也沒(méi)見(jiàn)得有多長(zhǎng)。總結(jié)一下:其實(shí)實(shí)現(xiàn)可滑動(dòng)控件的刷新或加載也不難,定義好接口以及相應(yīng)的待實(shí)現(xiàn)的方法,在要使用的地方實(shí)現(xiàn)該接口,并填充方法,在方法里面做刷新或加載的操作。另外刷新或加載完了之后,推薦使用Handler來(lái)更新界面,至于轉(zhuǎn)圈圈的界面,控制好時(shí)機(jī),該出現(xiàn)的時(shí)候讓他出現(xiàn),不該出現(xiàn)的時(shí)候堅(jiān)決將他干掉就行了。
參考: 感謝網(wǎng)上的資料,下次記得把鏈接和名字一并奉上,這次就低調(diào)些
。
想要源碼的可以去這兩個(gè)地方,不要分,拿走不謝。我也是個(gè)菜鳥,希望跟大家共同探討人生,哈哈哈
。
Git地址:https://github.com/1989Jiangtao/GalleryRefresh
代碼下載:http://download.csdn.net/detail/u010898329/9750269
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注