Breiz
Breiz

Reputation: 1193

Dynamically adding views to mixed xml/code compound layout

Sorry if this redundant with the ton of questions/answers on inflate, but I could not get a solution to my problem.

I have a compound view (LinearLayout) that has a fixed part defined in XML and additional functionalities in code. I want to dynamically add views to it.

Here is the XML part (compound.xml):

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/compoundView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView android:id="@+id/myTextView" 
        android:layout_width="110dp" 
        android:layout_height="wrap_content"
        android:text="000"  />
</LinearLayout>

I have defined in code a LinearLayout to refer to the XML:

public class CompoundControlClass extends LinearLayout {
    public CompoundControlClass (Context context) {
        super(context);
        LayoutInflater li;
        li = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        li.inflate(R.layout.compound_xml,*ROOT*, *ATTACH*);
    }
    public void addAView(){
        Button dynBut = new Button();
        // buttoin def+layout info stripped for brevity
        addView(dynBut);
    }
}

I tried to programmatically add a view with addAView.

If ROOT is null and ATTACH is false, I have the following hierarchy (per HierarchyViewer):

The original TextView in the XML is gone.

If ROOT is this and ATTACH is true, I have the following hierarchy:

I would like to have

where basically the code and XML are only one unique View. What have I grossly missed?

ANSWER BASED on feedback from D Yao ----------------------

The trick is to INCLUDE the compound component in the main layout instead of referencing it directly.

activity_main.xml

<RelativeLayout 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">
    <include layout="@layout/comound"
        android:id="@+id/compoundView"
        android:layout_alignParentBottom="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>
</RelativeLayout>

mainActivity.java

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CompoundControlClass c = (CompoundControlClass) this.findViewById(R.id.compoundView);
        c.addAView(this);
    }  
}

CompoundControlClass.java

public class CompoundControlClass extends LinearLayout {
    public CompoundControlClass(Context context) {
        super(context);
    }
    public CompoundControlClass(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public CompoundControlClass(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void addAView(Context context){
         ImageView iv = new ImageView(context);                    
         iv.setImageResource(R.drawable.airhorn);
         addView(iv);
    }
}

compound.xml

<com.sounddisplaymodule.CompoundControlClass    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/compoundView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" > 
    <TextView
        android:layout_width="110dp" 
        android:layout_height="wrap_content"
        android:gravity="right"
        android:textSize="40sp"
        android:textStyle="bold"
        android:text="0:00"  />     
</com.sounddisplaymodule.CompoundControlClass>

Upvotes: 3

Views: 1550

Answers (1)

D Yao.
D Yao.

Reputation: 401

Why not just call addView on the linearlayout? I don't see the need for CompoundControlClass based on the needs you have listed.

LinearLayout v = (LinearLayout)findViewById(R.id.compoundView);
v.addView(dynBut);

In this case, v will contain myTextView, then dynBut.

if you wish to have other functions added and thus really feel a need for creating the compound control class, just leave the constructor as super(etc) and remove the rest

Then your xml would look like this:

<com.yourpackage.CompoundControlClass xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/compoundView"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >
    <TextView android:id="@+id/myTextView" 
        android:layout_width="110dp" 
        android:layout_height="wrap_content"
        android:text="000"  />
</com.yourpackage.CompoundControlClass>

you will also have to ensure your CompoundControlClass.java contains the appropriate Constructor which takes both a Context and an attribute set.

Then, in your java, after you've called setContentView, you can do the following:

CompoundControlClass c = (CompoundControlClass)findViewById(R.id.compoundView);
Button b = new Button(context);
//setup b here or inflate your button with inflater
c.addView(b);

this would give you your desired heirarchy.

Upvotes: 1

Related Questions