詳解Android使GridView橫向水平滾動(dòng)的實(shí)現(xiàn)方式
Android為我們提供了豎直方向的滾動(dòng)控件GridView,但如果我們想讓它水平滾動(dòng)起來(lái),就需要自己實(shí)現(xiàn)了。
以下使用的測(cè)試數(shù)據(jù)datas集合都為L(zhǎng)ist<ResolveInfo>類(lèi)型,用來(lái)存儲(chǔ)手機(jī)中的所有App
public static List<ResolveInfo> getAppData(Context context) { PackageManager packageManager = context.getPackageManager(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); return packageManager.queryIntentActivities(mainIntent, 0); }
一、單行橫向顯示
實(shí)現(xiàn)思路
- 在代碼中動(dòng)態(tài)設(shè)置GridView的NumColumns,使其等于GridView要顯示的數(shù)據(jù)集合大小。
- 動(dòng)態(tài)設(shè)置item項(xiàng)寬度,結(jié)合數(shù)據(jù)集合大小來(lái)設(shè)置GridView的總寬度。
- 使用HorizontalScrollView包裹GridView
具體實(shí)現(xiàn)
關(guān)鍵代碼
/** * 將GridView改成單行橫向布局 */ private void changeGridView() { // item寬度 int itemWidth = DensityUtil.dip2px(this, 100); // item之間的間隔 int itemPaddingH = DensityUtil.dip2px(this, 1); int size = datas.size(); // 計(jì)算GridView寬度 int gridviewWidth = size * (itemWidth + itemPaddingH); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( gridviewWidth, LinearLayout.LayoutParams.MATCH_PARENT); mContentGv.setLayoutParams(params); mContentGv.setColumnWidth(itemWidth); mContentGv.setHorizontalSpacing(itemPaddingH); mContentGv.setStretchMode(GridView.NO_STRETCH); mContentGv.setNumColumns(size); }
這里用到的dip2px方法是根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)
/** * 根據(jù)手機(jī)的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素) * @param context 上下文 * @param dpValue dp值 * @return px值 */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); }
在布局文件中,使用HorizontalScrollView包裹GridView
<HorizontalScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"> <GridView android:id="@+id/gv_horizontal_gridview_line" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none"/> </LinearLayout> </HorizontalScrollView>
通過(guò)以上設(shè)置,再加上Adapter適配器就能實(shí)現(xiàn)單行橫向滾動(dòng)了,適配器使用常規(guī)的實(shí)現(xiàn)方式就行,這里就不貼了
二、多行橫向分頁(yè)顯示
實(shí)現(xiàn)思路
- 使用ViewPager實(shí)現(xiàn)左右翻頁(yè)效果。
- 根據(jù)數(shù)據(jù)集合大小,計(jì)算出要顯示的頁(yè)數(shù),并生成相應(yīng)數(shù)量的GridView。
- 在GridView的Adapter適配器中,動(dòng)態(tài)分配GridView需要顯示的數(shù)據(jù)集合。
- 使用List保存多個(gè)GridView實(shí)例并傳入ViewPager適配器中,一頁(yè)ViewPager對(duì)應(yīng)一個(gè)GridView實(shí)例。
具體實(shí)現(xiàn)
數(shù)據(jù)量很多時(shí),需要進(jìn)行分頁(yè),計(jì)算方式
需要頁(yè)數(shù) = 總數(shù)量 ÷ 每頁(yè)顯示數(shù)量
有些整除不了的,就需要使用Math.ceil()函數(shù),向上取整
關(guān)鍵代碼
/** * 獲取系統(tǒng)所有的應(yīng)用程序,根據(jù)每頁(yè)需要顯示的item數(shù)量,生成相應(yīng)數(shù)量的GridView頁(yè)面 */ private void initViews(List<ResolveInfo> datas) { int dataSize = datas.size(); // (需要頁(yè)數(shù) = 總數(shù)量 ÷ 每頁(yè)顯示數(shù)量)向上取整數(shù) int PageCount = (int) Math.ceil(dataSize / APP_SIZE); mGridViewList = new ArrayList<>(); for (int i = 0; i <= PageCount; i++) { GridView appPage = new GridView(this); appPage.setAdapter(new HorizontalGvAdapter(this, datas, i)); appPage.setNumColumns(4); appPage.setVerticalSpacing(1); appPage.setHorizontalSpacing(1); appPage.setHorizontalScrollBarEnabled(false); appPage.setVerticalScrollBarEnabled(false); mGridViewList.add(appPage); } if(dataSize % APP_SIZE == 0){ mGridViewList.remove(mGridViewList.size()-1); PageCount--; } mGvPagerAdapter = new HorizontalGvPagerAdapter(mGridViewList); viewPager.setAdapter(mGvPagerAdapter); viewPager.addOnPageChangeListener(new MyPageChangeListener()); addDot(PageCount); }
當(dāng)總數(shù)量 ÷ 每頁(yè)顯示數(shù)量剛好被整除時(shí),會(huì)出現(xiàn)一頁(yè)空白頁(yè)的情況,這個(gè)時(shí)候需要去掉多出來(lái)的那一頁(yè)
if(dataSize % APP_SIZE == 0){ mGridViewList.remove(mGridViewList.size()-1); PageCount--; }
Adapter在創(chuàng)建初期就要對(duì)顯示的數(shù)據(jù)進(jìn)行控制,因?yàn)檫@里每個(gè)GridView都有一個(gè)單獨(dú)的Adapter,所以需要對(duì)其顯示的datas進(jìn)行動(dòng)態(tài)計(jì)算
通過(guò)傳入構(gòu)造方法的數(shù)據(jù)進(jìn)行動(dòng)態(tài)計(jì)算,可以得出數(shù)據(jù)開(kāi)始加載的位置、結(jié)束加載的位置
HorizontalGvAdapter的構(gòu)造方法:
/** * 所有應(yīng)用數(shù)據(jù) */ private List<ResolveInfo> mAppDatas = new ArrayList<ResolveInfo>(); public HorizontalGvAdapter(Context context, List<ResolveInfo> list, int page) { this.mContext = context; // 開(kāi)始加載的位置 int pageStart = page * HorizontalGridViewAct.APP_SIZE; // 結(jié)束加載的位置 int pageEnd = pageStart + HorizontalGridViewAct.APP_SIZE; while ((pageStart < list.size()) && (pageStart < pageEnd)) { mAppDatas.add(list.get(pageStart)); pageStart++; } }
如果需要加小圓點(diǎn)的話(huà),可以先在布局中用一個(gè)空LinearLayout當(dāng)小圓點(diǎn)的容器
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/vp_horizontal_gridview" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_gravity="center" android:background="#c5c5c5" android:scaleType="fitXY"/> <!-- 底部小圓點(diǎn) --> <LinearLayout android:id="@+id/ll_dot_container" android:layout_width="match_parent" android:layout_height="50dp" android:background="#4b4b4b" android:layout_gravity="bottom" android:gravity="center" android:orientation="horizontal"/> </LinearLayout>
然后在代碼中用List<View>來(lái)保存創(chuàng)建的小圓點(diǎn)
// 放圓點(diǎn)的list private List<View> dotViewsList; /** * 創(chuàng)建指定數(shù)量的圓點(diǎn) * @param dotNumber viewPager的數(shù)量 */ private void addDot(int dotNumber) { if (null == dotViewsList) { dotViewsList = new ArrayList<View>(); } LinearLayout dotLayout = (LinearLayout) findViewById(R.id.ll_dot_container); for (int i = 0; i <= dotNumber; i++) { ImageView dotView = new ImageView(this); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); // 圓點(diǎn)與圓點(diǎn)之間的距離 params.leftMargin = 10; params.rightMargin = 10; // 圓點(diǎn)的大小 params.height = 15; params.width = 15; dotLayout.addView(dotView, params); dotViewsList.add(dotView); } // 設(shè)置圓點(diǎn)默認(rèn)選中第一個(gè) setDotShow(0); } 動(dòng)態(tài)添加完小圓點(diǎn)后,就可以設(shè)置它們的選中狀態(tài)了,這里只需要更改對(duì)應(yīng)小圓點(diǎn)的圖片顯示就行 /** * 顯示底部圓點(diǎn)導(dǎo)航 * @param position 選中哪個(gè)圓點(diǎn) */ private void setDotShow(int position){ if (dotViewsList == null){ return; } for (int i = 0; i < dotViewsList.size(); i++) { if (i == position) { dotViewsList.get(position).setBackgroundResource(R.drawable.ic_dot_on); } else { dotViewsList.get(i).setBackgroundResource(R.drawable.ic_dot_off); } } }
三、總結(jié)
以上就是讓GridView橫向滾動(dòng)的實(shí)現(xiàn)方式,其實(shí)我們完全可以不必這么麻煩,Google在support-v7包中為我們提供了RecyclerView控件,切換橫向和豎直滾動(dòng)只需要讓布局管理器使用setOrientation方法設(shè)置一下就好,非常便捷,如果項(xiàng)目允許,建議使用RecyclerView來(lái)實(shí)現(xiàn)此類(lèi)需求。
希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android開(kāi)發(fā)之橫向滾動(dòng)/豎向滾動(dòng)的ListView(固定列頭)
- Android程序開(kāi)發(fā)之ListView實(shí)現(xiàn)橫向滾動(dòng)(帶表頭與固定列)
- Android使用GridView實(shí)現(xiàn)橫向滾動(dòng)效果
- Android開(kāi)發(fā)實(shí)現(xiàn)橫向列表GridView橫向滾動(dòng)的方法【附源碼下載】
- Android GridView實(shí)現(xiàn)橫向列表水平滾動(dòng)
- Android自定義ViewGroup實(shí)現(xiàn)可滾動(dòng)的橫向布局(2)
- Android實(shí)現(xiàn)自定義的彈幕效果
- 實(shí)例解析如何在Android應(yīng)用中實(shí)現(xiàn)彈幕動(dòng)畫(huà)效果
- Android 實(shí)現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解及實(shí)例
- Android實(shí)現(xiàn)橫向無(wú)限循環(huán)滾動(dòng)的單行彈幕效果
相關(guān)文章
Android 中對(duì)JSON數(shù)據(jù)解析實(shí)例代碼
這篇文章主要介紹了Android 中對(duì)JSON數(shù)據(jù)解析實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03android?Service基礎(chǔ)(啟動(dòng)服務(wù)與綁定服務(wù))
大家好,本篇文章主要講的是android?Service基礎(chǔ)(啟動(dòng)服務(wù)與綁定服務(wù)),感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下,方便下次瀏覽2021-12-12Android Usb設(shè)備的監(jiān)聽(tīng)(Dev)外設(shè)端口的判定以及耳機(jī)的插拔
今天小編就為大家分享一篇關(guān)于Android Usb設(shè)備的監(jiān)聽(tīng)(Dev)外設(shè)端口的判定以及耳機(jī)的插拔,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12Android中ActionBar以及menu的代碼設(shè)置樣式
這篇文章主要介紹了Android中ActionBar以及menu的代碼設(shè)置樣式的相關(guān)資料,需要的朋友可以參考下2015-07-07Android仿新浪微博oauth2.0授權(quán)界面實(shí)現(xiàn)代碼(2)
這篇文章主要為大家詳細(xì)介紹了Android仿新浪微博oauth2.0授權(quán)界面實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11Android實(shí)現(xiàn)捕獲未知異常并提交給服務(wù)器的方法
這篇文章主要介紹了Android實(shí)現(xiàn)捕獲未知異常并提交給服務(wù)器的方法,涉及Android的異常與錯(cuò)誤處理機(jī)制相關(guān)操作技巧,需要的朋友可以參考下2016-08-08