3

我想让 CustomChoiceList 与 MvvmCross 一起使用,但在努力让示例正常工作时,不会选择 ListItem。

事实上,该示例使用了一个自定义的 LinearLayout,它扩展了 LinearLayout 并实现了 ICheckable。当使用与 MvxAdapter 和 MvxListView 相同的布局时,永远不会调用方法 OnCreateDrawableState 并且永远不会突出显示文本和选择图标。

我知道所选项目可以存储在 ViewModel 中。

这是原始示例: https ://github.com/xamarin/monodroid-samples/tree/master/CustomChoiceList

4

1 回答 1

3

事实上,MvxAdapter 类在幕后将列表项布局扩展为 MvxListItemView,因此您实际上在列表项模板周围获得了一个额外的 FrameLayout。MvxListItemView 没有实现 ICheckable,因此不会传播是否检查项目的信息。

诀窍是实现自定义 MvxAdapter 覆盖 CreateBindableView 并返回实现 ICheckable 的 MvxListItemView 的子类。您还必须将android:duplicateParentState="true"int 设置为列表项模板的根 (list_item.axml)

你可以在这里找到完整的项目: https ://github.com/takoyakich/mvvmcross-samples/tree/master/CustomChoiceList

下面是相关改动:

list_item.axml:

<?xml version="1.0" encoding="utf-8"?>
<customchoicelist.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
    android:duplicateParentState="true"
...

扩展 MvxAdapter:

class MyMvxAdapter : MvxAdapter {
        private readonly Context _context;
        private readonly IMvxAndroidBindingContext _bindingContext;

        public MyMvxAdapter(Context c) :this(c, MvxAndroidBindingContextHelpers.Current())
        {
        }
        public MyMvxAdapter(Context context, IMvxAndroidBindingContext bindingContext) :base(context, bindingContext)
        {
            _context = context;
            _bindingContext = bindingContext;
        }
        protected override MvxListItemView CreateBindableView(object dataContext, int templateId)
        {
            return new MyMvxListItemView(_context, _bindingContext.LayoutInflater, dataContext, templateId);
        }
    }

扩展 MvxListItemView :

class MyMvxListItemView : MvxListItemView, ICheckable
{

    static readonly int[] CHECKED_STATE_SET = {Android.Resource.Attribute.StateChecked};
    private bool mChecked = false;

    public MyMvxListItemView(Context context,
                           IMvxLayoutInflater layoutInflater,
                           object dataContext,
                           int templateId)
        : base(context, layoutInflater, dataContext, templateId)
    {         
    }

    public bool Checked {
        get {
            return mChecked;
        } set {
            if (value != mChecked) {
                mChecked = value;
                RefreshDrawableState ();
            }
        }
    }

    public void Toggle ()
    {
        Checked = !mChecked;
    }

    protected override int[] OnCreateDrawableState (int extraSpace)
    {
        int[] drawableState = base.OnCreateDrawableState (extraSpace + 1);

        if (Checked)
            MergeDrawableStates (drawableState, CHECKED_STATE_SET);

        return drawableState;
    }
}
于 2013-09-07T10:55:12.570 回答