Jamie-505 Jamie-505 - 5 months ago 35
Android Question

Adding a CardView to a FrameLayout ignores LayoutParams defined in the CardView's XML file

In my MainActivity I'm using a FloatingActionButton to add CardViews to an existing container (a FrameLayout) programatically.

But when I add the CardView all LayoutParams (e.g. width, height, margin, etc) are ignored. Is there a way to use the params specified in the XML File?

Here is my code:

card_view.xml

<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/cardview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
card_view:cardCornerRadius="2dp"
card_view:cardBackgroundColor="@color/cardViewBackground">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="example Text" />

</android.support.v7.widget.CardView>


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />

<TextView
android:id="@+id/textViewDate"
android:text="@string/default_main_activity_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="@color/colorPrimary"
android:textSize="20sp"
android:textAlignment="center"
android:padding="16dp" />

<FrameLayout
android:id="@+id/container_body"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:src="@drawable/ic_fab_add"
android:layout_gravity="end"
android:onClick="addCard"
android:visibility="gone"/>

</LinearLayout>


<fragment
android:id="@+id/fragment_navigation_drawer"
android:name="com.life_hacks.liftnotes.activity.FragmentDrawer"
android:layout_width="@dimen/nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="@layout/fragment_navigation_drawer"
tools:layout="@layout/fragment_navigation_drawer" />

</android.support.v4.widget.DrawerLayout>


and finally the code I use to add the CardView:

public void addCard(View v){
View cardView = View.inflate(getApplicationContext(), R.layout.card_view, null);
FrameLayout container = (FrameLayout) findViewById(R.id.container_body);
if(container != null){
container.addView(card_view);
}
}

Answer

For the layout_* attributes of an XML-defined View to be applied correctly, the ViewGroup that will hold it must be supplied to the LayoutInflater. In this case, it means that you need to pass your container as the last argument in the View.inflate() call. Doing this will also cause the inflated View to be automatically added to the ViewGroup, so you must not call addView() with it, or you'll get an IllegalStateException.

Also, since you'll be adding multiple Views to your container, it would seem that a LinearLayout would be more appropriate than a FrameLayout. I would also mention that if you plan on adding a lot of additional Views, a ListView or a RecyclerView might end up being a better option.