简体   繁体   中英

Change background color of ListView Items if MATCH found (Android ListView)

I have two List ArrayList which have some string values. Also, I have a ListView and an ArrayAdapter. The data given to the ArrayAdapter is coming from one of the ArrayList.


What I want to achive is : Compare both the arrayLists and if two elements present in the arrayLists are same, Then when the ListView is generated, the background for the listView item for which a match was found should be of different color.


I tried using listview.getChildAt(i).setBackgroundColor(Color.Blue) but it doesnt works. It is giving me as java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setBackgroundColor(int)' on a null object reference on the same line. If there is any better way to do this then post it in your answers.

 private List<String> forexInstruments;
 private ListView forexListView;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

String[]  temp = new String[]{
                "'" + "EURCAD" + "'",
                "'" + "USDGPY" + "'",
                "'" + "AUDUSD" + "'",
                "'" + "USDCHF" + "'",
                "'" + "EURGPY" + "'",
                "'" + "6B 03-16" + "'",
                "'" + "6E 03-16" + "'",
                "'" + "CL 03-16" + "'",
                "'" + "ZB 09-16" + "'"    
        };
    //1st Array List
    selectedGlobalInstruments = new ArrayList<>(Arrays.asList(temp));

    //2nd Array List
    forexInstruments = new ArrayList<>();
    forexInstruments.add("EURCAD");
    forexInstruments.add("USDGPY");
    forexInstruments.add("AUDUSD");
    forexInstruments.add("EURGBP");
    forexInstruments.add("USDJPY");
    forexInstruments.add("GBPUSD");
    forexInstruments.add("EURGPY");
    forexInstruments.add("USDCHF");


    forexListView = (ListView) findViewById(R.id.listView);
    final ArrayAdapter arrayAdapter = new    ArrayAdapter(this,R.layout.list_item_layout,R.id.list_item_instrument_textview,forexInstruments);
    forexListView.setAdapter(arrayAdapter);

    //Comparing both the ArrayLists. If two elements ar eqaul then change background color
    for(int j=0; j< selectedGlobalInstruments.size(); j++) {
        String tempA = selectedGlobalInstruments.get(j);
        Log.v("Selcted",selectedGlobalInstruments.get(j));
        for(int i=0; i < forexListView.getCount(); i++)
        {
            String instrumentList = "'" + forexListView.getItemAtPosition(i).toString()+ "'";
            Log.v("forexListview",instrumentList);
            if (tempA.equals(instrumentList)) {
                Log.v("Satisfied",instrumentList);
                forexListView.getChildAt(i).setBackgroundColor(Color.BLUE);
                arrayAdapter.notifyDataSetChanged();
            }
        }
    }

list_item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_item_instrument_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed"
android:textSize="18sp"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:textColor="#000000"
android:textStyle="bold"
android:layout_marginRight="10dp">
</TextView>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.shubhamhpcs.listviesttes.MainActivity">

<ListView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/listView"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />
</RelativeLayout>

In my opinion, an Activity shouldn't take care how an item from ListView is displayed, letting this job for an adapter (you're doing this in onCreate without having the rows for ListView created, resulting in a crash).
So what I would do is to create a class that has 2 fields: String value where you have your actual data to be displayed and a boolean hasBackground that indicates if that item should be displayed with a custom background or not. That class should look like this:

public class ListItem {
  public String value;
  public boolean hasBackground = false;

  public ListItem(String value, boolean background) {
    this.value = value;
    this.hasBackground = background;
  }
}

Then I would make the forexInstruments to have elements of type ListItem . I would add the elements like this: forexInstruments.add(getDefaultItem("USDGPY")); , where getDefaultItem is method that returns ListItem with background set to false .

private ListItem getDefaultItem(String value) {
    return new ListItem(value, false);
} 

After the list is initialised it have to be updated, so I created a method to find the common elements between those 2 lists, setting the hasBackground field to true for those elements.

private void updateCommonElements() {
    for (int j = 0; j < selectedGlobalInstruments.size(); j++) {
      for (int i = 0; i < forexInstruments.size(); i++) {
        String instrumentList = "'" + forexInstruments.get(i).value + "'";
        if (selectedGlobalInstruments.get(j).equals(instrumentList)) {
          forexInstruments.get(i).hasBackground = true;
        }
      }
    }
}

