问题
I wanted to get the CustomChoiceList to work with MvvmCross, but was struggling getting the sample working, the ListItem wouldn't get selected.
In fact the sample uses a custom LinearLayout that extends LinearLayout and implements ICheckable. When using the same layout with a MvxAdapter and an MvxListView the method OnCreateDrawableState is never called and the text and selection icon are never high-lighted.
I'm aware that the selected item could be stored in the ViewModel.
Here is the original sample: https://github.com/xamarin/monodroid-samples/tree/master/CustomChoiceList
回答1:
In fact the MvxAdapter class inflates the list item layout into a MvxListItemView behind the scenes, so you actually get an additional FrameLayout around your list item template. MvxListItemView doesn't implement ICheckable and therefore the information whether to check the item is not propagated.
The trick is to implement a custom MvxAdapter overwriting CreateBindableView and return a subclass of MvxListItemView that implements ICheckable.
You also must set the android:duplicateParentState="true"
int the root of the list item template (list_item.axml)
You can find the complete project here: https://github.com/takoyakich/mvvmcross-samples/tree/master/CustomChoiceList
Below the relevant changes:
list_item.axml:
<?xml version="1.0" encoding="utf-8"?>
<customchoicelist.CheckableLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:duplicateParentState="true"
...
Extended 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);
}
}
Extended 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;
}
}
来源:https://stackoverflow.com/questions/18672562/mvxlistview-checkable-list-item