peter.o
peter.o

Reputation: 3530

Create custom LinearLayout and fill it with Views

I've got a main LinearLayout, in main.xml file, which is set (setContentView) in Activity. Into the main LinearLayout I want to add 1-X custom LinearLayouts. So I've created one XML "template" detail_line.xml :

<?xml version="1.0" encoding="utf-8"?>
<com.test.layout.DetailLine
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingBottom="@dimen/button_bottom_padding">

        <LinearLayout
            android:id="@+id/purpleLine"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:orientation="horizontal">

            <!-- programmatically add other views -->

        </LinearLayout>

        <!-- more "purpleLines" will be coming but for now it's not a point of interest -->

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:paddingBottom="@dimen/detail_save_buttons"
        android:paddingTop="@dimen/detail_save_buttons">

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@android:color/darker_gray" />

    </LinearLayout>

</com.test.layout.DetailLine>

And this is the Class:

    public class DetailLine extends LinearLayout {

    private Map<String, String> row;

    private Context context;

    public DetailLine(Context context) {
        super(context);
        this.context = context;
        this._create();
    }

    public DetailLine(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        this._create();
    }

    public DetailLine(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        this._create();
    }

    /**
     * Inflates XML layout
     */
    private void _create() {
        this._purpleLine();
    }

    /**
     * Creates purple line
     */
    private void _purpleLine() {

        LinearLayout purpleLine = (LinearLayout) this.findViewById(R.id.purpleLine);
        purpleLine.removeAllViews(); // NullPointerException thrown here

// Add views...
    }
}

NullPointerException is thrown when using child View from custom LinearLayout. It looks like there is no connection between XML and Class. I tried calling LayoutInflater.from(this.context).inflate(R.layout.detail_line, null);, but no success. I've checked tutorial over here, but I'm not smarter rather confused with the <merge> stuff.

Upvotes: 1

Views: 3267

Answers (2)

peter.o
peter.o

Reputation: 3530

I've managed to find a correct answer, finally. All that needs to be done is to inflate LinearLayout file in a different way and change custom layout name (com.test.layout.DetailLine) back to LinearLayout.

private void _create() {
    inflate(this.context, R.layout.detail_line, this);
    this._purpleLine();
}

Credits: http://trickyandroid.com/protip-inflating-layout-for-your-custom-view/

Upvotes: 1

Karakuri
Karakuri

Reputation: 38605

You are calling _create() in your DetailLine's constructor, when it does not have children yet. You need to override onFinishInflate() instead, and then you can access its children:

protected void onFinishInflate() {
    LinearLayout purpleLine = (LinearLayout) this.findViewById(R.id.purpleLine);
    purpleLine.removeAllViews();
    ...
}

Upvotes: 0

Related Questions