Android Alternate Row Colors in Listview

Android Alternate row Colors in ListView

Here is how to do that.

My example code is given here in brief:

Override the getView method in your adapter:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
if (position % 2 == 1) {
view.setBackgroundColor(Color.BLUE);
} else {
view.setBackgroundColor(Color.CYAN);
}

return view;
}

Override ArrayAdapter and override getView method there.

So if your adapter is something like this:

public class MyAdapter extends ArrayAdapter

Your ListActivity will change like this:

 ArrayAdapter<String> adapter = new MyAdapter<String>(this,
android.R.layout.simple_list_item_1, Str.S);

Here's an example about overriding ArrayAdapter.

Alternate row Colors in ListView

Here what you need to do create a CustomAdapter:

public class CustomAdapter extends ArrayAdapter<App> {

public CustomAdapter (Context context) {
super(context);
}

public View getView(int position, View view, ViewGroup root) {
CustomHolder holder;
if(view == null) {
view = LayoutInflater.from(this.getContext()).inflate(R.layout.simple_list_item_1, root, false);
holder = new CustomHolder();
view.setBackgroundColor(position % 2 == ? Color 1 : Color 2);
view.setTag(holder);
} else {
holder = (CustomHolder)view.getTag();
}

holder.setApp((App)this.getItem(position));
return view;
}

public static class CustomHolder{
public void setApp(App app){//DO YOUR THING}

public CustomHolder () {
}
}
}

Then your activity should look like this:

import android.os.Bundle;
import android.view.Menu;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.app.Activity;
public class MainActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ListView listView = (ListView) findViewById(R.id.listView1);

List<App> apps = null;
try {
XMLPullParserHandler parser = new XMLPullParserHandler(getApplicationContext());
InputStream is=getAssets().open("apps.xml");
apps = parser.parse(is);

CustomAdapter<App> adapter = new CustomAdapter (this);
listView.setAdapter(adapter);

} catch (IOException e) {e.printStackTrace();}

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}

ListView Alternate colors

Override getView for the adapter

SimpleAdapter adapter = new SimpleAdapter(this, propositions, android.R.layout.simple_list_item_2,
new String[] {"Date", "Trajet"},
new int[] { android.R.id.text1,
android.R.id.text2})
{
@Override
public View getView (int position, View convertView, ViewGroup parent)
{
View v = super.getView(position, convertView, parent);
if(position %2==0)
{
v.setBackgroundColor(Color.BLUE);
}
else
{
v.setBackgroundColor(Color.WHITE);
}

return v;
}

};

Set alternate row color listview

I managed to solved it. Below is my updated code.

MainActivity:

