一个简单的RecyclerView多布局实现

实现一个简单的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<hotPlaceHidePosition.length;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<Build.VERSION_CODES.LOLLIPOP)
        {
//            下面这句话必须的
            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 包含子元素的个数。

猜你喜欢

转载自blog.csdn.net/handsonn/article/details/52850815