Create Layout Resource Programmatically Kotlin Android
android, android-layout, android-studio, kotlin
Solution
Ok the solution is as following:
Just need to add removeAllView on all parents before adding the childs
protected fun createXmlElement(title:String,description:String){
val parent = LinearLayout(this)
parent.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
parent.orientation = LinearLayout.HORIZONTAL
//children of parent linearlayout
val iv = ImageView(this)
val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
lp.setMargins(0, 11, 7, 0)
iv.setLayoutParams(lp)
iv.setImageResource(R.drawable.ic_action_play)
iv.getLayoutParams().height = 40
iv.getLayoutParams().width = 46
parent.addView(iv); // lo agregamos al layout
val relativeP = RelativeLayout(this)
relativeP.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT)
val linearCH = LinearLayout(this)
linearCH.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
// TextView1
val tv1 = TextView(this)
val lptv1 = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
lptv1.setMargins(0, 7, 0, 0)
tv1.setLayoutParams(lptv1)
tv1.setText(title) // title
tv1.setTextSize(TypedValue.COMPLEX_UNIT_SP,25F)
tv1.setTypeface(null, Typeface.BOLD)
// TextView2
val tv2 = TextView(this)
val lptv2 = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
lptv2.setMargins(0, 11, 7, 0)
tv2.setLayoutParams(lptv1)
tv2.setText(description) // description
tv2.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25F)
tv2.setTypeface(null, Typeface.BOLD)
linearCH.removeAllViews()
linearCH.addView(tv1)
linearCH.addView(tv2)
relativeP.removeAllViews()
relativeP.addView(linearCH)
// last ImageView
val iv2 = ImageView(this)
val lpiv2 = RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT)
lpiv2.setMargins(0, 11, 7, 0)
lpiv2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT)
iv2.setLayoutParams(lpiv2)
iv2.setImageResource(R.drawable.ic_action_share)
iv2.getLayoutParams().height = 40
iv2.getLayoutParams().width = 46
parent.removeAllViews()
parent.addView(iv)
parent.addView(relativeP)
parent.addView(iv2)
val finalParent = this.findViewById(R.id.contenedor) as ViewGroup
finalParent.addView(parent)
}
Thanks NSion, the error on logcat point to me the right direction!
Problem
I'm having problems trying to make this Layout totally programmatically, every time the process run end without success and the app crashes. The Part of XML im trying to create programmatically is it : ``` <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/idImagenPlay0" android:layout_width="62dp" android:layout_height="54dp" android:layout_marginRight="10dp" android:layout_marginTop="15dp" android:src="@drawable/ic_action_play" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/idNombre0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="Description" android:textSize="25sp" android:textStyle="bold" /> <TextView android:id="@+id/idInfo0" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="15dp" android:layout_marginRight="10dp" android:text="Title" /> </LinearLayout> <ImageView android:id="@+id/idImagenShare0" android:layout_width="54dp" android:layout_height="48dp" android:layout_alignParentRight="true" android:layout_marginRight="10dp" android:layout_marginTop="15dp" android:src="@drawable/ic_action_share" /> </RelativeLayout> </LinearLayout> ``` I'm trying to recreate it with the following kotlin code: ``` fun createXmlElement(title:String,description:String){ val parent = LinearLayout(this) parent.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) parent.orientation = LinearLayout.HORIZONTAL //children of parent linearlayout val iv = ImageView(this) val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) lp.setMargins(0, 11, 7, 0) iv.setLayoutParams(lp) iv.setImageResource(R.drawable.ic_action_play) iv.getLayoutParams().height = 40; iv.getLayoutParams().width = 46; parent.addView(iv); // lo agregamos al layout val relativeP = RelativeLayout(this) relativeP.layoutParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT) val linearCH = LinearLayout(this) linearCH.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) // TextView1 val tv1 = TextView(this) val lptv1 = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) lptv1.setMargins(0, 7, 0, 0) tv1.setLayoutParams(lptv1) tv1.setText(title) // nombre de la musica tv1.setTextSize(TypedValue.COMPLEX_UNIT_SP,25F) tv1.setTypeface(null, Typeface.BOLD); // TextView2 val tv2 = TextView(this) val lptv2 = LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) lptv2.setMargins(0, 11, 7, 0) tv2.setLayoutParams(lptv1) tv2.setText(description) // Descripcion de la musica tv2.setTextSize(TypedValue.COMPLEX_UNIT_SP, 25F) tv2.setTypeface(null, Typeface.BOLD); linearCH.addView(tv1) linearCH.addView(tv2) relativeP.addView(linearCH) // last ImageView val iv2 = ImageView(this) val lpiv2 = RelativeLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) lpiv2.setMargins(0, 11, 7, 0) lpiv2.addRule(RelativeLayout.ALIGN_PARENT_RIGHT) iv2.setLayoutParams(lpiv2) iv2.setImageResource(R.drawable.ic_action_share) iv2.getLayoutParams().height = 40; iv2.getLayoutParams().width = 46; parent.addView(iv) parent.addView(relativeP) parent.addView(iv2) } ``` This is the error I'm getting in logcat ``` 04-27 10:51:01.224 6973-6973/com.klystru.app.appE/AndroidRuntime: FATAL EXCEPTION: main Process: com.klystru.app.app, PID: 6973 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.klystru.app.app/com.klystru.app.app.MainActivity}: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2583) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2665) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1499) at android.os.Handler.dispatchMessage(Handler.java:111) at android.os.Looper.loop(Looper.java:207) at android.app.ActivityThread.main(ActivityThread.java:5765) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. at android.view.ViewGroup.addViewInner(ViewGroup.java:4453) at android.view.ViewGroup.addView(ViewGroup.java:4281) at android.view.ViewGroup.addView(ViewGroup.java:4222) at android.view.ViewGroup.addView(ViewGroup.java:4195) at com.klystru.app.app.MainActivity.createXmlElement(MainActivity.kt:284) at com.klystru.app.app.MainActivity.onCreate(MainActivity.kt:121) at android.app.Activity.performCreate(Activity.java:6309) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2530) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2665) at android.app.ActivityThread.-wrap11(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1499) at android.os.Handler.dispatchMessage(Handler.java:111) at android.os.Looper.loop(Looper.java:207) at android.app.ActivityThread.main(ActivityThread.java:5765) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:679) ``` I still research what it can be, I'm suspecting it may be wrong LayoutParams, but it's not really clear about how to set up correctly those resources programmatically. Thanks in advance. PD: If I found something I will update. Any help will be really welcome! UPDATE 1.0: Ok following the logcat I have to call `removeView` in child's parent, but I don't know exactly where. I am looking for that.