user270811
user270811

Reputation: 1751

custom view with layout

ok,

what i am trying to do is to embed a custom view in the default layout main.xml:

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

    <com.lam.customview.CustomDisplayView
        android:id="@+id/custom_display_view1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />


    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/prev"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:layout_weight="50"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:text="@string/prev" />
    </LinearLayout>
</LinearLayout>

as you can see the class is called com.lam.customview.CustomDisplayView, with the id of custom_display_view1.

now in the com.lam.customview.CustomDisplayView class, i want to use another layout called custom_display_view.xml because i don't want to programmatically create controls/widgets.

custom_display_view.xml is just a button and an image, the content of which i want to change based on certain conditions:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView 
    android:id="@+id/display_text_view1" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
    <ImageView 
    android:id="@+id/display_image_view1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
    </ImageView>

</LinearLayout>

i tried to do:

1)

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

    try
    {
        // register our interest in hearing about changes to our surface
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);

        View.inflate(context, R.layout.custom_display_view, null);

...

but got this error, "03-08 20:33:15.711: ERROR/onCreate(10879): Binary XML file line #8: Error inflating class java.lang.reflect.Constructor ".

2)

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

    try
    {
        // register our interest in hearing about changes to our surface
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);

        View.inflate(context, R.id.custom_display_view1, null);

...

but got this error, "03-08 20:28:47.401: ERROR/CustomDisplayView(10806): Resource ID #0x7f050002 type #0x12 is not valid "

also, if i do it this way, as someone has suggested, it's not clear to me how the custom_display_view.xml is associated with the custom view class.

thanks.

Upvotes: 35

Views: 65363

Answers (6)

Frank Schwieterman
Frank Schwieterman

Reputation: 24480

This blog post helped me understand what to do immensely http://trickyandroid.com/protip-inflating-layout-for-your-custom-view/. In case the blog post disappears, here are some parts of the code:

public class Card extends RelativeLayout {
    public Card(Context context) {
        super(context);
        init();
    }

    public Card(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public Card(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        inflate(getContext(), R.layout.card, this);
    }
}

with this layout:

<?xml version="1.0" encoding="utf-8"?>

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/card_padding"
    android:background="@color/card_background">

    <ImageView
        ... />

    <TextView
        ... />

</merge>

The control is included like:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin">

    <com.trickyandroid.customview.app.view.Card
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/card_background"
        android:padding="@dimen/card_padding"/>

</FrameLayout>

Where com.trickyandroid.customview.app.view is the namespace of class card. One thing that was new to me was the "merge" tag, which ends up being the same node as the Card tag in the containing doc.

Upvotes: 9

Jannie Theunissen
Jannie Theunissen

Reputation: 30164

When you inflate your layout, you should pass in a reference to the view instance to identify it as the root. So instead of calling:

View.inflate(context, R.layout.custom_display_view, null);

Call:

View.inflate(context, R.layout.custom_display_view, this);

See: The docs

Upvotes: 5

Karan
Karan

Reputation: 12782

Try using

context.getLayoutInflater().inflate( R.id.custom_display_view1, null );

Upvotes: 0

Jay
Jay

Reputation: 3233

Line #8 is your custom view in the first layout. Are you trying to load the wrong layout, so it's trying to load itself recursively? (I just did the same thing)

also you have:

 R.layout.custom_display_view

vs.

 R.id.custom_display_view1

with the 1 on the end there... which one is it?

Upvotes: 0

Rino Farina
Rino Farina

Reputation: 1116

I had the exact same issue, and the problem was that I was using the wrong ID... and it look's like you are too.

You should be referencing

R.layout.custom_display_view

-not-

R.id.custom_display_view

Upvotes: 70

herbertD
herbertD

Reputation: 10955

You can inflate the cutom_display_view into your custom class by:

public CustomDisplayView(Context context, AttributeSet attrs) {   
    super(context, attrs);           
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if(inflater != null){       
                inflater.inflate(R.layout.custom_display_view, this);
            }
}

Upvotes: 7

Related Questions