Android中如何實現多行、水平滾動的分頁的Gridview?
功能要求:
(1)比如每頁顯示2X2,總共2XN,每個item顯示圖片+文字(點選有連結)。
如果單行水平滾動,可以用Horizontalscrollview實現。
如果是多行水平滾動,則結合Gridview(一般是垂直滾動的)和Horizontalscrollview實現。
(2)水平滾動翻頁,下面有顯示當前頁的icon。
1. 實現自定義的HorizontalScrollView(HorizontalScrollView.java):
因為要翻頁時需要傳當前頁給呼叫者,所以fling函式中自己實現而不要呼叫父類的fling。
public class DrawerHScrollView extends HorizontalScrollView { private static final String TAG = "DrawerHScrollView"; private IDrawerPresenter drawerPresenter = null; private int currentPage = 0; private int totalPages = 1; private static Hashtable<Integer, Integer> positionLeftTopOfPages = new Hashtable(); public DrawerHScrollView(Context context) { super(context); } public DrawerHScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public DrawerHScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void cleanup(){ currentPage = 0; totalPages = 1; drawerPresenter = null; if(positionLeftTopOfPages != null){ positionLeftTopOfPages.clear(); } } public void setParameters(int totalPages, int currentPage, int scrollDisX) { Log.d(TAG, "~~~~~setParameters totalPages:"+totalPages +",currentPage:"+ currentPage +",scrollDisX:"+scrollDisX); this.totalPages = totalPages; this.currentPage = currentPage; positionLeftTopOfPages.clear(); for (int i = 0;i<totalPages;i++){ int posx = (scrollDisX) * i; positionLeftTopOfPages.put(i, posx); Log.d(TAG, "~~~~~setParameters i:"+i +",posx:"+posx); } smoothScrollTo(0, 0); } public void setPresenter(IDrawerPresenter drawerPresenter ) { this.drawerPresenter = drawerPresenter; } @Override public void fling(int velocityX) { Log.v(TAG, "-->fling velocityX:"+velocityX); boolean change_flag = false; if (velocityX > 0 && (currentPage < totalPages - 1)){ currentPage++; change_flag = true; } else if (velocityX < 0 && (currentPage > 0)){ currentPage--; change_flag = true; } if (change_flag){ int postionTo = (Integer)positionLeftTopOfPages.get(new Integer(currentPage)).intValue(); Log.v(TAG, "------smoothScrollTo posx:"+postionTo); smoothScrollTo(postionTo, 0); drawerPresenter.dispatchEvent(totalPages, currentPage); } //super.fling(velocityX); } }
2. 佈局檔案Activity_main.xml:
<com.example.multilinegridview.DrawerHScrollView android:id="@+id/hscrollview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" android:scrollbars="none" android:layout_below="@id/layout_drawer_top" android:layout_above="@id/layout_pagenumber" android:background="#CCCCCC" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <GridView android:id="@+id/gridView" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> </com.example.multilinegridview.DrawerHScrollView>
3. IDrawerPresenter介面(IDrawerPresenter.java):
public interface IDrawerPresenter {
IDrawerPresenter getInstance();
void dispatchEvent(int totalPages, int currentPage);
}
4. DrawerItem
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout_item" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_gravity="center" android:background="#FFFFFF"> <ImageView android:id="@+id/ivIcon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/tvTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="優惠券1" android:textColor="#000000" android:textStyle="bold"/> </LinearLayout>
5. MainActivity.java
(1)實現IDrawerPresenter介面,在HorizontalScrollView裡通過IDrawerPresenter介面來返回當前頁,從而更新pageindicator。
@Override
public IDrawerPresenter getInstance() {
return this;
}
@Override
public void dispatchEvent(int totalPages, int currentPage) {
Log.v(TAG, "~~~~dispatchEvent currentPage:" + currentPage);
Message msg = Message.obtain();
msg.what = MSG_DRAWER_UPDATE_PAGE_LAYOUT;
msg.arg1 = totalPages;
msg.arg2 = currentPage;
handler.sendMessage(msg);
}
(2)PageItemImageView和page indicator的更新
PageItemImageView顯示normal的page indicator,之後再將當前頁的圖片換成selected。
protected class PageItemImageView extends ImageView {
public PageItemImageView(Context context) {
super(context);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.icon_page_normal);
this.setImageBitmap(bitmap);
}
}
public void updateDrawerPageLayout(int total_pages, int sel_page) {
Log.e(TAG, "~~~updateBooksPageLayout total_pages:"+total_pages+",sel_page:"+sel_page);
layout_pagenumber.removeAllViews();
if (total_pages <= 0 || sel_page < 0 || sel_page >= total_pages){
Log.e(TAG, "total_pages or sel_page is outofrange.");
return;
}
for (int i = 0;i< total_pages;i++){
if (i != 0){
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(5, 0, 0, 0);
layout_pagenumber.addView(new PageItemImageView(this), params);
} else {
layout_pagenumber.addView(new PageItemImageView(this));
}
}
PageItemImageView selItem = (PageItemImageView) layout_pagenumber.getChildAt(sel_page);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_page_selected);
selItem.setImageBitmap(bitmap);
}
(3)DrawerListAdapter
private class DrawerListAdapter extends BaseAdapter {
private final String TAG = "MyListAdapter";
private LayoutInflater mInflater;
private LinearLayout layout_item;
private TextView tvTitle;
private ImageView ivIcon;
private final Context context;
private int colWid;
private int colHei;
public DrawerListAdapter(Context context, int colWid, int colHei) {
this.context = context;
this.colWid = colWid;
this.colHei = colHei;
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return drawerItemList.size();
}
public Object getItem(int position) {
return drawerItemList.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
DrawerItem item = drawerItemList.get(position);
if (convertView == null) {
convertView = mInflater.inflate(R.layout.drawer_item, null);
layout_item = (LinearLayout) convertView
.findViewById(R.id.layout_item);
ivIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
if (colHei != 0 && colWid != 0) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
colWid, colHei - 30);
ivIcon.setLayoutParams(params);
}
convertView.setTag(layout_item);
} else {
layout_item = (LinearLayout) convertView.getTag();
}
ivIcon.setImageResource(R.drawable.ic_launcher);
tvTitle.setText(String.valueOf(position));
return convertView;
}
}
(4)DrawerItemClickListener:
實現OnItemClickListener。(5) updateDrawerLayout
獲得data的size後,可以算出列數來得到固定行。
intnumCols = (drawerItemList.size() - 1) / 2 + 1
再算出gridview的width。因每頁可顯示2列,最後一頁可能右側沒有,為了翻頁順滑,可以給gridview增加一列空白。
intgridViewWid = numCols * colWid + (numCols + 1) * spaceing;
if(numCols % 2 == 1){
gridViewWid+= colWid + spaceing;
}
public void updateDrawerLayout() {
if ((drawerItemList == null) || (drawerItemList.size() == 0)) {
Log.d(TAG, "itemList is null or empty");
return;
}
if (!hasMeasured){
Log.d(TAG, "hasMeasured is false");
return;
}
int scrollWid = hscrollview.getWidth();
int scrollHei = hscrollview.getHeight();
if (scrollWid <= 0 || scrollHei <= 0){
Log.d(TAG, "scrollWid or scrollHei is less than 0");
return;
}
int spaceing = 10;
int colWid = (scrollWid - spaceing * 3) / 2;
int colHei = (scrollHei - spaceing * 3) / 2;
int numCols = (drawerItemList.size() - 1) / 2 + 1;
int gridViewWid = numCols * colWid + (numCols + 1) * spaceing;
// if numCols is odd (like 5), add blank space
if (numCols % 2 == 1){
gridViewWid += colWid + spaceing;
}
LayoutParams params = new LayoutParams(gridViewWid, scrollHei);
gridView.setLayoutParams(params);
gridView.setColumnWidth(colWid);
gridView.setHorizontalSpacing(spaceing);
gridView.setVerticalSpacing(spaceing);
gridView.setStretchMode(GridView.NO_STRETCH);
gridView.setNumColumns(numCols);
adapter = new DrawerListAdapter(this, colWid, colHei);
listener = new DrawerItemClickListener();
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(listener);
int pageNum = (drawerItemList.size() - 1) / 4 + 1;
hscrollview.setParameters(pageNum, 0, scrollWid - spaceing);
updateDrawerPageLayout(pageNum, 0);
}
效果圖: