Search code examples
androidxmlandroid-layoutkotlinandroid-gridlayout

How to add children to GridLayout through code (dynamically)?


Inside GridLayout I have 32 very similar FrameViews, the difference are ids (numbers)

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/myFrame1">
        <ImageView
            android:id="@+id/myImg1"
            android:layout_width="190dp"
            android:layout_height="105dp"
            android:layout_margin="4dp"
            android:src="@drawable/myImg"
            android:contentDescription="@string/station1" />
        <TextView
            android:id="@+id/descTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="4dp"
            android:layout_marginBottom="34dp"
            android:background="@android:color/transparent"
            android:text="@string/Station 1"
            android:textColor="@android:color/black"
            android:textSize="16sp"
            android:textStyle="bold"
            android:layout_marginStart="4dp" />
    </FrameLayout>

I might add more text views later and it's starting to get pretty messy so I need a general idea of how to insert this kind of layout dynamically, preferably in Kotlin language.


Solution

  • I have created a full project in which I am inserting frame dynamically.

    First You have to create layout frame_layout.xml. In this layout paste this:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/myFrame"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <ImageView
            android:id="@+id/myImg"
            android:layout_width="190dp"
            android:layout_height="105dp"
            android:layout_margin="4dp"
            android:contentDescription="station1"
            android:src="@drawable/ic_launcher_foreground" />
    
        <TextView
            android:id="@+id/descTextView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginStart="4dp"
            android:layout_marginLeft="4dp"
            android:layout_marginBottom="34dp"
            android:background="@android:color/transparent"
            android:text="Station 1"
            android:textColor="@android:color/black"
            android:textSize="16sp"
            android:textStyle="bold" />
    </FrameLayout>
    

    In activity layout:

    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView 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:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        >
    
        <androidx.gridlayout.widget.GridLayout
            android:id="@+id/gridRoot"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:columnCount="2"
            app:rowCount="32"
            >
    
        </androidx.gridlayout.widget.GridLayout>
    
    </ScrollView>
    

    And MainActivity.kt:

    import android.os.Bundle
    import android.widget.ScrollView
    import androidx.appcompat.app.AppCompatActivity
    import kotlinx.android.synthetic.main.activity_main.*
    import kotlinx.android.synthetic.main.frame_layout.view.*
    
    class MainActivity : AppCompatActivity()
    {
        override fun onCreate(savedInstanceState: Bundle?)
        {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            for (i in (1..32))// numbers of frames
            {
                val frame = ScrollView(this) // create frame
                layoutInflater.inflate(R.layout.frame_layout, frame) // add layout to frame
    
                frame.tag = i.toString() //add tag to enable finding specific frame at runtime
    
                frame.descTextView.text = "Section $i" // change textView on frame ( use string resources! not hardcoded string like me)
    
                gridRoot.addView(frame) // add frame to grid 
            }
    
        }
    }
    

    Result:

    Result

    If this works fine You can edit it and make it looks like You want.