0

我希望我ListView看起来像一个记事本,即带有水平线条背景图案。在记事本示例之后,我可以像这样扩展TextView和覆盖它onDraw()

r = new Rect();
for (int i = 0; i < getLineCount(); i++) {
  int baseline = getLineBounds(i, r);
  canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1, paint);
}
super.onDraw(canvas);

但是当列表中只有几个元素时,将没有足够的行来填充页面(左侧为实际结果,右侧为所需):

在此处输入图像描述 ~~~在此处输入图像描述

所以我尝试了另一种方法:覆盖ListView.onDraw(). 不幸的是,没有直接的方法来计算顶部滚动getScrollY()总是返回0),最重要的是,我必须禁用所有缓存和绘图优化,这肯定会降低性能,除了不能针对大型列表进行扩展。

最后,我的行小部件不是纯文本视图。它们是复杂的布局,即使主要内容是 -sure- a TextView。这意味着在布局内部我不能调用getLineBounds()(布局不是文本视图),而在文本视图中我不能因为TextView小于周围的布局,所以四个边会有间隙。

如何构建一个解决方案来显示我的自定义小部件并用水平线填充整个窗口?一种天真的方法是将虚拟的空元素添加到列表中,只要它适合所有可用空间,但是这是一种技巧,必须有更好的做事方式。使用背景图像不是一种选择,因为线之间的距离必须在运行时可定制。

4

1 回答 1

3

下面的代码基于您问题中的简单示例,这TextView是一个在底部画一条线的自定义(并且列表中没有分隔符)。在这种情况下,我将进行自定义ListView并覆盖如下dispatchDraw方法:

class CustomListView extends ListView {

    private Paint mPaint = new Paint();
    private Paint mPaintBackground = new Paint();

    public CustomListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint.setColor(Color.RED);
        mPaintBackground.setColor(Color.CYAN);
    }       

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        // ListView's height
        final int currentHeight = getMeasuredHeight();
        // this will let you know the status for the ListView, fitting/not
        // fitting content
        final int scrolledHeight = computeVerticalScrollRange();
        if (scrolledHeight >= currentHeight || scrolledHeight == 0) {
            // there is no need to draw something(for simplicity I assumed that
            // if the adapter has no items i wouldn't draw something on the
            // screen. If you still do want the lines then pick a decent value
            // to simulate a row's height and draw them until you hit the
            // ListView's getMeasuredHeight)
            return;
        } else {
            // get the last drawn child
            final View lastChild = getChildAt(getChildCount() - 1);
            // values used to know where to start drawing lines
            final int lastChildBottom = lastChild.getBottom();
            // last child's height(use this to determine an appropriate value
            // for the row height)
            final int lastChildHeight = lastChild.getMeasuredHeight();
            // determine the number of lines required to fill the ListView
            final int nrOfLines = (currentHeight - lastChildBottom)
                    / lastChildHeight;
            // I used this to simulate a special color for the ListView's row background
            Rect r = new Rect(0, lastChildBottom, getMeasuredWidth(),
                    getMeasuredHeight());           
            canvas.drawRect(r, mPaintBackground);
            for (int i = 0; i < nrOfLines; i++) {
                canvas.drawLine(0, lastChildBottom + (i + 1) * lastChildHeight,
                        getMeasuredWidth(), lastChildBottom + (i + 1)
                                * lastChildHeight, mPaint);
            }
        }
    }

}

看看您是否可以使用上面的代码并根据自己的需要进行调整。

于 2012-10-05T09:10:27.860 回答