0

I have designed an application with a list-view in which I can change the colors of list items, here is a link to a screen from the application:

Image

The colors are changed by changing an image on the left part of the list row. Now when I change the color slide down in the list, and the come back up the color go back to their original state (meaning the Image-view come back to its original source).

The data for the list is taken from an XML file, parsed to a hash-map and the using an adapter inflated into the list. How can I get around this issue?

As I see it because the list-view reuses the views that are not on screen, when I come back to the changed row that went out of the screen and then comes back it pulls its information again from the hash-map. So what I need to do is to find the index of data in the hash-map that was bind to row layout by the adapter, and there to change the associated color, that way the next time the adapter recreates this row it will be assigned with the right color. How can this be done?

Here is the Java code for this activity:

public class SkyGiraffeAppActivity extends Activity implements AdapterView.OnItemClickListener, View.OnClickListener {
// All static variables
static final String TAG = "SkyGiraffeAppActivity";
// XML node keys
static final String KEY_TASK = "task"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_DATE = "date";
static final String KEY_TIME = "time";
static final String KEY_PRIORITY  = "priority";
static final String KEY_USERPRIORITY = "userpriority";

View currentRow;
final ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
    ListView list = new ListView(this);
    list.setDivider(null);
    list.setDividerHeight(0);

    setContentView(list);
    getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.taskstitle);


    Log.e(TAG, "Created Array");

    XMLParser parser = new XMLParser();

    Log.e(TAG, "Getting xml from raw folder");
    InputStream xml = getResources().openRawResource(R.raw.taskslists); // getting XML

    Log.e(TAG, "reading xml file to string");
    String sxml = parser.readTextFile(xml);

    Log.e(TAG, "creating dom element from string");
    Document doc = parser.getDomElement(sxml); // getting DOM element

    Log.e(TAG, "getting node list of all the elements");
    NodeList nodeList = doc.getElementsByTagName(KEY_TASK);

    Log.e(TAG, "looping through all the elements");
    for (int i = 0; i < nodeList.getLength(); i++) 
    {
        // creating new HashMap
        HashMap<String, String> map = new HashMap<String, String>();
        Element e = (Element) nodeList.item(i);
        Log.e(TAG, "element number: " + i + " added to hash map");
        // adding each child node to HashMap key => value
        map.put(KEY_ID, parser.getValue(e, KEY_ID));
        map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
        map.put(KEY_DATE, parser.getValue(e, KEY_DATE));
        map.put(KEY_TIME, parser.getValue(e, KEY_TIME));
        map.put(KEY_PRIORITY, parser.getValue(e, KEY_PRIORITY));
        map.put(KEY_USERPRIORITY, parser.getValue(e, KEY_USERPRIORITY));

        // adding HashList to ArrayList
        menuItems.add(map);
    }

    // Adding menuItems to ListView
    ListAdapter adapter = new SimpleAdapter(this, menuItems, R.layout.row,
          new String[] { KEY_TITLE, KEY_DATE, KEY_TIME, KEY_PRIORITY, KEY_USERPRIORITY}, 
          new int[]    { R.id.text_title, R.id.text_date, R.id.text_time ,R.id.image_priority, R.id.bchangecolor}){

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View row =  super.getView(position, convertView, parent);
            View left = row.findViewById(R.id.bchangecolor);
            left.setTag(position);
            left.setOnClickListener(SkyGiraffeAppActivity.this);
            View right = row.findViewById(R.id.barrow);
            right.setTag(position);
            right.setOnClickListener(SkyGiraffeAppActivity.this);


            ImageView prioriy = (ImageView) row.findViewById(R.id.image_priority);
            ImageView usercolor = (ImageView) row.findViewById(R.id.bchangecolor);


            String userpriority = menuItems.get(position).get(KEY_USERPRIORITY);   
            Log.e(TAG, "user priority color for this view was: " + userpriority);

            if (userpriority.contentEquals("green"))
            {
                usercolor.setImageResource(R.drawable.task_bg_left_green);
            }
            else if (userpriority.contentEquals("blue"))
            {
                usercolor.setImageResource(R.drawable.task_bg_left_blue);
            }
            else if (userpriority.contentEquals("yellow"))
            {
                usercolor.setImageResource(R.drawable.task_bg_left_yellow);
            }
            else if (userpriority.contentEquals("orange"))
            {
                usercolor.setImageResource(R.drawable.task_bg_left_orange);
            }
            else if (userpriority.contentEquals("red"))
            {
                usercolor.setImageResource(R.drawable.task_bg_left_red);
            }


            int number = Integer.valueOf(menuItems.get(position).get(KEY_PRIORITY));
            switch ( number )
            {
            case 1:
                prioriy.setImageResource(R.drawable.priority_first);
                break;
            case 2:
                prioriy.setImageResource(R.drawable.priority_second);
                break;
            case 3:
                prioriy.setImageResource(R.drawable.priority_third);
                break;
            case 4:
                prioriy.setImageResource(R.drawable.priority_fourth);
                break;
            case 5:
                prioriy.setImageResource(R.drawable.priority_fifth);
                break;
            default:
                prioriy.setImageResource(R.drawable.priority_first);
            }

            return row;
        }
    };

    list.setAdapter(adapter);
    list.setOnItemClickListener(this);  
}

