如今的很多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);
}
}
}