zoukankan      html  css  js  c++  java
  • 高级UI-RecyclerView间隔线添加

    上文讲到了RecyclerView的简单使用,知道RecycleView是怎么使用的了,那么这一节将基于上一届的内容继续改进,在ListView中很轻松就能实现的间隔线,在RecycleView中也需要自己去实现,那么这一篇文章就来实现间隔线的添加,当然也包括边框线

    添加说明

    间隔线添加在线性布局中,边框线添加在网格布局中
    在RecycleView中,存在抽象类ItemDecoration,我们需要实现这个类,然后就可以愉快的画线了
    实现这个类,需要完成两个方法,一个是onDraw(),用于回调的绘制方法,一个是getItemOffsets(),用于得到Item的偏移量

    实现间隔线

    由于线性布局涉及到水平和竖直,所以这里也要做出相应的判断

    public class MyDividerItemDecoration extends RecyclerView.ItemDecoration {
        private int orientation = LinearLayoutManager.VERTICAL;
        private Drawable divider;
        private final int[] attrs = new int[]{android.R.attr.listDivider};
    
        public MyDividerItemDecoration(Context context, int orientation) {
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            divider = typedArray.getDrawable(0);
            typedArray.recycle();
            setOrientation(orientation);
        }
    
        public void setOrientation(int orientation) {
            if (orientation != LinearLayoutManager.VERTICAL
                    && orientation != LinearLayoutManager.HORIZONTAL) {
                throw new IllegalArgumentException("unsupport type");
            }
            this.orientation = orientation;
        }
    
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            if (orientation == LinearLayoutManager.VERTICAL) {
                outRect.set(0, 0, 0, divider.getIntrinsicHeight());
            } else {
                outRect.set(0, 0, divider.getIntrinsicWidth(), 0);
            }
        }
    
        //RecyclerView回调绘制方法
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            if (orientation == LinearLayoutManager.VERTICAL) {
                drawVertical(c, parent);
            } else {
                drawHorizontal(c, parent);
            }
            super.onDraw(c, parent, state);
        }
    
        private void drawHorizontal(Canvas c, RecyclerView parent) {
            int top = parent.getPaddingTop();
            int bottom = parent.getHeight() - parent.getPaddingBottom();
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                int left = child.getRight() + params.rightMargin + Math.round(ViewCompat.getTranslationX(child));
                int right = left + divider.getIntrinsicHeight();
                divider.setBounds(left, top, right, bottom);
                divider.draw(c);
            }
        }
    
        private void drawVertical(Canvas c, RecyclerView parent) {
            int left = parent.getPaddingLeft();
            int right = parent.getWidth() - parent.getPaddingRight();
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                int top = child.getBottom() + params.bottomMargin + Math.round(ViewCompat.getTranslationY(child));
                int bottom = top + divider.getIntrinsicHeight();
                divider.setBounds(left, top, right, bottom);
                divider.draw(c);
            }
        }
    }
    

    在线性布局中调用

    public class LineActivity extends AppCompatActivity {
    
        private RecyclerView recyclerView;
        private MyRecyclerViewAdapter adapter;
        private List<String> list;
        private MyDividerItemDecoration decor;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_line);
            recyclerView = (RecyclerView) findViewById(R.id.line_recyclerview);
            list = DataUtils.initData(100);
            adapter = new MyRecyclerViewAdapter(list);
            //设置点击监听
            adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    Toast.makeText(LineActivity.this, "点击 item " + position, Toast.LENGTH_SHORT).show();
                }
            });
            //设置样式,默认垂直
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
            //水平布局
            //recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true));
            //绘制间隔线
            if(decor != null){
                recyclerView.removeItemDecoration(decor);
            }
            decor = new MyDividerItemDecoration(this,LinearLayoutManager.VERTICAL);
            recyclerView.addItemDecoration(decor);
            recyclerView.setAdapter(adapter);
        }
    }
    

    实现效果如下图
    RecyclerView间隔线添加-RecyclerView间隔线

    实现边框线

    实现边框线和实现间隔线的思路一致,间隔线是绘制一侧,而边框线是绘制两侧,这是为了防止线条重合,造成整体不美观
    首先依旧是要实现ItemDecoration

    public class AroundItemDividerDecoration extends RecyclerView.ItemDecoration {
        private Drawable divider;
        private final int[] attrs = new int[]{android.R.attr.listDivider};
    
        public AroundItemDividerDecoration(Context context) {
            divider = context.getResources().getDrawable(R.drawable.item_divider);
        }
    
        @Override
        public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
            int right = divider.getIntrinsicWidth();
            int bottom = divider.getIntrinsicHeight();
            if (isLastColum(itemPosition, parent)) {
                right = 0;
            }
            if (isLastRow(itemPosition, parent)) {
                bottom = 0;
            }
            outRect.set(0, 0, right, bottom);
        }
    
        private boolean isLastRow(int itemPosition, RecyclerView parent) {
            int spanCount = getSpanCount(parent);
            if (spanCount == -1) {
                return false;
            }
            int childCount = parent.getAdapter().getItemCount();
            int lastRowCount = childCount % spanCount;
            if (lastRowCount == 0 || lastRowCount < spanCount) {
                return true;
            }
            return false;
        }
    
        private boolean isLastColum(int itemPosition, RecyclerView parent) {
            int spanCount = getSpanCount(parent);
            if (spanCount == -1) {
                return false;
            }
            if ((itemPosition + 1) % spanCount == 0) {
                return true;
            }
            return false;
        }
    
        private int getSpanCount(RecyclerView parent) {
            RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
            if (layoutManager instanceof GridLayoutManager) {
                GridLayoutManager grid = (GridLayoutManager) parent.getLayoutManager();
                int spanCount = grid.getSpanCount();
                return spanCount;
            }
            return -1;
        }
    
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            drawVertical(c, parent);
            drawHorizontal(c, parent);
        }
    
        private void drawHorizontal(Canvas c, RecyclerView parent) {
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                int left = child.getLeft() - params.leftMargin;
                int right = child.getRight() + params.rightMargin;
                int top = child.getBottom() + params.bottomMargin;
                int bottom = top + divider.getIntrinsicHeight();
                divider.setBounds(left, top, right, bottom);
                divider.draw(c);
            }
        }
    
        private void drawVertical(Canvas c, RecyclerView parent) {
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; i++) {
                View child = parent.getChildAt(i);
                RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
                int left = child.getRight() + params.rightMargin;
                int right = left + divider.getIntrinsicWidth();
                int top = child.getTop() - params.topMargin;
                int bottom = child.getBottom() + params.bottomMargin;
                divider.setBounds(left, top, right, bottom);
                divider.draw(c);
            }
        }
    }
    

    这里使用的是一个自定义的分割线

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
        <size
            android:width="2dp"
            android:height="2dp" />
        <solid android:color="#00ff00" />
    </shape>
    

    最后在网格布局中调用

    public class GridActivity extends AppCompatActivity {
        private RecyclerView recyclerView;
        private MyRecyclerViewAdapter adapter;
        private List<String> list;
        private AroundItemDividerDecoration decor;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_grid);
            recyclerView = (RecyclerView) findViewById(R.id.grid_recyclerview);
            list = DataUtils.initData(100);
            adapter = new MyRecyclerViewAdapter(list);
            //设置样式
            recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
            recyclerView.setAdapter(adapter);
            if(decor != null){
                recyclerView.removeItemDecoration(decor);
            }
            decor = new AroundItemDividerDecoration(this);
            recyclerView.addItemDecoration(decor);
        }
    }
    

    实现效果如下图所示
    RecyclerView间隔线添加-RecyclerView添加边框线

    补充:添加Item

    要添加Item,只要知道位置便可,在RecycleView中,数据刷新的方式更加高效,添加了很多局部刷新的方法
    在适配器中添加如下方法,便可实现数据添加,删除类似

    public void addData(int postion) {
        list.add(postion, "addItem" + postion);
        notifyItemInserted(postion);
    }
    

    然后在activity中调用,为了使画面不那么突兀,添加动画效果

    public class LineActivity extends AppCompatActivity {
    
        private RecyclerView recyclerView;
        private MyRecyclerViewAdapter adapter;
        private List<String> list;
        private MyDividerItemDecoration decor;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_line);
            recyclerView = (RecyclerView) findViewById(R.id.line_recyclerview);
            list = DataUtils.initData(100);
            adapter = new MyRecyclerViewAdapter(list);
            //设置点击监听
            adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(View view, int position) {
                    Toast.makeText(LineActivity.this, "点击 item " + position, Toast.LENGTH_SHORT).show();
                }
            });
            //设置样式,默认垂直
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
            //水平布局
            //recyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, true));
            //设置Item动画
            recyclerView.setItemAnimator(new DefaultItemAnimator());
            //绘制间隔线
            if(decor != null){
                recyclerView.removeItemDecoration(decor);
            }
            decor = new MyDividerItemDecoration(this,LinearLayoutManager.VERTICAL);
            adapter.notifyDataSetChanged();
            recyclerView.addItemDecoration(decor);
            recyclerView.setAdapter(adapter);
        }
    
        public void addItem(View view) {
            adapter.addData(2);
        }
    }
    

    实现效果如下
    RecyclerView间隔线添加-RecyclerView添加Item
    源代码:链接:https://pan.baidu.com/s/13wDP14_cTlrul-YJHgavgg 密码:7vr0

  • 相关阅读:
    vim可以打开,gvim无法打开
    Ubuntu用apt-get安装时依赖包无法安装
    如何用mm、mmm编译android中的模块
    装饰模式简单的代码
    FileWriter和FileReader简单使用
    TCP/IP、Http、Socket的区别--特别仔细
    surface实例-小球弹起事例
    android中图片的三级缓存cache策略(内存/文件/网络)
    接口回调
    大公司的Java面试题集
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664603.html
Copyright © 2011-2022 走看看