实现一个简单的item多布局,当做记录,主要是通过不同的itemType来实现,先放上我的实现效果,运行使用的是 API19的模拟器,如下,图片大都是百度的:
由于使用了百分比布局,所以横屏的也顺便适配了,横屏的如下,
需要注意一下这些地方:
1、由于我的最外层布局使用的是 viewpager + fragment,在轮播图下面几个圆形按钮的布局(第二个itemType)也是fragment,所以在第二个itemType 里面需要使用 getChildFragmentManager()
而不是 getFragmentManager(),否则会造成 最下面导航栏切换 fragment 时,切换页面之后 第二个itemType 的圆形图标加载不出来(try try),这是因为变成了是fragment管理子fragment,所以需要这样设置;
2、轮播图使用的是 github 的一个开源:
https://github.com/youth5201314/banner
也可以自己写,里面给的圆形指示器设置了大小和高度,所以我们需要通过反射来修改(如果是自定义指示器的话),或者通过一组圆形指示器图片来直接使用也可以,反射如下:
int testDp = ***;
Field field = banner.getClass().getDeclaredField("mIndicatorMargin");
field.setAccessible(true);
field.set(banner,testDp);
3、第二个itemType 的圆形指示器就通过xml来画,通过一个 linearLayout 动态添加即可:
for(int i=0;i<3;i++)
{
// 设置圆圈点
View view = new View(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(10,10);
params.leftMargin = 20;
view.setBackgroundResource(R.drawable.point_background);
view.setLayoutParams(params);
view.setEnabled(false);
linearLayout.addView(view);
}
4、还有一个是最后的itemType的实现,可以看到有三个有停车场的标志,有两个没有,所以需要让没有点设置为INVISIBLE,在onBindViewHolder中添加如下代码:
if(position != 3)
holder.hot_title_place.setVisibility(View.GONE);
for(int i = 0;i<hotPlaceHidePosition.length;i++)
{
if (position == hotPlaceHidePosition[i])
{
holder.stop_car_sign.setVisibility(View.INVISIBLE);
}
}
但是上面这个会出现 bug,就是下拉刷新之后停车场没有设置为INVISIBLE 标志也会随机的不见,开始可能有一个,也可能是两个,最后全部都消失,旋转屏幕之后回来又恢复正常,所以需要设置成如下:
holder.hot_title_place.setVisibility(View.VISIBLE);
if(position != 3)
holder.hot_title_place.setVisibility(View.GONE);
holder.stop_car_sign.setVisibility(View.VISIBLE);
for(int i = 0;i
{
if (position == hotPlaceHidePosition[i])
{
holder.stop_car_sign.setVisibility(View.INVISIBLE);
}
}
我开始是想通过 layoutManager 来获取每个 item 之后隐藏,如下:
@Override
public void onAttachedToRecyclerView(final RecyclerView recyclerView)
{
super.onAttachedToRecyclerView(recyclerView);
Toast.makeText(context,"onAttachedToRecyclerView",Toast.LENGTH_SHORT).show();
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if(manager instanceof LinearLayoutManager)
{
View view = manager.findViewByPosition(5);
ImageView imageView = (ImageView) view.findViewById(R.id.stop_car_sign);
imageView.setVisibility(View.INVISIBLE);
}
}
但是这样无效,同样,通过如下开始运行时候可以,但是由于它获取的是可见屏幕的位置,所以会导致隐藏位置不确定,代码如下,同样在 onAttachedToRecyclerView 中添加:
recyclerView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int width = recyclerView.getWidth();
int height = recyclerView.getHeight();
if (width > 0 && height > 0) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
recyclerView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
View firstRecyclerViewItem = recyclerView.getLayoutManager().findViewByPosition(0);
}
});
所以需要在 onBindViewHolder 中设置。
5、状态栏着色使用了 systembartint,封装了一下:
public class MethodUtil
{
private SystemBarTintManager tintManager;
private static MethodUtil methodUtil;
public static MethodUtil getMethodUtil()
{
if(methodUtil == null)
methodUtil = new MethodUtil();
return methodUtil;
}
/*
* 通知栏统一颜色,沉浸式
* */
public void systemBarColorUtil(Context context,int color)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
&& Build.VERSION.SDK_INT// 下面这句话必须的
getActivity(context).getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
tintManager = new SystemBarTintManager(getActivity(context));
tintManager.setStatusBarTintEnabled(true);
tintManager.setTintResource(color);//通知栏所需颜色
}
}
/*
* 通过获取 context 获取activity
* */
private Activity getActivity(Context context)
{
while(!(context instanceof Activity) && context instanceof ContextWrapper)
{
context = ((ContextWrapper) context).getBaseContext();
}
if(context instanceof Activity)
{
return (Activity)context;
}
throw new ActivityNotFoundException("Unable to get Activity");
}
}
其它的都很简单,就是注意百分比布局的使用,通过 itemType同样 也可以添加上拉刷新,刷新数据可以写个观察者模式或者使用广播、EventBus,加载图片用的是Glide,并且这里没有使用Glide的缓存,代码还有很多欠缺,菜鸟一枚,权当记录。
代码放在这里:
https://github.com/laymanZ/SimpleRecyclerViewItem
6、上面这种实现的方法使用了多个fragment,另一种可以直接使用一个gridLayoutManager 和 一个 recyclerview 即可,通过重写 grdiLayoutManager 的 setSpanSizeLookup 方法,代码如下:
final GridLayoutManager gridLayoutManager = new GridLayoutManager(this,2);
gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup()
{
@Override
public int getSpanSize(int position)
{
int type = mRecyclerView.getAdapter().getItemViewType(position);
if(type == DataModel.TYPE_THREE)
return gridLayoutManager.getSpanCount();
else
return 1;
}
});
mRecyclerView.setLayoutManager(gridLayoutManager);
如上,gridLayoutManager 是 列数为 2 的管理器,在getSpanSize里面,return 1
则表示返回的布局大小占一行的 1/2
,因为 上面声明的是 2 列,即分母为 2 ,下面 return 1中1是分子,所以如果想要占满整个 Item 的话,return 2 即可,即 2/2
(如果声明列数为3,return 1 即表示 占一个 item的 1/3,有点啰嗦,哈哈), 在这里 return 2 也就是 return gridLayoutManager.getSpanCount(),数据不会写死。所以,只要使用一个 gridLayoutManager 和 最外层 一个 recyclerview 即可,通过不同 type 来设置每一行的item 包含子元素的个数。