【问题标题】:OnChildClick inside ExpandableListActivity does not fireExpandableListActivity 内的 OnChildClick 不会触发
【发布时间】:2012-05-14 13:56:25
【问题描述】:

我遇到了一个问题,我花了太多时间试图弄清楚。当我的 ExpandableListAdapter 中的一个子项被单击时,我无法触发 OnChildClick 侦听器。

据我了解,当单击其中一行子项时,应该触发下面 ViewCheckListActivity.cs 文件的被覆盖的 OnChildClick 事件。我确定我错过了一些愚蠢的东西,但想知道是否有人有任何经验并且可以为我指明正确的方向以使其正常工作。

代码如下:

CheckListItem_Group.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/loGroup"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:minWidth="25px"
  android:minHeight="25px">
  <CheckedTextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:layout_marginLeft="20px"
      android:paddingLeft="35dip"
      android:textStyle="bold"
      android:textSize="14dip"
      android:gravity="center_vertical"
      android:layout_gravity="right"
      android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
      android:id="@+id/chkCheckList" />
</LinearLayout>

CheckListItem_Item.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/loItem"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:minWidth="25px"
    android:minHeight="25px">
    <CheckedTextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="20px"
        android:paddingLeft="35dip"
        android:textStyle="bold"
        android:textSize="14dip"
        android:gravity="center_vertical"
        android:layout_gravity="right"
        android:clickable="false"
        android:focusable="true"
        android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
        android:id="@+id/chkCheckListItem" />
</LinearLayout>

ViewCheckListActivity.cs

public class ViewCheckListActivity : ExpandableListActivity
{
    private Int32? _checkListId;
    protected static DiversLogDao Dao;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);

        var checkListItems = Dao.GetCheckListItems(_checkListId.Value);

        var adapter = new CheckListItemAdapter(this, checkListItems);
        SetListAdapter(adapter);

        ExpandableListView.ChoiceMode = ChoiceMode.Multiple;
        ExpandableListView.SetOnChildClickListener(this);
    }

    public override bool OnChildClick (ExpandableListView parent, View v, int groupPosition, int childPosition, long id)
    {
        return base.OnChildClick (parent, v, groupPosition, childPosition, id);
    }
}

CheckListItemAdapter.cs

public class CheckListItemAdapter : BaseExpandableListAdapter
{
    private readonly List<Item> _checkListItems;
    public readonly Activity Context;

    public CheckListItemAdapter(Activity context, List<CheckListItem> checkListItems)
    {
        _checkListItems =
            checkListItems.Where(i => i.ParentId == null)
                .Select(i => new Item
                                    {
                                        Id = i.Id,
                                        Name = i.Name,
                                        Description = i.Description,
                                        ChildItems = checkListItems.Where(c => c.ParentId == i.Id)
                                            .Select(c => new ChildItem
                                                            {
                                                                Id = c.Id,
                                                                CheckListId = c.CheckListId,
                                                                ParentId = c.ParentId,
                                                                Name = c.Name,
                                                                Description = c.Description,
                                                                LastUpdated = c.LastUpdated,
                                                                Checked = false
                                                            }).ToList()
                                    }).ToList();
        Context = context;
    }

    public override View GetGroupView(int groupPosition, bool isExpanded, View convertView, ViewGroup parent)
    {
        if (convertView == null)
        {
            convertView = Context.LayoutInflater.Inflate(Resource.Layout.CheckListItem_Group, null) as LinearLayout;
        }

        if (convertView != null)
        {
            var checkList = convertView.FindViewById<CheckedTextView>(Resource.Id.chkCheckList);
            checkList.SetText(_checkListItems[groupPosition].Name, TextView.BufferType.Normal);
            checkList.Checked = _checkListItems[groupPosition].AllChildrenChecked();
        }

        return convertView;
    }

    public override View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
    {
        if(convertView == null)
        {
            convertView = Context.LayoutInflater.Inflate(Resource.Layout.CheckListItem_Item, parent, false) as LinearLayout;
        }

        if (convertView != null)
        {
            var checkListItem = convertView.FindViewById<CheckedTextView>(Resource.Id.chkCheckListItem);
            checkListItem.SetText(_checkListItems[groupPosition].ChildItems[childPosition].Name, TextView.BufferType.Normal);
            checkListItem.Checked = _checkListItems[groupPosition].ChildItems[childPosition].Checked;
            checkListItem.Tag = _checkListItems[groupPosition].ChildItems[childPosition];

            checkListItem.Click -= CheckListItemClick;
            checkListItem.Click += CheckListItemClick;
        }

        return convertView;
    }

