How to add a dynamic view to a ListView item at runtime?

后端 未结 3 752
Happy的楠姐
Happy的楠姐 2021-01-02 14:58

My problem is that I don\'t know whether I should use multiple list view or a custom listview item adapter which can grows dynamically. For example, for a particular user, t

相关标签:
3条回答
  • 2021-01-02 15:20

    Here's an idea that'll probably enable you to introduce as many item types as you like without having to modify adapter every time you do:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        AbstractItem abstractItem = ((AbstractItem)getItem(position));
        // if null or new item type is different than the one already there
        if (convertView == null || (convertView.getTag() != null
                && ((AbstractItem)convertView.getTag()).getType().equals(abstractItem.getType())) {
              convertView = abstractItem.inflateSelf(getContext());
        }
    
        abstractItem.fillViewWithData(convertView);
        convertView.setTag(abstractItem);
        return convertView;
    }
    
    public class AbstractItem {
        public abstract View inflateSelf(Context context);
        public abstract String getType();
        public abstract void fillViewWithData(View view);
    }
    
    public class PictureSnapItem extends AbstractItem {
        // data fields
        WeakReference<Bitmap> wBitmap;
        String pictureComment;
        ...
    
        public abstract View inflateSelf(Context context) {
            // get layout inflater, inflate a layout resource, return
            return ((Activity)context).getLayoutInflater.inflate(R.layout.picture_snap_item);
        }
        public abstract String getType() {
            // return something class-specific, like this
            return getClass().getCanonicalName();
        }
        public abstract void fillViewWithData(View view) {
            // fill the view with data from fields, assuming view has been
            // inflated by this very class's inflateSelf(), maybe throw exception if
            // required views can't be found
            ImageView img = (ImageView) view.findViewById(R.id.picture);
            TextView comment = (TextView) view.findViewById(R.id.picture_comment)
        }
    }
    

    ... and then extend AbstractItem and add instances to adapter, no need to add any if clauses to getView() any more.

    0 讨论(0)
  • 2021-01-02 15:26

    If you have small number of possible variants (on your screenshots I can see 2 different list items) You have two possible variants:

    1. Setup count of different types by this method, and provide type for every item - and you can use convertView.

    2. Create "full" list item view and set visibility for elements, that you don't want to see in particular item.

    Some code for #2:

    public class ListTestActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        List<Element> list = new ArrayList<Element>();
        list.add(new Element(0));
        list.add(new Element(0));
        list.add(new Element(1));
        list.add(new Element(0));
        list.add(new Element(1));
        list.add(new Element(1));
        list.add(new Element(0));
        list.add(new Element(0));
        list.add(new Element(1));
        list.add(new Element(1));
        list.add(new Element(1));
        list.add(new Element(0));
        list.add(new Element(0));
        list.add(new Element(1));
        list.add(new Element(0));
        list.add(new Element(0));
        ((ListView) findViewById(android.R.id.list)).setAdapter(new SampleAdapter(this, list));
    }
    
    private class SampleAdapter extends BaseAdapter {
    
        private List<Element> list;
        private Context context;
    
        public SampleAdapter(Context context, List<Element> list) {
            this.list = list;
            this.context = context;
        }
    
        @Override
        public int getCount() {
            return list.size();
        }
    
        @Override
        public Element getItem(int position) {
            return list.get(position);
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null)
                switch (getItemViewType(position)) {
                case 0:
                    convertView = new CheckBox(context);
                    break;
                default:
                    convertView = new Button(context);
                    break;
                }
            // Output here shows that you can lay on getItemViewType(position) as indicator of convertView type or structure
            Log.e("test", getItemViewType(position) + ": " + convertView.getClass().getSimpleName());
            return convertView;
        }
    
        @Override
        public int getItemViewType(int position) {
            return getItem(position).type;
        }
    
        @Override
        public int getViewTypeCount() {
            return 2;
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    }
    
    private class Element {
        public int type;
    
        public Element(int type) {
            this.type = type;
        }
    }
    }
    
    0 讨论(0)
  • 2021-01-02 15:43

    A custom adapter would solve your problem. This is because you can change the views that are being added to each row in the Listview, because you can change the content via logic that you implement in the custom adapter.

    When the getView() method returns a view that is not null, this means for that particular row there is a view that was already there. As such if this is the case, you may or may not want to change content in that specific view. Or you could build a brand new view with dynamic content for that particular row.

    One thing to note is that getView() will be called as many times as there are items found in your adapter.

    0 讨论(0)
提交回复
热议问题