即使没有数据,ListView类的替代背景颜色

我想为我的自定义ListView类设置一个交替的颜色。

代码如下:

 import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.widget.ListView; public 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.parseColor("#1A000000")); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); final int currentHeight = getMeasuredHeight(); final View lastChild = getChildAt(getChildCount() - 1); if (lastChild == null) return; for (int i = 0; i < getChildCount(); i++) { if (getChildCount() % 2 == 0) { mPaintBackground.setColor(Color.WHITE); } else { mPaintBackground.setColor(Color.RED); } } final int lastChildBottom = lastChild.getBottom(); final int lastChildHeight = lastChild.getMeasuredHeight(); final int nrOfLines = (currentHeight - lastChildBottom) / lastChildHeight; Rect r = new Rect(0, lastChildBottom, getMeasuredWidth(), getMeasuredHeight()); canvas.drawRect(r, mPaintBackground); canvas.drawLine(0, lastChildBottom, getMeasuredWidth(), lastChildBottom, mPaint); for (int i = 0; i < nrOfLines; i++) { canvas.drawLine(0, lastChildBottom + (i + 1) * lastChildHeight, getMeasuredWidth(), lastChildBottom + (i + 1) * lastChildHeight, mPaint); } return; } } 

为了得到ListView的交替背景颜色,我已经使用这个代码:

 for (int i = 0; i < getChildCount(); i++) { if (getChildCount() % 2 == 0) { mPaintBackground.setColor(Color.WHITE); } else { mPaintBackground.setColor(Color.RED); } } 

适配器内部:

  if (position % 2 == 0) { view.setBackgroundColor(Color.RED); } else { view.setBackgroundColor(Color.WHITE); } 

但它总是显示一种颜色,红色或白色与我尝试的一切。 我没有交替颜色白红 – 白 – 红。

Solutions Collecting From Web of "即使没有数据,ListView类的替代背景颜色"

这是失败的原因是因为你的for循环永远不会改变。 你总是检查getChildCount() % 2getChildCount()将为每个迭代返回相同的值。 你需要根据职位做你的支票:

 for(int i = 0; i < getChildCount(); i++){ if(i % 2 == 0){ mPaintBackground.setcolor(Color.WHITE); } else{ mPaintBackground.setColor(Color.RED); } } 

如果有帮助的话,把i的计数器variables重命名,以便将来可以读取更多的可读性,或记下它来帮助你自己。

我还想补充一点,鉴于你现在的代码,你的for循环没有改变任何东西。 这只是迭代儿童的数量和设置mPaintBackground 。 最后,它会留下它从上次迭代中得到的任何价值。

我认为处理绘制背景颜色的最佳方法是在Listview的适配器中,在这种情况下,可以重写getView()并根据position参数进行检查:

 int backgroundResource; if(position % 2 == 0){ backgroundResource = getResources.getColor(android.R.color.WHITE); } else{ backgorundResource = getResources.getColor(android.R.color.RED); } view.setBackground(backgroundResource); 

当然,以上只是伪代码,可能需要根据你的项目进行调整。


上述解决scheme仅适用于现有数据。 如果你需要一个交替的颜色,不pipe是否有数据,如果我现在明白的是你正在尝试在dispatchDraw实现的。 我会非常诚实地说,我不是100%确定如何做到这一点,而且我也无法testing,但是我想象的是这样的步骤:

  • 获取ListView的高度
  • 获取ListView的宽度
  • 如果使用wrapPreviousItemHeight(如果使用wrapPreviousItemHeight),则可能会更棘手,因为无法预测项目的大小,所以交替使用空ListView的颜色将会很困难。
  • ListView中留有空间时,绘制一个矩形。

在这里请注意,你不能迭代基于孩子的数量,因为你可能没有任何在这一点上。

伪代码:

 listViewWidth = getMeasuredWidth(); listViewHeight = getMeasuredHeight(); numChildren = getChildCount(); itemHeight = getItemHeight(); // See comments above, adjust this for your problem. currentTop = 0; // Used to keep track of the top of the rectangle we are drawing. currentBottom = itemHeight; // Used to keep track of the bottom rectangle we are currently drawing. int currentRectangle = 0; while(currentBottom <= listViewHeight){ if(currentRectangle % 2 == 0){ mPaintBackground.setColor(Color.WHITE); } else{ mPaintBackground.setColor(Color.RED); } Rect r = new Rect(0, currentBottom, getMeasuredWidth(), getMeasuredHeight()); canvas.drawRect(r, mPaintBackground); // Move to next currentTop += itemHeight; currentBottom += itemHeight; currentRectangle++; } 

最后,我在@ McAdam331的帮助下得到了我的答案。 使用他的代码后,我有一些奇怪的事情,但之后,我已经修复使用这一个代码

  int listViewHeight = getMeasuredHeight(); int itemHeight = lastChild.getMeasuredHeight(); int currentTop = 0; int currentBottom = lastChild.getBottom(); int currentRectangle = 0; while (currentBottom <= listViewHeight) { if (currentRectangle % 2 == 0) { mPaintBackground.setColor(Color.WHITE); } else { mPaintBackground.setColor(Color.parseColor("#f7f7f7")); } Rect r = new Rect(0, currentBottom, getMeasuredWidth(), getMeasuredHeight()); canvas.drawRect(r, mPaintBackground); // Move to next currentTop += itemHeight; currentBottom += itemHeight; currentRectangle++; } 

逻辑中有一个小错误。 这里是该部分的更新代码:

 for (int i = 0; i < getChildCount(); i++) { if (i % 2 == 0) { view.setBackgroundColor(getResources.getColor(Color.WHITE)); } else { view.setBackgroundColor(getResources.getColor(Color.RED)); } } 

检查应该是计数器控制variables,getChildCount将总是返回的总数,这就是为什么你总是看到相同的颜色。 上面的粘贴代码将解决您的问题。 但是这个代码应该在你的适配器类的getView()中,因为getView()函数在每一行都被调用来渲染。 你目前的做法只是调用一次函数,你不会达到预期的结果。

您可以通过简单地创build一个自定义Adapter来为Listview创build相同的效果:

 public class MyAlternateColorAdapter extends ArrayAdapter<SomeObject> { private Context context; //Get the Context from the constructor ... @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View rowView = inflater.inflate(R.layout.rowlayout, parent, false); if (position % 2 == 0) { rowView.setBackgroundColor(Color.RED); // Or use rowView.setBackgroundResource(R.drawable.bg_red); where bg_red is a drawable with a selector to provide touch feedback } else { rowView.setBackgroundColor(Color.WHITE); } // Set the data of the row ... } }