android网格导航的实现

如今的很多app都在首页有一个可以滑动的导航,像美团App在首页上也有,如图:

还有很多的app也有,比如京东、饿了么等等,这个功能实现起来其实也不难,有RecycleView就可以,因为RecycleView有一个网格的布局,但是为了使用方便,还有就是以后其他的项目也需要用到,所以我把这个功能做了一个封装,全都封装在一个.java类里面,使用的时候就只需要在布局中引用该控件,同时在Activity或是Fragment中添加几行代码就可以使用整个功能。

我封装的类名为EntryListView.java,将这个类放到自己的项目中。

一。先看使用方式

在布局中引用该控件

在布局对应activity或是Fragment中添加如下代码

mEntryList是我封装的EntryListView.java这个类的对象,第一行代码是设置行数跟列数,第二行代码中的listEntry是一个List对象,里面存放着每个item的内容,比如可以这样写,其中Entry.java是存放信息的实体类

好了这样就可以实现整个功能了,给大家看一下我自己这边的效果图

二。简单说一下我封装的EntryListView.java里面实现的原理,我这里使用的是ViewPager来实现滑动切换的,ViewPager的每一页都是一个GridView,这个大家都知道,他就是网格布局,然后网格布局里面的每一个item,就是一个图标跟一个标题,整个过程都是动态创建布局,没有引用到布局文件,只有这样移植性才比较强,只需要把我的这个EntryListView.java引用到自己的项目中,通过上面的方法是使用,就可以了。

下面是大家关系的问题,那就是源码啦,下面就是源码,里面注释很清晰,看了都懂,直接拿走不谢,觉得好的话多关注点个喜欢就行(微笑)

package qin.zszc.com.basiclib.widget.custom.entrynavigation;


import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;

import qin.zszc.com.basiclib.R;
import qin.zszc.com.basiclib.support.imageloader.ImageLoader;
import qin.zszc.com.basiclib.widget.custom.entrynavigation.model.Entry;

/**
 * Created by xcfor on 2018/7/11.
 * 首页导航栏
 */

public class EntryListView extends FrameLayout implements ViewPager.OnPageChangeListener {

    private final int IND_WIDTH_SIZE = 6; //指示器默认宽的长度

    private Context mContext;
    private ViewPager mViewPager;
    private PagerAdapter mAdapter;
    private MyGridViewAdapter mMyGridViewAdpter;
    private LinearLayout mIndecatorLayout;

    private int mColumNum = 5;//多少列
    private int mRowNum = 2;//多少行
    private int mPageSize = 8;//每页多少个
    private int mCount;//滑动页面的数量
    private int mPrePosition = 0; //历史页pos
    private int mIndicatorWidth;//指示器宽度
    private int mIndicatorHight = 3;//指示器高度
    private int mCurrentPos = 0;//当前页pos
    private int mIconSize = 40; //item中图片的宽高
    private int mTextSize = 11; //item中字体的大小

    private List<List<Entry>> mResultList;//分页后的数据列表
    private List<Entry> mLists;//获取到的数据列表
    private List<View> mItemView = new ArrayList<>();//存放gridView的列表

    public EntryListView(@NonNull Context mContext) {
        super(mContext);
        this.mContext = mContext;
    }

    public EntryListView(@NonNull Context mContext, @Nullable AttributeSet attrs) {
        super(mContext, attrs);
        this.mContext = mContext;
    }

    public EntryListView(@NonNull Context mContext, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(mContext, attrs, defStyleAttr);
        this.mContext = mContext;
    }

    public void setPageSize(int rowNum,int colNum){
        mRowNum=rowNum;
        mColumNum=colNum;
        mPageSize=rowNum*colNum;
    }