public void onClick(View v) 
{
     Intent i = new Intent(this, TaskColorChangeActivity.class);
     i.putExtra("color", "choosecolor");

     switch(v.getId()) {
        case R.id.bchangecolor:
            Log.e(TAG, "pressed the color change button on" + v.getId());
            currentRow = v;
            startActivityForResult(i, 1);
            break;
        case R.id.barrow:
            Log.e(TAG, "pressed the arrow button on" + v.getId());
            i = createIntentwithExtra(v.getRootView());
            startActivity(i);
            break;
        default:
            break;
        }   
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, data);

    if(data.getExtras().containsKey("chosencolor"))
    {
        ImageView imageView = (ImageView) currentRow.findViewById(R.id.bchangecolor);
        if (data.getStringExtra("chosencolor").contentEquals("blue"))
        {
            imageView.setImageResource(R.drawable.task_bg_left_blue);
            //menuItems.get(po)
        }
        else if (data.getStringExtra("chosencolor").contentEquals("green"))
        {
            imageView.setImageResource(R.drawable.task_bg_left_green);
        }
        else if (data.getStringExtra("chosencolor").contentEquals("yellow"))
        {
            imageView.setImageResource(R.drawable.task_bg_left_yellow);
        }
        else if (data.getStringExtra("chosencolor").contentEquals("orange"))
        {
            imageView.setImageResource(R.drawable.task_bg_left_orange);
        }
        else if (data.getStringExtra("chosencolor").contentEquals("red"))
        {
            imageView.setImageResource(R.drawable.task_bg_left_red);    
        } 
    }
}

public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
    Log.e(TAG, "pressed the row itself" + v.getId());
    Intent intent = createIntentwithExtra(v);
    startActivity(intent);  
}

public Intent createIntentwithExtra(View v)
{
    Intent intent = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
    String title = ((TextView) v.findViewById(R.id.text_title)).getText().toString();
    String date = ((TextView) v.findViewById(R.id.text_date)).getText().toString();
    String time = ((TextView) v.findViewById(R.id.text_time)).getText().toString();
    intent.putExtra(KEY_TITLE, title);
    intent.putExtra(KEY_DATE, date);
    intent.putExtra(KEY_TIME, time);

    return intent;
}}
halfer
  • 19,824
  • 17
  • 99
  • 186
Emil Adz
  • 40,709
  • 36
  • 140
  • 187

1 Answers1

0

You should re-use the already created view.Some thing like this:

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    if(convertView == null){
        //CREATE NEW HOLDER
        holder = new ViewHolder();
        // Layout XML
        int layoutFile = R.layout.adapter_layout;
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(layoutFile, null);
        convertView.setTag(holder);
        holder.tvName= (TextView)convertView.findViewById(R.id.tvName);

              /// SET DE VALUES TO THE VIEW HERE, INCLUDING THE
              /// ONCLICK TO THE VIEW
    Users u = arrayUser.get(position);

    holder.tvName.setText(u.getName());


    }
    else
        holder= (ViewHolder)convertView.getTag();
    return convertView;
}

static class ViewHolder{
    TextView tvName;
}   
JannGabriel
  • 302
  • 5
  • 14
  • what is a ViewHolder, how to i design this class? – Emil Adz Jan 18 '13 at 01:54
  • this ViewHolder IS a class inside the one where you create your view. In this class you declare all the views you want to show on your list. In my example is a simple list with a textview to show just a name. – JannGabriel Jan 18 '13 at 10:04
  • Thank @JannGabriel,but I don't think i could follow this way because of the fact that my list is multi-clickable and i need to create new view in order to assign "onItemClick" functions to them. As i already wrote i think because the list-view reuses the views that are not on screen, when i come back to the changed row that went out of the screen and then comes back it puls its information again from the hash-map. So what i need to do is to find the index of data in the hash-map that was bind to row layout by the adapter, and update the color in it. May you have an idea have can I update it? – Emil Adz Jan 18 '13 at 14:44
  • I have edit my post. Now it will work to you. I ran a test with 2 buttons changing a textview and it worked just great. – JannGabriel Jan 18 '13 at 16:47
  • can you please explain what is this row for: Users u = arrayUser.get(position); – Emil Adz Jan 18 '13 at 17:00
  • this is my array where i get the value to the view. In your case is the "menuItems.get(position)" – JannGabriel Jan 18 '13 at 17:46
  • Thanks man you have partially helped me, but what really did the trick for me is adding: menuItems.get(currentRowposition).put(KEY_USERPRIORITY, "color"); in the onActivityResult for the color change activity, now for every color that i change in the list the hash map is updated with the new color. Thanks again. – Emil Adz Jan 18 '13 at 18:18
  • Good to hear that you made it. But think about reuse the views that you already have created. It will improve the app performance – JannGabriel Jan 18 '13 at 18:40
  • actually i was happy to early the list is still is not consistent with the it shows changes Imageviews : ( – Emil Adz Jan 18 '13 at 19:47
  • it still change the view when you scroll the list or just when you reload the activity? – JannGabriel Jan 18 '13 at 19:52
  • it does it when i scroll, the problem is that the position int represent a index of only the visible rows in the screen so it will be a number between 1-8 (approximation) when i want to update the hash map of row number 18 it's it's update a an earlier row instead. do you know how can i get to the right location in the hash map of the chosen row? – Emil Adz Jan 18 '13 at 20:24
  • sorry, now I can't help you. It should be working as you aways use the row position to get the velues in the hash map (menuItems.get(position)). Anyway the hash map and the list should have the same number of rows not one between 1-8 and the other 18 lines. There is some thing REALY estrange in your code. Use debug to see which is the value to the variable POSITION and which is the possition of the data in the Hashmap. Take a look if the possition of the hashmap starts with 0 or 1. Maybe this is the difference and the reason that you are updating a earlier row. – JannGabriel Jan 21 '13 at 10:07
  • Well i kinda did, it is working but I do still have to recreate a new view every time and set a tag on it, using convertView didn't do me any help either, it some times gave me the wrong textures for the rows. or maybe i am still unable to understand those concepts. – Emil Adz Jan 24 '13 at 13:06