• 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);
        }

    效果图:

  • 相关阅读:
    [Leetcode] Symmetric tree 对称二叉树
    [Leetcode] Populating next right pointer in each node ii 填充每个节点的右指针
    [Leetcode] Populating next right pointer in each node 填充每个节点的右指针
    [Leetcode] Same tree判断是否为相同树
    [Leetcode] Path Sum II路径和
    [Leetcode] Path Sum路径和
    [Leetcode] Binary tree maximum path sum求二叉树最大路径和
    [Leetcode] The minimum depth of binary tree二叉树的最小深度
    设计模式-工厂方法模式
    设计模式-简单工厂模式
  • 原文地址:https://www.cnblogs.com/a354823200/p/3918961.html
Copyright © 2020-2023  润新知