    public void init() {
        if (mAdapter == null) {
            return;
        }
        mViewPager.setAdapter(mAdapter);

        //切换画面
        mViewPager.setPageTransformer(true, new EntryListView.MyPageTransformer());
        mIndecatorLayout.removeAllViews();

        //向线性布局中添加小圆点指示器
        View line;
        LinearLayout.LayoutParams params;
        for (int i = 0; i < mCount; i++) {
            line = new View(mContext);
            line.setId(i);
            params = new LinearLayout.LayoutParams(dip2px(mIndicatorWidth), dip2px(mIndicatorHight));
            params.setMargins(dip2px(3), 0, dip2px(3), 0);
            line.setLayoutParams(params);
            line.setBackgroundResource(R.drawable.basiclib_line_bg_selector);
            line.setEnabled(false);//默认设为非选中
            mIndecatorLayout.setGravity(Gravity.CENTER_HORIZONTAL);
            mIndecatorLayout.addView(line);
        }
        mIndecatorLayout.getChildAt(0).setEnabled(true);
        mViewPager.setCurrentItem(0);
    }

    /**
     * 获取数据
     * @param mLists
     */
    public void setData(List<Entry> mLists) {
        if (mLists.isEmpty()) {
            return;
        }
        this.mLists = mLists;
        mCount = pageNum();
        cutOutList(mLists, mPageSize);
        if (mAdapter == null) {
            mAdapter = new EntryListView.MyEntryAdapter(mItemView);
        }
        init();
    }

    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     */
    private int dip2px(float dpValue) {
        final float scale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    /**
     * 按照size的大小截取list
     *
     * @param lists
     * @param size
     * @return
     */
    public List<List<Entry>> cutOutList(List<Entry> lists, int size) {
        mResultList = new ArrayList<>();
        int arrSize = lists.size() % size == 0 ? lists.size() / size : lists.size() / size + 1;
        for (int i = 0; i < arrSize; i++) {
            List<Entry> sub = new ArrayList<>();
            for (int j = i * size; j <= size * (i + 1) - 1; j++) {
                if (j <= lists.size() - 1) {
                    sub.add(lists.get(j));
                }
            }
            mResultList.add(sub);
        }
        return mResultList;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        //初始化Viewpager(应用入口列表)
        mIndicatorWidth = dip2px(IND_WIDTH_SIZE);
        LinearLayout llContent = new LinearLayout(mContext);
        llContent.setOrientation(LinearLayout.VERTICAL);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        mViewPager = new customViewPager(mContext);
        mViewPager.setLayoutParams(params);
        llContent.addView(mViewPager);

        //初始化指示器容器
        mIndecatorLayout = new LinearLayout(mContext);
        params.bottomMargin = 28;
        mIndecatorLayout.setLayoutParams(params);
        mIndecatorLayout.setOrientation(LinearLayout.HORIZONTAL);
        llContent.addView(mIndecatorLayout);
        mViewPager.addOnPageChangeListener(this);
        addView(llContent);
    }


    /**
     * 计算出页面的数量
     * @return
     */
    public int pageNum() {
        if (mLists.size() % mPageSize != 0 && mLists.size() / mPageSize < 1) {
            mCount = 1;
        } else if (mLists.size() % mPageSize != 0 && mLists.size() / mPageSize >= 1) {
            mCount = mLists.size() / mPageSize + 1;
        } else {
            mCount = mLists.size() / mPageSize;
        }
        return mCount;
    }


    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        mCurrentPos = position;
        mIndecatorLayout.getChildAt(mPrePosition % mCount).setEnabled(false);
        mIndecatorLayout.getChildAt(mCurrentPos % mCount).setEnabled(true);//设置true放后面,防止初始化时两个pos都为0时。没有默认选中
        mPrePosition = mCurrentPos;
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }


    /**
     * 导航Viewpager的适配器,向ViewPager的每一个页中添加一个GridView
     */
    class MyEntryAdapter extends PagerAdapter {
        List<View> listItem;//前面加类型

        public MyEntryAdapter(List<View> itemView) {
            this.listItem = itemView;
        }

