自定义多选列表视图Android

时间:2014-03-04 09:20:03

标签: java android xamarin.android

我一直在尝试创建一个多选的ListView,就像在这个链接中查看图片一样: picture 当用户取消选中左上角的复选框时,listviewItem布局必须更改为未选中状态。 现在我用它:

public class ProcedureAdapter : BaseAdapter<Procedure>
{
    List<Procedure> items;
    Activity context;
    Dictionary<int, bool> CheckedItems = new Dictionary<int, bool>();
    public ProcedureAdapter(Activity context, List<Procedure> items)
        : base()
    {
        this.context = context;
        this.items = items;
        for (int i = 0; i < items.Count; i++)
        {
            CheckedItems.Add(i, false);
        }
    }
    public override long GetItemId(int position)
    {
        return position;
    }
    public override Procedure this[int position]
    {
        get { return items[position]; }
    }
    public override int Count
    {
        get { return items.Count; }
    }

    public void toggleCheck(int position)
    {
        if (CheckedItems.ContainsKey(position))
        {
            CheckedItems[position] = !CheckedItems[position];
            base.NotifyDataSetChanged();
        }
    }
    public override View GetView(int position, View convertView, ViewGroup parent)
    {
        var item = items[position];
        View view = convertView;
        if (view == null) 
            view = context.LayoutInflater.Inflate(Resource.Layout.ProcedureListViewItem, null);

        if (!CheckedItems.ContainsKey(position))
            CheckedItems.Add(position, false);

        if (CheckedItems[position])
        {
            checkBox.Visibility = ViewStates.Visible;
            checkBox.Checked = true;
            ProcedureTypeImage.Visibility = ViewStates.Gone;
        }
        else
        {
            checkBox.Visibility = ViewStates.Gone;
            checkBox.Checked = false;
            ProcedureTypeImage.Visibility = ViewStates.Visible;
        }



        return view;
    }
}

在活动中:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var view = inflater.Inflate(Resource.Layout.ProceduresLayout, container, false);
        listView = view.FindViewById<ListView>(Resource.Id.listView1);
        listView.ItemLongClick += listView_ItemLongClick;
        procAdapter = new ProcedureAdapter(Activity, procedures);
        listView.Adapter = procAdapter;

        return view;
    }

    void listView_ItemLongClick(object sender, AdapterView.ItemLongClickEventArgs e)
    {
        procAdapter.toggleCheck(e.Position);
    }

但我遇到了问题: 当用户取消选中复选框时,如何更改布局? 我试过在Adapter中处理CheckedChange事件,但我怎么知道这个ListViewItem的位置? 我的解决方案在我看来不是很好,请给我建议我怎样才能做得更好。 我想知道你是否向我展示了一个关于C#或Java的简单例子。 感谢

1 个答案:

答案 0 :(得分:0)

我做了一个可能对你有帮助的简单例子。它是一个列表,每个列表项都有一个TextView和CheckBox。文本视图显示绿色或红色的位置,具体取决于是否选中复选框。它是您问题的简化版本。不知道它是否是最好的解决方案,但它会起作用。

唯一需要注意的事项。由于绑定复选框时会重复使用视图,因此它可以触发CheckedChange事件。这就是在进行绑定时首先更改Tag的原因。

using System.Globalization;
using Android.App;
using Android.Graphics;
using Android.Views;
using Android.Widget;
using Object = Java.Lang.Object;

namespace AndroidApplication1
{
    public class LvAdapter : BaseAdapter
    {
        private readonly Activity _context;
        public bool[] Bools = new bool[15];

        public LvAdapter(Activity context)
        {
            _context = context;
        }

        public override Object GetItem(int position)
        {
            return null;
        }

        public override long GetItemId(int position)
        {
            return position;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            ViewHolder vh;

            var view = convertView;
            if (view == null)
            {
                view = _context.LayoutInflater.Inflate(Resource.Layout.list_item, parent, false);
                vh = new ViewHolder();
                vh.Initialize(view, this);
                view.Tag = vh;
            }
            vh = view.Tag as ViewHolder;
            if (vh != null) vh.Bind(position, Bools);
            return view;
        }

        public override int Count
        {
            get { return Bools.Length; }
        }

        private class ViewHolder : Object
        {
            private TextView _text;
            private CheckBox _check;

            public void Initialize(View view, LvAdapter adapter)
            {
                _text = view.FindViewById<TextView>(Resource.Id.tvText);
                _check = view.FindViewById<CheckBox>(Resource.Id.cbCheck);

                _check.CheckedChange += (sender, args) =>
                {
                    var tagHoldr = (((View) sender).Tag) as TagHolder;
                    adapter.Bools[tagHoldr.Positon] = args.IsChecked;
                    tagHoldr.TextView.SetTextColor(args.IsChecked ? Color.Green : Color.Red);
                };
            }

            public void Bind(int position, bool[] bools)
            {
                _check.Tag = new TagHolder { Positon = position, TextView = _text };
                _text.Text = position.ToString(CultureInfo.InvariantCulture);
                _check.Checked = bools[position];
                _text.SetTextColor(bools[position] ? Color.Green : Color.Red);
            }
        }

        private class TagHolder : Object
        {
            public int Positon { get; set; }
            public TextView TextView { get; set; }
        }
    }
}