public class MainActivity extends Activity {

private TextView cityText;
private TextView condDescr;

private ImageView imgView;

private ListView mainListView;
private ArrayAdapter<String> listAdapter;
WeatherAdapter wa;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String city = "";

mainListView = (ListView) findViewById(R.id.mainListView);

cityText = (TextView) findViewById(R.id.cityText);
condDescr = (TextView) findViewById(R.id.condDescr);
imgView = (ImageView) findViewById(R.id.condIcon);

// Create and populate a List of variable names.
String[] weather = new String[] {};
ArrayList<String> weatherData = new ArrayList<String>();
weatherData.addAll(Arrays.asList(weather));

listAdapter = new WeatherAdapter(this, weatherData);

JSONWeatherTask task = new JSONWeatherTask();
task.execute(new String[] { city });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private class JSONWeatherTask extends AsyncTask<String, Void, Weather> {

@Override
protected Weather doInBackground(String... params) {
Weather weather = new Weather();
String data = ((new WeatherHttpClient()).getWeatherData(params[0]));

try {
weather = JSONWeatherParser.getWeather(data);

// Retrieve the icon
weather.iconData = ((new WeatherHttpClient())
.getImage(weather.currentCondition.getIcon()));

} catch (JSONException e) {
e.printStackTrace();
}
return weather;

}

@Override
protected void onPostExecute(Weather weather) {
super.onPostExecute(weather);

if (weather.iconData != null && weather.iconData.length > 0) {
Bitmap img = BitmapFactory.decodeByteArray(weather.iconData, 0,
weather.iconData.length);
imgView.setImageBitmap(img);
}

cityText.setText(weather.location.getCity() + ", "
+ weather.location.getCountry());
condDescr.setText("Weather: " + weather.currentCondition.getCondition() + " ("
+ weather.currentCondition.getDescr() + ")");
listAdapter.add("Temperature: "+ "\t\t\t\t"
+ Math.round((weather.temperature.getTemp() - 273.15))
+ "°C");
listAdapter.add("Humidity: " + "\t\t\t\t\t\t" + weather.currentCondition.getHumidity() + "%");
listAdapter.add("Air pressure: " + "\t\t\t\t" + weather.currentCondition.getPressure() + " hPa");
listAdapter.add("Air condition: " + "\t\t\t\t");

// Set the ArrayAdapter as the ListView's adapter.
mainListView.setAdapter(listAdapter);
}

}

WeatherAdapter:

public class WeatherAdapter extends ArrayAdapter<String> {
private final Activity context;
private ArrayList<String> weatherData;

static class ViewHolder {
public TextView text;
public ImageView image;
}

public WeatherAdapter(Activity context, ArrayList<String> weatherData) {
super(context, R.layout.list, weatherData);
this.context = context;
this.weatherData = weatherData;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View rowView = convertView;
// reuse views
if (rowView == null) {
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.list, null);
// configure view holder
ViewHolder viewHolder = new ViewHolder();
viewHolder.text = (TextView) rowView.findViewById(R.id.rowTextView);
/*
* viewHolder.text = (TextView)
* rowView.findViewById(R.id.TextView01); */
viewHolder.image = (ImageView) rowView .findViewById(R.id.icon);

rowView.setTag(viewHolder);
}

ViewHolder holder = (ViewHolder) rowView.getTag();
ArrayList<String> s = new ArrayList<String>(weatherData);
String []sa = new String [s.size()];
sa = s.toArray(sa);

holder.text.setText(sa[position]);

if (sa[position].startsWith("Air pressure")) {
rowView.setBackgroundResource(R.color.skyblue) ;

}

return rowView;
}
}

Alternating colors in Listview in Android Studio App

You should override getView method in your listview adapter from which you can do the following :

View getView (int position, View convertView, ViewGroup parent) {
...
if(position % 2 == 0) {
convertView.setBackgroundColor(color1);
else {
convertView.setBackgroundColor(color2);
}
return convertView;
}

Of course your convertView should have been created before. If your adapter just extends ArrayAdapter you can just add the following line instead of the dots :

convertView = super.getView(position, convertView, parent);

Checkout this tutorial for more information.

EDIT

I will explain a little bit more.

When you want to use a ListView, you need an Adapter. The adapter is used to render the data, so each row. The ListView is just the container of the row, so if you change the background color of the ListView, you are just changing the color of the whole container. What you want to do is changing the color of each row. You have to do it in the adatper's method getView.

So first you extend for exemple an ArrayAdatper and you override getView

public class MyAdatper extends ArrayAdapter<String> {
View getView (int position, View convertView, ViewGroup parent) {
convertView = super.getView(position, convertView, parent);
if(position % 2 == 0) {
convertView.setBackgroundColor(color1);
else {
convertView.setBackgroundColor(color2);
}
return convertView;
}

Then in your Activity you do :

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

resultListView = (ListView)findViewById(R.id.efile_results_list_view);

String[] mockValue = {
"Value 1",
"value 2",
"value 3" };

MyAdatper adapter = new MyAdapter(this, R.layout.list_item, R.id.info_text, mockValues));
resultListView.setAdapter(adapter);

}

Finally, create a layout that will represent a row. For example inside list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="center"
android:layout_margin="10dp">

<TextView
android:id="@+id/info_text"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</RelativeLayout>

I suggest that you look at some documentation and some tutorial to know exactly how this is working.

Here I gave you the example for a simple ListView Displaying an Array of String. If you are looking to display more complex views, look for the BaseAdapter.

Alternate background color for ListView class even without data

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:

  • Get the height of the ListView
  • Get the width of the ListView
  • Get the height of one child (listPreferredItemHeight, if you use that. If you use wrap content, this might be trickier because you cannot predict the size of the items, so alternating colors for an empty ListView would be difficult).
  • While there is space left in the ListView, draw a rectangle.

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++;
}


Related Topics



Leave a reply



Submit