How can I change the background color for an specific row properly in a ListView? (Android)

前端 未结 7 1981
别那么骄傲
别那么骄傲 2020-12-17 05:05

I have spent some days trying to solve a problem I have with ListViews on Android. I would like to implement a single selection list box using a ListView. So, I would like t

相关标签:
7条回答
  • 2020-12-17 05:29

    try this,

    OnItemClickListener onitemclick = new OnItemClickListener() {
    
            @Override
            public void onItemClick(AdapterView<?> adapter, View arg1, int position, long id) {
                    selectedItem= position;
                    adapter.notifyDataSetChanged();
            }
        };
    

    override getView() method of your adapter:

     @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View view = View.inflate(context, R.layout.item_list, null);
    
            if (position == selectedItem) {
                // set your color
            }
    
            return view;
        }
    
    0 讨论(0)
  • 2020-12-17 05:30

    Yes you should use as Dave said:

    view.setBackgroundColor(SELECTED_COLOR);
    

    and perhaps

    view.refreshDrawableState(); 
    

    however because Android recycle lists, it will repeat your selected colour on every first item which is not shown on the screen. So if your screen size can show ten items than 11th, 21nd etc will be also shown as selected when you scroll.

    To avoid this you have to create a custom adapter. Then in getView you need to say this:

    if (myActivity.selectedRow != position){
        v.setBackgroundColor(Color.TRANSPARENT);
    } else {
        v.setBackgroundColor(SELECTED_COLOUR);
    }
    

    Where selectedRow is a public static int selectedRow within myActivity, the activity which creates your list. There you store the row number which is selected when clicking the list.

    0 讨论(0)
  • 2020-12-17 05:30

    Thanks Dave and ChristianB for your answers. I still do not know why Android does it, so the question is still unresolved. However, I found a way to get what I needed creating a custom Adapter. I will give you the code in case someone could need it.

    public class CustomAdapter extends ArrayAdapter<String> {
    
        protected static final int NO_SELECTED_COLOR = 0xFF191919;
        protected static final int SELECTED_COLOR = 0xFF3366CC;
    
        private ArrayList<String> items;
        private LayoutInflater mInflater;
        private int viewResourceId;
        private int selectedPosition;
    
        public CustomAdapter(Activity activity,int resourceId,
            ArrayList<String> list) {
            super(activity,resourceId,list);
    
            // Sets the layout inflater
            mInflater = (LayoutInflater)activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            // Set a copy of the layout to inflate
            viewResourceId = resourceId;
    
            // Set a copy of the list
            items = list;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView tv = (TextView)convertView;
            if (tv == null) {
                tv = (TextView)mInflater.inflate(viewResourceId, null);
            }
            tv.setText(items.get(position));
    
            // Change the background color
            if (position==selectedPosition) tv.setBackgroundColor(SELECTED_COLOR);
            else tv.setBackgroundColor(NO_SELECTED_COLOR);
    
            return tv;
        }
    
        public void setSelected(int position) {
            selectedPosition = position;
        }
    }
    

    So, in the ListView initialization I just need to put this listener:

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
            ((CustomAdapter)listAdapter).setSelected(position);
            listView.invalidate();
        }
    });
    

    This is not an efficient solution due to I am extending from ArrayAdapter which is suppose to have a copy of all data provided. Thus, I am using much more memory than needed and in case the list becomes very large I could have memory trouble. So, if someone knows a better solution, please post!

    0 讨论(0)
  • 2020-12-17 05:33

    listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {

      @Override
    public void onItemClick(AdapterView<?> parent, final View view, int position, long   id) 
    {
    
        View v;
    
        int count = parent.getChildCount();
        v =parent.getChildAt(position);
        parent.requestChildFocus(v, view);  v.setBackground(res.getDrawable(R.drawable.transparent_button));
    
                for (int i=0; i<count; i++)
                {
                    if (i!= position)
                    {
                        v = parent.getChildAt(i);t  v.setBackground(res.getDrawable(R.drawable.not_clicked));
    
                    }
                }
    
            }
    
        });
    

    Basically, create two drawables - one that is transparent, and another that is the desired color. Request focus at the clicked position (int position as defined) and change the color of said row. Then walk through the parent listview, and change all other rows accordingly. This accounts for when a user clicks on the listview multiple times.

    0 讨论(0)
  • 2020-12-17 05:37

    I have used this code it works nice you should try this:

    listView.getChildAt(0).setBackgroundColor(Color.BLUE);
    
    0 讨论(0)
  • 2020-12-17 05:39

    I believe this is due to the way ListViews number and re-use rows. So, rather than using parent.getChildAt(i) to get the row you wish to manipulate, use the View object passed to onItemClick itself.

    view.setBackgroundColor(SELECTED_COLOR);
    
    0 讨论(0)
提交回复
热议问题