詳解Android使GridView橫向水平滾動的實現(xiàn)方式
Android為我們提供了豎直方向的滾動控件GridView,但如果我們想讓它水平滾動起來,就需要自己實現(xiàn)了。
以下使用的測試數(shù)據(jù)datas集合都為List<ResolveInfo>類型,用來存儲手機中的所有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);
}
一、單行橫向顯示

實現(xiàn)思路
- 在代碼中動態(tài)設(shè)置GridView的NumColumns,使其等于GridView要顯示的數(shù)據(jù)集合大小。
- 動態(tài)設(shè)置item項寬度,結(jié)合數(shù)據(jù)集合大小來設(shè)置GridView的總寬度。
- 使用HorizontalScrollView包裹GridView
具體實現(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();
// 計算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ù)手機的分辨率從 dp 的單位 轉(zhuǎn)成為 px(像素)
/**
* 根據(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>
通過以上設(shè)置,再加上Adapter適配器就能實現(xiàn)單行橫向滾動了,適配器使用常規(guī)的實現(xiàn)方式就行,這里就不貼了
二、多行橫向分頁顯示

實現(xiàn)思路
- 使用ViewPager實現(xiàn)左右翻頁效果。
- 根據(jù)數(shù)據(jù)集合大小,計算出要顯示的頁數(shù),并生成相應(yīng)數(shù)量的GridView。
- 在GridView的Adapter適配器中,動態(tài)分配GridView需要顯示的數(shù)據(jù)集合。
- 使用List保存多個GridView實例并傳入ViewPager適配器中,一頁ViewPager對應(yīng)一個GridView實例。
具體實現(xiàn)
數(shù)據(jù)量很多時,需要進(jìn)行分頁,計算方式
需要頁數(shù) = 總數(shù)量 ÷ 每頁顯示數(shù)量
有些整除不了的,就需要使用Math.ceil()函數(shù),向上取整
關(guān)鍵代碼
/**
* 獲取系統(tǒng)所有的應(yīng)用程序,根據(jù)每頁需要顯示的item數(shù)量,生成相應(yīng)數(shù)量的GridView頁面
*/
private void initViews(List<ResolveInfo> datas) {
int dataSize = datas.size();
// (需要頁數(shù) = 總數(shù)量 ÷ 每頁顯示數(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ù)量 ÷ 每頁顯示數(shù)量剛好被整除時,會出現(xiàn)一頁空白頁的情況,這個時候需要去掉多出來的那一頁
if(dataSize % APP_SIZE == 0){
mGridViewList.remove(mGridViewList.size()-1);
PageCount--;
}
Adapter在創(chuàng)建初期就要對顯示的數(shù)據(jù)進(jìn)行控制,因為這里每個GridView都有一個單獨的Adapter,所以需要對其顯示的datas進(jìn)行動態(tài)計算
通過傳入構(gòu)造方法的數(shù)據(jù)進(jìn)行動態(tài)計算,可以得出數(shù)據(jù)開始加載的位置、結(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;
// 開始加載的位置
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++;
}
}
如果需要加小圓點的話,可以先在布局中用一個空LinearLayout當(dāng)小圓點的容器
<?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"/>
<!-- 底部小圓點 -->
<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>來保存創(chuàng)建的小圓點
// 放圓點的list
private List<View> dotViewsList;
/**
* 創(chuàng)建指定數(shù)量的圓點
* @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);
// 圓點與圓點之間的距離
params.leftMargin = 10;
params.rightMargin = 10;
// 圓點的大小
params.height = 15;
params.width = 15;
dotLayout.addView(dotView, params);
dotViewsList.add(dotView);
}
// 設(shè)置圓點默認(rèn)選中第一個
setDotShow(0);
}
動態(tài)添加完小圓點后,就可以設(shè)置它們的選中狀態(tài)了,這里只需要更改對應(yīng)小圓點的圖片顯示就行
/**
* 顯示底部圓點導(dǎo)航
* @param position 選中哪個圓點
*/
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橫向滾動的實現(xiàn)方式,其實我們完全可以不必這么麻煩,Google在support-v7包中為我們提供了RecyclerView控件,切換橫向和豎直滾動只需要讓布局管理器使用setOrientation方法設(shè)置一下就好,非常便捷,如果項目允許,建議使用RecyclerView來實現(xiàn)此類需求。
希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android開發(fā)之橫向滾動/豎向滾動的ListView(固定列頭)
- Android程序開發(fā)之ListView實現(xiàn)橫向滾動(帶表頭與固定列)
- Android使用GridView實現(xiàn)橫向滾動效果
- Android開發(fā)實現(xiàn)橫向列表GridView橫向滾動的方法【附源碼下載】
- Android GridView實現(xiàn)橫向列表水平滾動
- Android自定義ViewGroup實現(xiàn)可滾動的橫向布局(2)
- Android實現(xiàn)自定義的彈幕效果
- 實例解析如何在Android應(yīng)用中實現(xiàn)彈幕動畫效果
- Android 實現(xiàn)仿網(wǎng)絡(luò)直播彈幕功能詳解及實例
- Android實現(xiàn)橫向無限循環(huán)滾動的單行彈幕效果
相關(guān)文章
Android開發(fā)中Looper.prepare()和Looper.loop()
Looper用于封裝了android線程中的消息循環(huán),默認(rèn)情況下一個線程是不存在消息循環(huán)(message loop)的,具體調(diào)用方法大家可以通過本文學(xué)習(xí)2016-11-11
Android三種方式實現(xiàn)ProgressBar自定義圓形進(jìn)度條
這篇文章主要介紹了Android三種方式實現(xiàn)ProgressBar自定義圓形進(jìn)度條的相關(guān)資料,需要的朋友可以參考下2016-03-03
Android開發(fā):微信授權(quán)登錄與微信分享完全解析
本篇文章主要介紹了Android微信授權(quán)登錄與微信分享,具有一定的參考價值,有需要的可以了解一下。2016-11-11
Android設(shè)置個性化Dialog小圖標(biāo)的方法
這篇文章主要介紹了Android設(shè)置個性化Dialog小圖標(biāo)的方法,涉及Android針對系統(tǒng)資源的設(shè)置與調(diào)用相關(guān)操作技巧,需要的朋友可以參考下2016-08-08
Android自定義View實現(xiàn)水平帶數(shù)字百分比進(jìn)度條
這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)水平帶數(shù)字百分比進(jìn)度條,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12
Android提高之使用NDK把彩圖轉(zhuǎn)換灰度圖的方法
這篇文章主要介紹了Android使用NDK把彩圖轉(zhuǎn)換灰度圖的方法,在Android項目開發(fā)中有一定的實用價值,需要的朋友可以參考下2014-08-08

