绑定到MvxLinearLayout中的View的宽度

时间:2016-07-31 22:16:36

标签: android xamarin xamarin.android mvvmcross

我想创建数据绑定到View的宽度,该宽度位于MvxLinearLayout内的MvxListView内。

因此,MvxListView包含MvxLinearLayout项,其中包含View 需要Width绑定的项目。

我的布局代码(为清晰起见,删除了不必要的ViewGroup个容器):

MvxListView

<Mvx.MvxLinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        local:MvxBind="ItemsSource ContainerItems; ItemClick DoSomething"
        local:MvxItemTemplate="@layout/container_item_template"
        />

container_item_template

<Mvx.MvxLinearLayout
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:orientation="horizontal"
    local:MvxBind="ItemsSource MyItems"
    local:MvxItemTemplate="@layout/my_item_template" />

my_item_template

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="40dp"
android:layout_height="20dp"
local:MvxBind="Width Width" />

我创建了以下自定义目标绑定:

public class ViewWidthCustomBinding : MvxAndroidTargetBinding
{
    public ViewWidthCustomBinding(object target) : base(target)
    {

    }

    public override Type TargetType
    {
        get { return typeof (double); }
    }

    protected override void SetValueImpl(object target, object value)
    {
        var realTarget = target as View;
        if (target == null)
            return;
        int width = 0;

        if (value is int)
        {
            width = (int) value;
        }
        else if (value is float)
        {
            width = (int) Math.Ceiling((float) value);
        }
        else if (value is double)
        {
            width = (int)Math.Ceiling((double)value);
        }

        if (width < 1)
        {
            return;
        }
        // my LayoutParameters here are always null for some reason
        // so the layout parameters are not set to the 40dp. 20dp, as it is set above in the item template
        // Looks like this gets applied first, and then it is replaced when actual parent (root) gets assigned since all my views get the 40do width, 20dp height assigned in the item template
        realTarget.LayoutParameters = new MvxLinearLayout.LayoutParams(width, MvxLinearLayout.LayoutParams.MatchParent);

    }
}

有人有什么想法吗?

1 个答案:

答案 0 :(得分:4)

我认为你必须处理竞争条件绑定与布局通胀(从XML /布局周期创建布局参数)。

我认为您必须使用自定义视图,如:

public class CustomView : View
{
    private double _customWidth;

    public double CustomWidth
    {
        get { return _customWidth; }
        set
        {
            _customWidth = value;
            var param = LayoutParameters;

            if (param != null)
            {
                param.Width = (int)_customWidth;
            }
            LayoutParameters = param;
        }
    }

    public override ViewGroup.LayoutParams LayoutParameters
    {
        get { return base.LayoutParameters; }
        set
        {
            if (value != null)
            {
                value.Width = (int)_customWidth;
                base.LayoutParameters = value;
            }
        }
    }

    public CustomView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
    {
    }

    public CustomView(Context context) : base(context)
    {
    }

    public CustomView(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public CustomView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
    {
    }

    public CustomView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
    {
    }
}

然后绑定CustomWidth而不是Width

<CustomView
    android:layout_width="40dp"
    android:layout_height="20dp"
    android:background="#FF0000"
    local:MvxBind="CustomWidth MyWidth"/>

如果要在绑定目标中绑定不同类型的宽度值(int,float,double),则必须将转换转换为转换器或稍微更改绑定目标。我想你明白了。

这里的好处是,您不必知道布局参数的类型(例如MvxLinearLayout.LayoutParams),因为您不必自己创建它。这有两个好处:

  • 您不会覆盖其他属性,例如边距,高度等。
  • 它可以在多个父布局中使用