Android中如何实现多行、水平滚动的分页的Gridview?

功能要求:

(1)比如每页显示2X2,总共2XN,每个item显示图片+文字(点击有链接)。

如果单行水平滚动,可以用Horizontalscrollview实现。

如果是多行水平滚动,则结合Gridview(一般是垂直滚动的)和Horizontalscrollview实现。

(2)水平滚动翻页,下面有显示当前页的icon。

1.      实现自定义的HorizontalScrollView(HorizontalScrollView.java):

因为要翻页时需要传当前页给调用者,所以fling函数中自己实现而不要调用父类的fling。

[java] view plaincopy

  1. public class DrawerHScrollView extends HorizontalScrollView {
  2. private static final String TAG = "DrawerHScrollView";
  3. private IDrawerPresenter drawerPresenter = null;
  4. private int currentPage = 0;
  5. private int totalPages = 1;
  6. private static Hashtable<Integer, Integer> positionLeftTopOfPages = new Hashtable();
  7. public DrawerHScrollView(Context context) {
  8. super(context);
  9. }
  10. public DrawerHScrollView(Context context, AttributeSet attrs) {
  11. super(context, attrs);
  12. }
  13. public DrawerHScrollView(Context context, AttributeSet attrs, int defStyle) {
  14. super(context, attrs, defStyle);
  15. }
  16. public void cleanup(){
  17. currentPage = 0;
  18. totalPages = 1;
  19. drawerPresenter = null;
  20. if(positionLeftTopOfPages != null){
  21. positionLeftTopOfPages.clear();
  22. }
  23. }
  24. public void setParameters(int totalPages, int currentPage, int scrollDisX) {
  25. Log.d(TAG, "~~~~~setParameters totalPages:"+totalPages +",currentPage:"+ currentPage +",scrollDisX:"+scrollDisX);
  26. this.totalPages = totalPages;
  27. this.currentPage = currentPage;
  28. positionLeftTopOfPages.clear();
  29. for (int i = 0;i<totalPages;i++){
  30. int posx = (scrollDisX) * i;
  31. positionLeftTopOfPages.put(i, posx);
  32. Log.d(TAG, "~~~~~setParameters i:"+i +",posx:"+posx);
  33. }
  34. smoothScrollTo(0, 0);
  35. }
  36. public void setPresenter(IDrawerPresenter drawerPresenter ) {
  37. this.drawerPresenter = drawerPresenter;
  38. }
  39. @Override
  40. public void fling(int velocityX) {
  41. Log.v(TAG, "-->fling velocityX:"+velocityX);
  42. boolean change_flag = false;
  43. if (velocityX > 0 && (currentPage < totalPages - 1)){
  44. currentPage++;
  45. change_flag = true;
  46. } else if (velocityX < 0 && (currentPage > 0)){
  47. currentPage--;
  48. change_flag = true;
  49. }
  50. if (change_flag){
  51. int postionTo = (Integer)positionLeftTopOfPages.get(new Integer(currentPage)).intValue();
  52. Log.v(TAG, "------smoothScrollTo posx:"+postionTo);
  53. smoothScrollTo(postionTo, 0);
  54. drawerPresenter.dispatchEvent(totalPages, currentPage);
  55. }
  56. //super.fling(velocityX);
  57. }
  58. }

2.      布局文件Activity_main.xml:

[html] view plaincopy

  1. <com.example.multilinegridview.DrawerHScrollView
  2. android:id="@+id/hscrollview"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:layout_margin="10dp"
  6. android:scrollbars="none"
  7. android:layout_below="@id/layout_drawer_top"
  8. android:layout_above="@id/layout_pagenumber"
  9. android:background="#CCCCCC" >
  10. <LinearLayout
  11. android:layout_width="fill_parent"
  12. android:layout_height="wrap_content"
  13. android:orientation="horizontal" >
  14. <GridView
  15. android:id="@+id/gridView"
  16. android:layout_width="fill_parent"
  17. android:layout_height="wrap_content" />
  18. </LinearLayout>
  19. </com.example.multilinegridview.DrawerHScrollView>

3.      IDrawerPresenter接口(IDrawerPresenter.java):

[java] view plaincopy

  1. public interface IDrawerPresenter {
  2. IDrawerPresenter getInstance();
  3. void dispatchEvent(int totalPages, int currentPage);
  4. }

4.      DrawerItem

[html] view plaincopy

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/layout_item"
  3. android:orientation="vertical"
  4. android:layout_width="match_parent"
  5. android:layout_height="wrap_content"
  6. android:gravity="center"
  7. android:layout_gravity="center"
  8. android:background="#FFFFFF">
  9. <ImageView
  10. android:id="@+id/ivIcon"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:src="@drawable/ic_launcher"  />
  14. <TextView
  15. android:id="@+id/tvTitle"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:text="优惠券1"
  19. android:textColor="#000000"
  20. android:textStyle="bold"/>
  21. </LinearLayout>

5.      MainActivity.java

(1)实现IDrawerPresenter接口,在HorizontalScrollView里通过IDrawerPresenter接口来返回当前页,从而更新pageindicator。

