I want to set an alternating color for my custom ListView
class.
The code is given below:
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;
}
}
To get an alternating background color for ListView
, I have used this code:
for (int i = 0; i < getChildCount(); i++) {
if (getChildCount() % 2 == 0) {
mPaintBackground.setColor(Color.WHITE);
} else {
mPaintBackground.setColor(Color.RED);
}
}
Inside of the adapter:
if (position % 2 == 0) {
view.setBackgroundColor(Color.RED);
} else {
view.setBackgroundColor(Color.WHITE);
}
But it always shows one color, red or white with everything I try. I am not getting alternating colors white-red-white-red.
The reason this is failing is because your for loop never changes. You are always checking getChildCount() % 2
. getChildCount()
will return the same for each iteration. You need to do your check based on position:
for(int i = 0; i < getChildCount(); i++){
if(i % 2 == 0){
mPaintBackground.setcolor(Color.WHITE);
} else{
mPaintBackground.setColor(Color.RED);
}
}
If it helps, rename your counter variable from i
to position
so that this will be more readable for you in the future, or make a note of it to help yourself out.
I would also like to add that, given the code you have now, your for loop isn't changing anything. It is just iterating through the number of children and setting mPaintBackground
. In the end, it will be left with whatever value it receives from the last iteration.
I think the best way to handle drawing the background color would be in the adapter for the Listview, in which case you can override getView() and do a check based on the position
parameter:
int backgroundResource;
if(position % 2 == 0){
backgroundResource = getResources.getColor(android.R.color.WHITE);
} else{
backgorundResource = getResources.getColor(android.R.color.RED);
}
view.setBackground(backgroundResource);
Of course, the above is just pseudocode, it may need to be adjusted to your project.
The above solution will work only for existing data. If you need an alternating color regardless of whether or not there is data, which if I understand now is what you were trying to achieve in dispatchDraw
. I will be very honest that I am not 100% sure how to do this, and I cannot test it, but I imagine the steps going like this:
Note here that you cannot iterate based on number of children, because you might not have any at this point.
Pseudocode:
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++;
}
Finally I got my answer with the huge help of @McAdam331. After using his code i got some weird thing but after that i have repaired code using this one
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++;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With