绘制带有边框线的ListView

  • Post author:
  • Post category:其他


先看看效果

列表内容没有填满控件

列表内容填满控件

1.在布局文件中定义ListView和它的父控件RelativeLayout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.vieboo.ltline.MainActivity"
    android:padding="10dp"
    android:id="@+id/layout_main">

    <include
        android:id="@+id/layout_top"
        layout="@layout/layout_list_item" />

    <ListView
        android:id="@+id/list_view"
        android:layout_below="@+id/layout_top"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>

</RelativeLayout>

2.自定义一个继承自View的LineCanvasView类,来实现画线

  1. 将标题行View(也就是ListView的itemView)传入LineCanvasView中
  2. 重写onDraw(Canvas canvas)方法,根据标题行View的宽高和ListView的宽高来计算线的位置,最后绘制边框线
@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.TRANSPARENT);
        //listview的item的高度(标题行的高度)
        int childHeight = layout_title.getHeight();
        //listview加标题总高度
        int totalHeight = listView.getHeight() + childHeight;
        //listview宽度
        int width = listView.getWidth();
        //横向子view的数量
        int countHorizontal = layout_title.getChildCount();
        //纵向最大行数
        int countVerticalLine = totalHeight / childHeight;
        //listview当前显示列表数量
        int itemCount = listView.getChildCount();

        /**
         * listview数据不够填满整页时
         */
        if(itemCount < countVerticalLine) {
            totalHeight = countVerticalLine * childHeight;
            //竖线
            canvas.drawLine(0, 0, 1, totalHeight, mPaint);
            for(int i=0; i<countHorizontal; i++) {
                View childView = layout_title.getChildAt(i);
                float startX = childView.getX() + childView.getWidth();
                canvas.drawLine(startX - 1, 0, startX, totalHeight, mPaint);
            }
            //横线
            canvas.drawLine(0, 0, width, 1, mPaint);
            int tempHeight = 0;
            for(int i=0; i<countVerticalLine; i++) {
                tempHeight += childHeight;
                canvas.drawLine(0, tempHeight - 1, width, tempHeight, mPaint);
            }
        }
        /**
         * listview数据超过整页可以显示的数据时
         */
        else {
            //竖线
            canvas.drawLine(0, 0, 1, totalHeight, mPaint);
            for(int i=0; i<countHorizontal; i++) {
                View childView = layout_title.getChildAt(i);
                float startX = childView.getX() + childView.getWidth();
                canvas.drawLine(startX - 1, 0, startX, totalHeight, mPaint);
            }
            //横线
            canvas.drawLine(0, 0, width, 1, mPaint);
            canvas.drawLine(0, childHeight - 1, width, childHeight, mPaint);
            float draw_position = 0;
            int i=itemCount-countVerticalLine;
            for ( ; i < countVerticalLine; i++) {
                View itemView = listView.getChildAt(i);
                float startY = itemView.getY();
                int itemHeight = itemView.getHeight();
                draw_position = startY + itemHeight + childHeight - 1;
                canvas.drawLine(0, draw_position, width, draw_position, mPaint);
            }
        }
    }

3.在Activity中监听ListView的滑动事件,事实更新LineCanvasView的绘制方法

//当listview数据超过整页可以显示的数据时,需要动态绘制line
        list_view.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {

            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if(null != lineCanvasView) lineCanvasView.invalidate();
            }
        });

如果不需要标题行可以先拿到ListView的Item高度然后在onDraw()方法里计算,但是绘制算法需要改动一下这里就不尝试了,有需求的同学可以自己尝试一下。

demo地址:


https://github.com/Vieboo/BorderListView.git



版权声明:本文为sjzx3142原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。