[java] view plaincopy

  1. @Override
  2. public IDrawerPresenter getInstance() {
  3. return this;
  4. }
  5. @Override
  6. public void dispatchEvent(int totalPages, int currentPage) {
  7. Log.v(TAG, "~~~~dispatchEvent currentPage:" + currentPage);
  8. Message msg = Message.obtain();
  9. msg.what = MSG_DRAWER_UPDATE_PAGE_LAYOUT;
  10. msg.arg1 = totalPages;
  11. msg.arg2 = currentPage;
  12. handler.sendMessage(msg);
  13. }

(2)PageItemImageView和page indicator的更新

PageItemImageView显示normal的page indicator,之后再将当前页的图片换成selected。

[java] view plaincopy

  1. protected class PageItemImageView extends ImageView {
  2. public PageItemImageView(Context context) {
  3. super(context);
  4. Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
  5. R.drawable.icon_page_normal);
  6. this.setImageBitmap(bitmap);
  7. }
  8. public void updateDrawerPageLayout(int total_pages, int sel_page) {
  9. Log.e(TAG, "~~~updateBooksPageLayout total_pages:"+total_pages+",sel_page:"+sel_page);
  10. layout_pagenumber.removeAllViews();
  11. if (total_pages <= 0 || sel_page < 0 || sel_page >= total_pages){
  12. Log.e(TAG, "total_pages or sel_page is outofrange.");
  13. return;
  14. }
  15. for (int i = 0;i< total_pages;i++){
  16. if (i != 0){
  17. LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  18. params.setMargins(5, 0, 0, 0);
  19. layout_pagenumber.addView(new PageItemImageView(this), params);
  20. } else {
  21. layout_pagenumber.addView(new PageItemImageView(this));
  22. }
  23. }
  24. PageItemImageView selItem = (PageItemImageView) layout_pagenumber.getChildAt(sel_page);
  25. Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_page_selected);
  26. selItem.setImageBitmap(bitmap);

(3)DrawerListAdapter

[java] view plaincopy

  1. private class DrawerListAdapter extends BaseAdapter {
  2. private final String TAG = "MyListAdapter";
  3. private LayoutInflater mInflater;
  4. private LinearLayout layout_item;
  5. private TextView tvTitle;
  6. private ImageView ivIcon;
  7. private final Context context;
  8. private int colWid;
  9. private int colHei;
  10. public DrawerListAdapter(Context context, int colWid, int colHei) {
  11. this.context = context;
  12. this.colWid = colWid;
  13. this.colHei = colHei;
  14. mInflater = (LayoutInflater) context
  15. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  16. }
  17. public int getCount() {
  18. return drawerItemList.size();
  19. }
  20. public Object getItem(int position) {
  21. return drawerItemList.get(position);
  22. }
  23. public long getItemId(int position) {
  24. return position;
  25. }
  26. public View getView(int position, View convertView, ViewGroup parent) {
  27. DrawerItem item = drawerItemList.get(position);
  28. if (convertView == null) {
  29. convertView = mInflater.inflate(R.layout.drawer_item, null);
  30. layout_item = (LinearLayout) convertView
  31. .findViewById(R.id.layout_item);
  32. ivIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
  33. tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
  34. if (colHei != 0 && colWid != 0) {
  35. LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
  36. colWid, colHei - 30);
  37. ivIcon.setLayoutParams(params);
  38. }
  39. convertView.setTag(layout_item);
  40. } else {
  41. layout_item = (LinearLayout) convertView.getTag();
  42. }
  43. ivIcon.setImageResource(R.drawable.ic_launcher);
  44. tvTitle.setText(String.valueOf(position));
  45. return convertView;
  46. }
  47. }

(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;

}

[java] view plaincopy

  1. public void updateDrawerLayout() {
  2. if ((drawerItemList == null) || (drawerItemList.size() == 0)) {
  3. Log.d(TAG, "itemList is null or empty");
  4. return;
  5. }
  6. if (!hasMeasured){
  7. Log.d(TAG, "hasMeasured is false");
  8. return;
  9. }
  10. int scrollWid = hscrollview.getWidth();
  11. int scrollHei = hscrollview.getHeight();
  12. if (scrollWid <= 0 || scrollHei <= 0){
  13. Log.d(TAG, "scrollWid or scrollHei is less than 0");
  14. return;
  15. }
  16. int spaceing = 10;
  17. int colWid = (scrollWid - spaceing * 3) / 2;
  18. int colHei = (scrollHei - spaceing * 3) / 2;
  19. int numCols = (drawerItemList.size() - 1) / 2 + 1;
  20. int gridViewWid = numCols * colWid + (numCols + 1) * spaceing;
  21. // if numCols is odd (like 5), add blank space
  22. if (numCols % 2 == 1){
  23. gridViewWid += colWid + spaceing;
  24. }
  25. LayoutParams params = new LayoutParams(gridViewWid, scrollHei);
  26. gridView.setLayoutParams(params);
  27. gridView.setColumnWidth(colWid);
  28. gridView.setHorizontalSpacing(spaceing);
  29. gridView.setVerticalSpacing(spaceing);
  30. gridView.setStretchMode(GridView.NO_STRETCH);
  31. gridView.setNumColumns(numCols);
  32. adapter = new DrawerListAdapter(this, colWid, colHei);
  33. listener = new DrawerItemClickListener();
  34. gridView.setAdapter(adapter);
  35. gridView.setOnItemClickListener(listener);
  36. int pageNum = (drawerItemList.size() - 1) / 4 + 1;
  37. hscrollview.setParameters(pageNum, 0, scrollWid - spaceing);
  38. updateDrawerPageLayout(pageNum, 0);
  39. }

