XML attributes from merge layout to RelativeLayout via inflate
Asked Answered
F

2

15

According to this CommonsWare example I managed to get my RelativeLayout subclass to be merged with my layout described in a xml layout with merge root. My only concern is that I cannot describe my RelativeLayout parameters in xml.

My xml layout:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:my="http://schemas.android.com/apk/res/hu.someproject"
  android:layout_width="36dp"
  android:layout_height="wrap_content"
  android:layout_marginLeft="3dp"
  android:layout_marginRight="3dp"
  android:width="36dp" >

 <RelativeLayout
    android:id="@+id/upper_container"
    style="?pretty_style"
    android:layout_alignLeft="@+id/image_title"
    android:layout_alignParentTop="true"
    android:layout_alignRight="@+id/image_title"
    android:layout_centerHorizontal="true" >

    <View
        android:id="@+id/upper_indicator"
        android:layout_width="fill_parent"
        android:layout_height="5dp"
        android:layout_alignParentTop="true"
        android:background="@color/mycolor" />

    <TextView
        android:id="@+id/text_degree"
        style="?pretty_style"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="23°" />
</RelativeLayout>

<hu.MyView
    android:id="@+id/image_title"
    style="?my_image_title"
    android:layout_below="@+id/upper_container"
    android:layout_centerHorizontal="true"
    my:myColor="#2f8741"/>

I think the problem is that merge happens to the children of the merge tag, and not the merge itself. Any idea how can I get my parameters in the merge to affect my RelativeLayout?

My RelativeLayout subclass, without package declaration and imports:

public class MyRelativeLayoutSubclass extends RelativeLayout {

    public MyRelativeLayoutSubclass(Context context) {
        super(context);

        initTile(null);
    }

    public MyRelativeLayoutSubclass(Context context, AttributeSet attrs) {
        super(context, attrs);

        initTile(attrs);
    }

    public MyRelativeLayoutSubclass(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initTile(attrs);
    }

    private void initTile(Object object) {
        final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_great_little_layout, this, true);
    }
}

I know I can add everything to a LayoutParams, and then add my MyRelativeLayoutSubclass with that LayoutParams, but I would like escape that, that's a lot of unnecessary code.

Faze answered 20/1, 2012 at 11:54 Comment(0)
B
22

I think the problem is that merge happens to the children of the merge tag, and not the merge itself.

AFAIK, you are correct. <merge> is a placeholder, not a ViewGroup.

I know I can add everything to a LayoutParams, and then add my MyRelativeLayoutSubclass with that LayoutParams, but I would like escape that, that's a lot of unnecessary code.

Create an XML layout file containing a MyRelativeLayoutSubclass element, and put your attributes there. Then, inflate that layout.

Bellflower answered 20/1, 2012 at 12:14 Comment(8)
This is a very obvious solution, and I have no idea why I missed it.Faze
It doesn't let you have default attributes easily though. I have to re-enter them every time I use my custom component.Kuth
@Timmmm: MyRelativeLayoutSubclass can certainly have default values for attributes, used when it tries to read in the attributes from the XML (and fails to encounter them).Bellflower
Yeah but I mean you can't define them in XML (as attempted in the question) which would be the most ideal thing.Kuth
Well, the last advice cannot be applied, unfortunately, to ListView items.Plant
@Snicolas: Custom views certainly can be used in ListView rows.Bellflower
@CommonsWare, for sure Mark, but what I mean is that as soon as you use merge, you cannot pass parameters via XML. If you have to wrap a custom view using merge into something else to achieve it, you loose the whole point of merge that is to reduce the view hierarchy depth. This optimization being especially useful for lists. As in listviews, you would instanciate a custom view using its code-constructor, it would not be possible to customize it via XML parameter anymore, only programmatically. Sorry I was not clear. Btw, I am at andev con too. Do we lunch together tomorrow ?Plant
Although this is a working solution, it's far from ideal. You'd need two XML files for a single view, and naming gets hard.Waers
H
3

Extracting all the attributes into Style was a solution for me. As a bonus it's screen-size dependent unlike the hard-coded attributes or Java-code. Maybe you can go further and put it into the Theme attributes.

<com.example.widget.MyCustomView
    android:id="@+id/my_custom_view"

    style="@style/MyCustomView.Default"/>
Hoick answered 15/11, 2013 at 15:12 Comment(1)
Attributes and programmatic LayoutParams can be screen size dependant.Systematism

© 2022 - 2024 — McMap. All rights reserved.