Android自定义视图组不呈现子项

时间:2017-08-15 09:12:02

标签: c# android android-layout

我正在尝试编写一个自定义视图组,我目前在我的布局文件中复制很多。这是一个非常简单的文本框,两个文本框放置在一个垂直方向和一些填充的线性布局中。值得一提的是,我使用Xamarin来开发这个应用程序,但我不认为这个问题是特定于Xamarin的。我的实现如下:

[Register("qube.AppListItem")]
class AppListItem : LinearLayout
{
    private string m_Label;
    private string m_Value;
    private int m_LabelSize;
    private int m_ValueSize;
    private int m_HorizontalPadding;
    private int m_VerticalPadding;
    private ValueType m_ValueType;

    private TextView m_LabelView;
    private TextView m_ValueView;

    public AppListItem(Context context) : this(context, null)
    {
    }

    public AppListItem(Context context, IAttributeSet attrs) : this(context, attrs, 0)
    {
    }

    public AppListItem(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
    {
        Initialize(context, attrs);
    }

    private void Initialize(Context context, IAttributeSet attrs)
    {
        var a = context.ObtainStyledAttributes(attrs, Resource.Styleable.AppListItem, 0, 0);

        m_Label = a.GetString(Resource.Styleable.AppListItem_label);
        m_Value = a.GetString(Resource.Styleable.AppListItem_value);
        m_LabelSize = a.GetDimensionPixelOffset(Resource.Styleable.AppListItem_labelSize, Resource.Dimension.font_small);
        m_ValueSize = a.GetDimensionPixelOffset(Resource.Styleable.AppListItem_valueSize, Resource.Dimension.font_medium);
        m_HorizontalPadding = a.GetDimensionPixelOffset(Resource.Styleable.AppListItem_horizontalPadding, Resource.Dimension.row_padding);
        m_VerticalPadding = a.GetDimensionPixelOffset(Resource.Styleable.AppListItem_verticalPadding, Resource.Dimension.info_list_padding);
        m_ValueType = (ValueType)a.GetInt(Resource.Styleable.AppListItem_valueType, (int)ValueType.STRING);

        a.Recycle();

        Orientation = Orientation.Vertical;
        Clickable = true;
        SetPadding(m_HorizontalPadding, m_VerticalPadding, m_HorizontalPadding, m_VerticalPadding);

        if (Build.VERSION.SdkInt >= BuildVersionCodes.Honeycomb)
        {
            // If we're running on Honeycomb or newer, then we can use the Theme's
            // selectableItemBackground to ensure that the View has a pressed state
            TypedValue outValue = new TypedValue();
            Context.Theme.ResolveAttribute(Android.Resource.Attribute.SelectableItemBackground, outValue, true);
            SetBackgroundResource(outValue.ResourceId);
        }

        BuildView();
    }

    private void BuildView()
    {
        m_LabelView = new TextView(Context);
        m_LabelView.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
        m_LabelView.TextSize = m_LabelSize;
        m_LabelView.Text = m_Label;
        AddView(m_LabelView);

        if (m_ValueType == ValueType.EDITTEXT)
            m_ValueView = new EditText(Context);
        else
            m_ValueView = new TextView(Context);

        m_ValueView.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
        m_ValueView.TextSize = m_ValueSize;
        m_ValueView.Text = m_Value;
        AddView(m_ValueView);
    }

    protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);
    }

    public string Label
    {
        get { return m_Label; }
        set
        {
            m_Label = value;
            m_LabelView.Text = value;
            Invalidate();
            RequestLayout();
        }
    }

    public string Value
    {
        get { return m_ValueView.Text; }
        set
        {
            m_ValueView.Text = value;
            m_Value = value;
            Invalidate();
            RequestLayout();
        }
    }

    public enum ValueType
    {
        STRING, EDITTEXT
    }
}

如上所述,预期的行为是两个堆叠在一起的文本框,但实际行为是高度为0的视图(如果android:layout_height="wrap_content")。手动将layout_height设置为20dp只会显示该高度的空白视图。

1 个答案:

答案 0 :(得分:0)

好吧,我犯的错误是愚蠢的,这是可以预料的。当我从typedarray获取维度时,我传入的默认值是资源ID而不是与这些id相关联的实际值。例如:

m_LabelSize = a.GetDimensionPixelOffset(Resource.Styleable.AppListItem_labelSize, Resource.Dimension.font_small);

应该是

m_LabelSize = a.GetDimensionPixelOffset(Resource.Styleable.AppListItem_labelSize, Resources.GetDimensionPixelOffset(Resource.Dimension.font_small));