效果图:

时间: 2024-10-09 00:58:25

Android中如何实现多行、水平滚动的分页的Gridview?的相关文章

Android中仿淘宝首页顶部滚动自定义HorizontalScrollView定时水平自动切换图片

Android中仿淘宝首页顶部滚动自定义HorizontalScrollView定时水平自动切换图片 自定义ADPager 自定义水平滚动的ScrollView效仿ViewPager 当遇到要在ViewPager中添加多张网络请求图片的情况下,不能进行复用,导致每次都要重新去求情已经请求过的数据致使流量数据过大 自定义的数据结构解决了这个问题,固定传递的图片数据之后进行统一请求,完成后进行页面切换数据复用 代码中涉及网络请求是用的Volley网络请求框架 PicCarousel是网络数据请求的U

在ASP.NET MVC5中实现具有服务器端过滤、排序和分页的GridView

背景 在前一篇文章<[初学者指南]在ASP.NET MVC 5中创建GridView>中,我们学习了如何在 ASP.NET MVC 中实现 GridView,类似于 ASP.NET web 表单的功能.通过前文,我们已经了解到使用 jQuery 插件的数据表可以很容易地实现具有搜索.排序和分页等重要功能的表格. 前文中需要注意的是,所有通过插件实现的特性都是客户端的,这意味着所有的数据都首先在页面载入,然后由插件来处理客户端搜索.分页和排序的数据.如果数据表不是特别大,这么做是可以的:但是,如

Android中如何使用命令行查看内嵌数据库SQLite3

在上图中,除了最后一个红色的方框,其它方框都是adb shell下的命令. [1]在Android程序中,一般创建的数据库存放在 /data/data/[应用程序包名]/databases 的目录下. [2]cd 命令:文件夹跳转命令.ls 命令:查看某个文件夹下面有哪些文件. [3]使用 "sqlite3 [数据库名称] " 命令来对某数据库进行一系列的操作. [4]在经过第[3]步骤后,可以使用 .tables 命令查看某数据库中包含哪些表.若要查询某表中包含的数据,在 sqlit

Android中Gallery和ImageSwitcher同步自动(滚动)播放图片库

本文主要内容是如何让Gallery和ImageSwitcher控件能够同步自动播放图片集 ,看起来较难,然而,实现的方法非常简单, 请跟我慢慢来.总的来说,本文要实现的效果如下图:(截图效果不怎么好) 本文是建立在以下两篇bolg上的:      1.Android入门第十二篇之Gallery                  2.Android 控件之ImageSwitcher图片切换器 如果对Gallery和ImageSwitcher控件不是很熟悉的同学,建议先过去看看,本文并没有怎么讲述控

Android ViewPager实现多个图片水平滚动

1.示意图                       2.实现分析 (1).xml配置 <!-- 配置container和pager的clipChildren=false, 并且指定marginLeft 和 marginRight 的值--> <LinearLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height=&qu

Android 中旋转屏幕,触摸,滚动

package com.learingselenium.android; import junit.framework.TestCase import org.openqa.selenium.Rotatable; import org.openqa.selenium.ScreenOrientation; import org.openqa.selenium.WebDriver; import org.openqa.selenium.android.AndroidDriver; import or

Android中通过Java代码实现ScrollView滚动视图-以歌词滚动为例

场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改为LinearLayout,并通过android:orientation="vertical">设置为垂直布局,然后添加id属性,并设置内边距 <?xml version="1.0" encoding="utf-8"?> <L

Android学习——HorizontalScollview水平滚动控件

HorizatalScollView控件只是支持水平滚动,而且它只能包含一个控件,通常是在<HorizatalScollView>标签中定义一个<LinearLayout> 标签并且在<LinearLayout>标签中android:orientation属性值设置为horization.然后在<LinearLayout>标签中放置多个控件,如果<LinearLayout>标签中的控件所占的总宽度超出屏幕的宽度,就会出现滚动效果. <Lin

解决Android中,禁止ScrollView内的控件改变之后自动滚动

问题: 最近在写一个程序界面,有一个scrollVIew,其中有一段内容是需要在线加载的. 当内容加载完成后,ScrollView中内容的长度会发生改变,这时ScrollView会自动下滚,如下图所示: 滚动的那一下体验特别不好,所以要防止这种情况.即不论Scrollview中内容如何,都要保持在最上. 解决办法: 先简单写一下我的xml文件的结构: [html] view plaincopy <ScrollView android:id="@+id/scrollView1" a