        @Override
        public int getCount() {
            return mCount;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            //向Viewpager每一页中添加一个gridView布局
            for (int i = 0; i < mCount; i++) {
                GridView gridView = new CustomGridView(mContext);
                gridView.setNumColumns(mColumNum);
                gridView.setGravity(Gravity.CENTER);
                gridView.setPadding(2, 2, 2, 0);
                listItem.add(gridView);
                mMyGridViewAdpter = new MyGridViewAdapter(mContext, mResultList.get(i), 0, mPageSize);
                gridView.setAdapter(mMyGridViewAdpter);
            }
            container.addView(listItem.get(position));
            return listItem.get(position);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }


    /**
     * 导航gridView的适配器,向gridView的每一项中添加信息
     */
    class MyGridViewAdapter extends BaseAdapter {

        private Context context;
        private List<Entry> lists;
        private int index;//页数小标,标示第几页,从0开始
        private int mPargerSize;//每页显示的最大的数量

        public MyGridViewAdapter(Context context, List<Entry> lists, int index, int mPargerSize) {
            this.context = context;
            this.lists = lists;
            this.index = index;
            this.mPargerSize = mPargerSize;
        }

        @Override
        public int getCount() {
            return lists.size() > (index + 1) * mPargerSize ?
                    mPargerSize : (lists.size() - index * mPargerSize);
        }

        @Override
        public Object getItem(int i) {
            return lists.get(i + index * mPargerSize);
        }

        @Override
        public long getItemId(int i) {
            return i + index * mPargerSize;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            return addGridViewChildLayout(view, i);
        }

        /**
         * 动态创建gridView的子布局
         *
         * @param view
         */
        public View addGridViewChildLayout(View view, int pos) {
            LinearLayout ll = new LinearLayout(context);
            GridView.LayoutParams llparams = new GridView.LayoutParams(GridView.LayoutParams.MATCH_PARENT, GridView.LayoutParams.MATCH_PARENT);
            ll.setOrientation(LinearLayout.VERTICAL);
            ll.setLayoutParams(llparams);
            ll.setPadding(0, dip2px(10), 0, 0);
            ll.setGravity(Gravity.CENTER);
            LinearLayout.LayoutParams img_params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            LinearLayout.LayoutParams tv_params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            ImageView img = new ImageView(context);
            img.setScaleType(ImageView.ScaleType.FIT_XY);
            img_params.gravity = Gravity.CENTER;
            img_params.width = dip2px(mIconSize);
            img_params.height = dip2px(mIconSize);
            img.setLayoutParams(img_params);
            ll.addView(img);
            TextView textView = new TextView(context);
            textView.setTextSize(mTextSize);
            textView.setTextColor(getResources().getColor(R.color.basiclib_colorBack));
            textView.setPadding(0, 20, 0, 0);
            textView.setLayoutParams(tv_params);
            ll.addView(textView);
            view = ll;
            ImageLoader.display(lists.get(pos).getEntryIocn(),img,R.mipmap.basicres_picture_default,R.mipmap.basicres_picture_default);
            textView.setText(lists.get(pos).getEntryName());
            return view;
        }

    }

    /**
     * 定义viewpager滑动效果
     */
    private class MyPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View page, float position) {
            final float normalizedposition = Math.abs(Math.abs(position) - 1);
            page.setAlpha(normalizedposition);
        }
    }

    /**
     * 自定义Viewpager,计算viewPager高度
     */
    private class customViewPager extends ViewPager {

        public customViewPager(Context context) {
            super(context);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int height = 0;
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                child.measure(widthMeasureSpec,
                        MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                int h = child.getMeasuredHeight();
                if (h > height)
                    height = h;
            }
            heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                    MeasureSpec.EXACTLY);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    /**
     * 自定义GridView,计算GridView高度
     */
    private class CustomGridView extends GridView {
        public CustomGridView(Context context) {
            super(context);
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
                    MeasureSpec.AT_MOST);
            super.onMeasure(widthMeasureSpec, expandSpec);
        }
    }

}
原创文章 10 获赞 29 访问量 2万+

猜你喜欢

转载自blog.csdn.net/taoyuxin1314/article/details/82051242
今日推荐