简体   繁体   中英

Android custom viewgroup not rendering children

I am trying to write a custom viewgroup which I currently duplicate a lot across my layout files. It is a really simple one, two textboxes placed within a linearlayout with a vertical orientation and some padding. It is worth mentioning that I use Xamarin to develop this application, but I don't think the issue is Xamarin specific. My implementation is as follows:

[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
    }
}

The expected behavior is, as said, two textboxes stacked on top of each other, however, the actual behavior is a view with height 0 (if android:layout_height="wrap_content" ). Setting the layout_height to something like 20dp manually just shows a blank view of that height.

Okay, the mistake I made was a silly one, which was to be expected. When I get the dimensions from the typedarray, the default value I pass in are resource id's instead of the actual values associated with those id's. For example:

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

should be

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM