Home » Android » android – Use XML Layout as view for View Subclass?

android – Use XML Layout as view for View Subclass?

Posted by: admin June 15, 2020 Leave a comment

Questions:

I feel as though I used to know how to do this, but I’m currently drawing a blank. I have a class that extends from View (Card) and I wrote a layout for it in XML. What I want to do is set the View of Card to be the XML View in the constructor, so I can use the methods in Card to set TextViews and whatnot. Any suggestions? Code below:

Card.java:
(I have View.inflate(context, R.layout.card_layout, null); there as an example of what I want to do, but it’s not working. I basically want the class to be the interface for the View, and in order to do that I need to somehow assign the XML layout to the View. Do I use something along the lines of setContentView(View view)? There is no such method in the View class, but is there something like it?)

public class Card extends View {

    TextView tv;

    public Card(Context context) {
        super(context);
        View.inflate(context, R.layout.card_layout, null);
        tv = (TextView) findViewById(R.id.tv);
    }

    public Card(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        View.inflate(context, R.layout.card_layout, null);
        tv = (TextView) findViewById(R.id.tv);
    }

    public Card(Context context, AttributeSet attrs) {
        super(context, attrs);
        View.inflate(context, R.layout.card_layout, null);
        tv = (TextView) findViewById(R.id.tv);
    }

    public void setText(String text) {
        tv.setText(text);
    }

}

card_layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="336dp"
    android:layout_height="280dp"
    android:layout_gravity="center"
    android:background="@drawable/card_bg"
    android:orientation="vertical" >


    <TextView
        android:id="@+id/tv"
        android:layout_height="fill_parent"
        android:layout_width="wrap_content"
        android:textSize="24dp"
    />

</LinearLayout>
How to&Answers:

What you’re trying to do is not possible with the current setup. A View(or a direct subclass of it) represent a single view it doesn’t have the notion of child views, what you’re trying to do. The LayoutInflater can’t be used with a simple View because the simple View class doesn’t have the methods to actually add the child to it(like the addView() method).

On the other hand, the correct class to use to be able to have children is the ViewGroup(or one of the direct subclasses like LinearLayout, FrameLayout etc) which accept adding Views or other ViewGroups to it, by supplying the addView methods. In the end your class should be:

public class Card extends ViewGroup {

    TextView tv;

    public Card(Context context) {
        super(context);
        View.inflate(context, R.layout.card_layout, this);
        tv = (TextView) findViewById(R.id.tv);
    }

    public Card(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        View.inflate(context, R.layout.card_layout, this);
        tv = (TextView) findViewById(R.id.tv);
    }

    public Card(Context context, AttributeSet attrs) {
        super(context, attrs);
        View.inflate(context, R.layout.card_layout, this);
        tv = (TextView) findViewById(R.id.tv);
    }

    public void setText(String text) {
        tv.setText(text);
    }

}

If I recall you have to override onLayout if you extend ViewGroup, so instead(and because of your layout file), you should look at extending LinearLayout and replace the LinearLayout from the xml layout with a merge tag.

Answer:

You should be able to use your class name in the layout. Something like:

<your.package.name.Card 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="336dp"
    android:layout_height="280dp"
    ...

Just call findViewById to get child views.

To use your Card class, you use the inflator to get an instance, then attach it to a parent view.

LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
Card card = (Card) inflater.inflate(R.layout.card_layout, null);
parentView.addView(card);

Have a look at the docs for more info.