    protected void CheckListItemClick(object sender, EventArgs e)
    {
        var chkItem = sender as CheckedTextView;

        if (chkItem == null) return;

        chkItem.Toggle();

        var childItem = chkItem.Tag as ChildItem;

        if (childItem == null) return;

        childItem.Checked = chkItem.Checked;
    }

    public override Object GetChild(int groupPosition, int childPosition)
    {
        return _checkListItems[groupPosition].ChildItems[childPosition];
    }

    public override long GetChildId(int groupPosition, int childPosition)
    {
        return _checkListItems[groupPosition].ChildItems[childPosition].Id;
    }

    public override int GetChildrenCount(int groupPosition)
    {
        return _checkListItems[groupPosition].ChildItems.Count();
    }

    public override Object GetGroup(int groupPosition)
    {
        return _checkListItems[groupPosition];
    }

    public override long GetGroupId(int groupPosition)
    {
        return _checkListItems[groupPosition].Id;
    }

    public override bool IsChildSelectable(int groupPosition, int childPosition)
    {
        return true;
    }

    public override int GroupCount
    {
        get { return _checkListItems.Count(); }
    }

    public override bool HasStableIds
    {
        get { return true; }
    }

    private class Item : Object
    {
        public Int32 Id { get; set; }
        public String Name { get; set; }
        public String Description { get; set; }
        public List<ChildItem> ChildItems { get; set; } 

        public bool AllChildrenChecked()
        {
            return ChildItems.All(i => i.Checked);
        }
    }

    private class ChildItem : Object
    {
        public Int32 Id { get; set; }
        public Int32 CheckListId { get; set; }
        public Int32? ParentId { get; set; }
        public String Name { get; set; }
        public String Description { get; set; }
        public DateTime LastUpdated { get; set; }
        public Boolean Checked { get; set; }
    }
}

【问题讨论】:

    标签: xamarin.android


    【解决方案1】:

    我尝试自己重现此问题,据我所知,这是当前 Android 版本 Mono 中的一个错误。我提交了一个 bug report to Xamarin ,其中包含一个 repro 应用程序和一个可用的 Java 等效应用程序。

    也就是说,当您可以使用单击项目时,还有另一种挂钩选项。您可以在适配器的 GetChildView 方法中为视图上的 Click 事件分配处理程序:

    public override View GetChildView(int groupPosition, int childPosition, bool isLastChild, View convertView, ViewGroup parent)
    {
        // ...existing code in this method...
    
        convertView.Click += delegate 
        {
            // do stuff
        };
    
        return convertView;
    }
    

    【讨论】:

    • 我没有尝试过,但知道这绝对是件好事。经过很多天的努力,我能够让它正常工作。不确定我发现的内容是否符合设计,但如果需要,我很乐意更新您提交的错误。
    【解决方案2】:

    我终于能够完成这项工作。这是我为使其正常工作所做的工作。

    首先是在布局项中添加 focusable 属性,如下所示:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/loItem"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:focusable="false"
        android:minWidth="25px"
        android:minHeight="25px">
        <CheckedTextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20px"
            android:paddingLeft="35dip"
            android:textStyle="bold"
            android:textSize="14dip"
            android:gravity="center_vertical"
            android:layout_gravity="right"
            android:focusable="false"
            android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
            android:id="@+id/chkCheckListItem" />
    </LinearLayout>
    

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/loGroup"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal"
      android:focusable="false"
      android:minWidth="25px"
      android:minHeight="25px">
      <CheckedTextView
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:layout_marginLeft="20px"
          android:paddingLeft="35dip"
          android:textStyle="bold"
          android:textSize="14dip"
          android:gravity="center_vertical"
          android:layout_gravity="right"
          android:focusable="false"      
          android:drawableRight="?android:attr/listChoiceIndicatorMultiple"
          android:id="@+id/chkCheckList" />
    </LinearLayout>
    

    单独这样做并不能解决问题。接下来是可移除的添加到复选框列表的点击事件。

    checkListItem.Click -= CheckListItemClick;
    checkListItem.Click += CheckListItemClick;
    

    进行这 2 项更改可以让事件一直传播到 Activity 本身。

    我只是希望这些信息能在未来对其他人有所帮助。不确定这是否符合设计。

    柴坦亚·马尔维奇

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 1970-01-01
      • 2019-08-07
      相关资源
      最近更新 更多