In the end, the onCreate would look like this:

forexInstruments = new ArrayList<>();
forexInstruments.add(getDefaultItem("USDGPY"));
forexInstruments.add(getDefaultItem("AUDUSD"));
forexInstruments.add(getDefaultItem("EURGBP"));
forexInstruments.add(getDefaultItem("USDJPY"));
forexInstruments.add(getDefaultItem("GBPUSD"));
forexInstruments.add(getDefaultItem("EURGPY"));
forexInstruments.add(getDefaultItem("USDCHF"));

updateCommonElements();

forexListView = (ListView) findViewById(R.id.listView);
MyAdapter adapter = new MyAdapter(this, android.R.layout.simple_list_item_1, android.R.id.text1);
adapter.addAll(forexInstruments);
forexListView.setAdapter(adapter);

where MyAdapter is a class extending ArrayAdapter , being responsible for colouring the background of a row or not.

public class MyAdapter extends ArrayAdapter<ListItem> {
  int res = 0;
  int textRes = 0;

  public MyAdapter(Context context, int resource, int textViewResourceId) {
    super(context, resource, textViewResourceId);
    res = resource;
    textRes = textViewResourceId;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
      convertView = LayoutInflater.from(parent.getContext()).inflate(res, parent, false);
    }
    ListItem item = getItem(position);
    if (item.hasBackground) {
      convertView.setBackgroundColor(Color.BLUE);
    } else {
      convertView.setBackgroundColor(Color.TRANSPARENT);
    }
    TextView textView = (TextView) convertView.findViewById(textRes);
    textView.setText(item.value);
    return convertView;
  }
}

And this is the final result in my simulator: 屏幕截图

Note: I used some Android default layouts, but they can be changed to your layouts in a few seconds.

您需要通知适配器有关更改:

arrrayAdapter.notifyDataSetChanged();

I think you are trying to getItem of list when it is not yet completely set.Please check if below helps:

ArrayAdapter arrayAdapter =null;
String[]  temp = new String[]{
            "'" + "EURCAD" + "'",
            "'" + "USDGPY" + "'",
            "'" + "AUDUSD" + "'",
            "'" + "USDCHF" + "'",
            "'" + "EURGPY" + "'",
            "'" + "6B 03-16" + "'",
            "'" + "6E 03-16" + "'",
            "'" + "CL 03-16" + "'",
            "'" + "ZB 09-16" + "'"    
    };

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

init();


forexInstruments.add("EURCAD");
forexInstruments.add("USDGPY");
forexInstruments.add("AUDUSD");
forexInstruments.add("EURGBP");
forexInstruments.add("USDJPY");
forexInstruments.add("GBPUSD");
forexInstruments.add("EURGPY");
forexInstruments.add("USDCHF");

arrayAdapter.notifyDataSetChanged();

//Comparing both the ArrayLists. If two elements ar eqaul then change background color
checkSameItems();

}     

private void init(){
    //1st Array List
    selectedGlobalInstruments = new ArrayList<>(Arrays.asList(temp));

    //2nd Array List
    forexInstruments = new ArrayList<>();
    forexListView = (ListView) findViewById(R.id.listView);
    arrayAdapter = new    ArrayAdapter(this,R.layout.list_item_layout,R.id.list_item_instrument_textview,forexInstruments);
    forexListView.setAdapter(arrayAdapter);

}

private void checkSameTimes(){
     for(int j=0; j< selectedGlobalInstruments.size(); j++) {
    String tempA = selectedGlobalInstruments.get(j);
    Log.v("Selcted",selectedGlobalInstruments.get(j));
    for(int i=0; i < forexListView.getCount(); i++)
    {
        String instrumentList = "'" + forexListView.getItemAtPosition(i).toString()+ "'";
        Log.v("forexListview",instrumentList);
        if (tempA.equals(instrumentList)) {
            Log.v("Satisfied",instrumentList);
            forexListView.getChildAt(i).setBackgroundColor(Color.BLUE);
            arrayAdapter.notifyDataSetChanged();
        }
    }
 }
}

I think that your strings are both different, they wont be ever equal. Since your

selectedGlobalInstruments.get(0) = 'EURCAD';

which you are initializing as : "'" + "EURCAD" + "'",

while:

forexInstruments.get(0) = EURCAD ;

There is a difference of ' in both the strings so they wont be equal.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM