1

I used the following code create a custom listview ....But the problem with this code it it is selecting only one item..but highlighting many items...i mean ..for example..if i have 8 items in the list..And i can see only 3 items(rest i have to scroll to see)..if i click the first item...it gets highlighted along with the fourth and the 7th item...

public class MainMenu extends Activity {
    ListView lmenu;
    View v1;
    String s;
    Class<?> ourclass;
    View layout, row;
    static int trantype;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menulist);

        Menu Menu_data[] = new Menu[] { new Menu("1.White"),
                new Menu("2.Blue"), new Menu("3.Purple"), new Menu("4.Red"),
                new Menu("5.Yellow"), new Menu("6.Black"), new Menu("6.Black"),
                new Menu("6.Black"), new Menu("6.Black"), new Menu("6.Black"),
                new Menu("6.Black"), new Menu("6.Black") };

        MenuAdapter adapter = new MenuAdapter(this, R.layout.menutext,
                Menu_data);
        lmenu = (ListView) findViewById(R.id.mainmenu);

        lmenu.setAdapter(adapter);

        lmenu.setOnItemClickListener(new OnItemClickListener() {

            public void onItemClick(AdapterView<?> ada, View v, int position,
                    long id) {
                // TODO Auto-generated method stub

                /*
                 * v.setBackgroundColor(Color.parseColor("#FCD5B5")); if (!(v1
                 * == null) && v1 != v)
                 * v1.setBackgroundColor(Color.parseColor("#EEEEEE")); v1 = v;
                 */
                Intent swipeit = new Intent(getBaseContext(), Swipeit.class);
                trantype = position + 1;
                startActivity(swipeit);
            }
        });

        findViewById(R.id.BLogout).setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                // TODO Auto-generated method stub
                finish();
            }
        });
    }

    public class Menu {
        public String title;

        public Menu() {
            super();
        }

        public Menu(String title) {
            super();
            this.title = title;
        }
    }

    public class MenuAdapter extends ArrayAdapter<Menu> {

        Context context;
        int layoutResourceId;
        Menu data[] = null;
        LayoutInflater inflater;
        boolean[] arrBgcolor;
        private int activeHex, inactiveHex;

        public MenuAdapter(Context context, int layoutResourceId, Menu[] data) {
            super(context, layoutResourceId, data);
            this.layoutResourceId = layoutResourceId;
            this.context = context;
            this.data = data;
            activeHex = Color.parseColor("#FCD5B5");
            inactiveHex = Color.parseColor("#EEEEEE");

            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            arrBgcolor = new boolean[13];
        }

        @Override
        public View getView(final int position, final View convertView,
                ViewGroup parent) {
            try {
                MenuHolder holder = null;
                row = convertView;
                // convertView.setBackgroundColor(Color.BLACK);
                if (row == null) {
                    LayoutInflater inflater = ((Activity) context)
                            .getLayoutInflater();
                    row = inflater.inflate(layoutResourceId, parent, false);
                    holder = new MenuHolder();
                    holder.txtTitle = (TextView) row.findViewById(R.id.tv1);
                    row.setTag(holder);
                } else {
                    holder = (MenuHolder) row.getTag();
                }

                Menu Menu = data[position];
                holder.txtTitle.setText(Menu.title);
                holder.txtTitle.setOnClickListener(new OnClickListener() {

                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        resetArrbg();
                        arrBgcolor[position] = true;
                        if (arrBgcolor[position]) {
                            row.setBackgroundColor(activeHex);
                        } else {
                            row.setBackgroundColor(inactiveHex);
                        }
                        notifyDataSetChanged();
                    }
                });
            } catch (Exception e) {
                Toast.makeText(getApplicationContext(), String.valueOf(e),
                        Toast.LENGTH_LONG).show();
            }
            return row;
        }

        private void resetArrbg() {
            for (int i = 0; i < arrBgcolor.length; i++) {
                arrBgcolor[i] = false;
            }
        }

        public class MenuHolder {
            TextView txtTitle;
        }
    }
}

my xml containing list...

    <include
        android:id="@+id/header"
        android:layout_alignParentTop="true"
        layout="@layout/header" />

    <RelativeLayout
        android:id="@+id/Rlmain"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/header"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/TMain"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginBottom="8dp"
            android:layout_marginLeft="10dp"
            android:layout_marginTop="8dp"
            android:text="Main Menu"
            android:textColor="#000000"
            android:textSize="15dp" />

        <View
            android:id="@+id/Vtop"
            android:layout_width="fill_parent"
            android:layout_height="2dp"
            android:layout_below="@+id/TMain"
            android:background="@android:color/darker_gray" />
    </RelativeLayout>

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_above="@+id/Vbot"
        android:layout_below="@+id/Rlmain"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/mainmenu"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#E0E0E0"
            android:cacheColorHint="#00000000"
            android:divider="@android:color/transparent"
            android:dividerHeight="20dp" >
        </ListView>
    </RelativeLayout>

    <View
        android:id="@+id/Vbot"
        android:layout_width="fill_parent"
        android:layout_height="2dp"
        android:layout_above="@+id/textView1"
        android:background="@android:color/darker_gray" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="© India Transact Services Ltd."
        android:textColor="#000000"
        android:textSize="15dp" />

</RelativeLayout>

my xml for list....

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/LLtv"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#EEEEEE"
    android:cacheColorHint="#00000000" >

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:paddingBottom="12dp"
        android:paddingTop="12dp"
        android:textColor="#000000"
        android:textSize="20dp" />

</LinearLayout>

Can please anyone help me and tell where i am going wrong?

Adolf Dsilva
  • 13,092
  • 8
  • 34
  • 45

2 Answers2

1

This happens because of the way ListView reuses Views when populating the list. Lets say you see three rows of the list at any given time. You "highlight" the first row by setting the background color (like you do), and scroll down. When the first row leaves the screen, Android does something smart. Instead of creating a new View for, say, the fifth row, it reuses the View from row one. That's the View you changed the background color of, so row five now got the same background color. Only the data is changed.

As for how to implement a different background color on the selected row, and the selected row only, have a look at this answer. I do believe you got to implement a custom ListAdapter, at least if you're developing for API levels lower than 11.

Community
  • 1
  • 1
Ole
  • 7,899
  • 2
  • 29
  • 34
1

What you want can't be achieved with your current setup. You need to implement a custom adapter where you have access to the getView() method. For reasons made clearer in the answer here, what you need to do is use some sort of data-container that will hold the status of an individual row using some indicator and then perform your action based on it's position on the container (which should correspond to its position on the listview)

for example, check out this re-write:

protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    resetArrbg();
    arrBgcolor[position] = true;
    if (arrBgcolor[position]) {
        v.setBackgroundColor(Color.parseColor("#FCD5B5"));
    } else {
        v.setBackgroundColor(Color.BLUE);           
    }
}

boolean[] arrBgcolor = new boolean[list.size()];

private void resetArrbg() {
    for (int i = 0; i < arrBgcolor.length; i++) {
        arrBgcolor[i] = false;
    }
}

Does it make sense now why it can't work with the current set-up? The else part of the method, the part affecting the other views, can never take place because you don't have access to the other positions in the onListItemClick method, but you do in getView(). This is of course, unless you know of a way around this then, by all means, more power to you. all the same i don't think the v1 technique do you any good.

EDIT:

public class MainActivity extends Activity {
    ListView lmenu;
    View v1;
    String s;
    Class<?> ourclass;
    View layout, row;
    static int trantype;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menulist);

        Menu Menu_data[] = new Menu[] { new Menu("1.White"),
                new Menu("2.Blue"), new Menu("3.Purple"), new Menu("4.Red"),
                new Menu("5.Yellow"), new Menu("6.Black"), new Menu("6.Black"),
                new Menu("6.Black"), new Menu("6.Black"), new Menu("6.Black"),
                new Menu("6.Black"), new Menu("6.Black") };

        MenuAdapter adapter = new MenuAdapter(this, R.layout.menutext, Menu_data);
        lmenu = (ListView) findViewById(R.id.mainmenu);
        lmenu.setAdapter(adapter);
    }

    public class Menu {
        public String title;

        public Menu() {
            super();
        }

        public Menu(String title) {
            super();
            this.title = title;
        }
    }

    public class MenuAdapter extends ArrayAdapter<Menu> {

        Context context;
        int layoutResourceId;
        Menu data[];
        LayoutInflater inflater;
        boolean[] arrBgcolor;
        private int activeHex, inactiveHex;

        public MenuAdapter(Context context, int layoutResourceId, Menu[] data) {
            super(context, layoutResourceId, data);
            this.layoutResourceId = layoutResourceId;
            this.context = context;
            this.data = data;


            activeHex = Color.parseColor("#FCD5B5");
            inactiveHex = Color.parseColor("#EEEEEE");

            inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            arrBgcolor = new boolean[data.length];
            resetArrbg();
        }

        @Override
        public View getView(final int position, final View convertView,
                ViewGroup parent) {

            final MenuHolder holder;
            row = convertView;
            // convertView.setBackgroundColor(Color.BLACK);
            if (row == null) {
                row = inflater.inflate(layoutResourceId, parent, false);
                holder = new MenuHolder();
                holder.txtTitle = (TextView) row.findViewById(R.id.tv1);
                row.setTag(holder);
            } else {
                holder = (MenuHolder) row.getTag();
            }

            Menu Menu = data[position];
            holder.txtTitle.setText(Menu.title);


            if (arrBgcolor[position]) {
                row.setBackgroundColor(activeHex);
            } else {
                row.setBackgroundColor(inactiveHex);
            }

            holder.txtTitle.setOnClickListener(new OnClickListener() {

                public void onClick(View v) {
                    resetArrbg();
                    arrBgcolor[position] = true;
                    notifyDataSetChanged();
                }
            });

            return row;
        }

        private void resetArrbg() {
            for (int i = 0; i < arrBgcolor.length; i++) {
                arrBgcolor[i] = false;
            }
        }

        public class MenuHolder {
            TextView txtTitle;
        }
    }
}
Community
  • 1
  • 1
mango
  • 5,577
  • 4
  • 29
  • 41
  • ok...i changed the code and now i am using a custom array adapter as shown over here "http://www.ezzylearning.com/tutorial.aspx?tid=1763429"...but i am confused about where to call the getview() method...if i call it on onitemclick() in the onCreate() then what should be its parameters??? – Adolf Dsilva Nov 26 '12 at 12:42
  • You override the getview method in your custom array adapter much like your tutorial has. Then you make a click listener inside (for the most straightforward way) and you put your color changing code inside. The adapter will do it all in this fashion, onitemclick will have nothing to do with it. You don't call getview, it's automatically called every time a new listview row is loaded. Also don't forget notifydatasetchanged() if you're not seeing any changes. – mango Nov 26 '12 at 13:02
  • no man still the same problem...i have updated my code...is it right??? or i m still doing it wrong? – Adolf Dsilva Nov 26 '12 at 13:16
  • Well what did the logcat say? – mango Nov 26 '12 at 20:24
  • i fixed the force close...but it has the same problem i.e. highlighting multiple rows....and it is onclicktext...if we click on background it doesn't work....so any more ideas :/ – Adolf Dsilva Nov 27 '12 at 07:17
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20151/discussion-between-mango-and-audi) – mango Nov 27 '12 at 07:19