0

In my main activity I want to add additional TextView items to the layout. I am using the following piece of code in my MainActivity-createOn (partly based on this post and this answer):

LayoutInflater inflater = (LayoutInflater)getLayoutInflater();
View view = inflater.inflate(R.layout.activity_main, null);
GridLayout item = (GridLayout ) view.findViewById(R.id.main_grid);

final int N = 10; // total number of textviews to add

final TextView[] myTextViews = new TextView[N]; // create an empty array;

for (int i = 0; i < N; i++) {
    // create a new textview
    final TextView rowTextView = new TextView(this);
    // set some properties of rowTextView or something
    rowTextView.setText("This is row #" + i);

    // add the textview to the linearlayout
    item.addView(rowTextView);

    // save a reference to the textview for later
    myTextViews[i] = rowTextView;
}
setContentView(view);

The layout for the main activity is as follows:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity" >

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"/>

    </android.support.design.widget.AppBarLayout>

    <GridLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/main_grid"

        android:useDefaultMargins="true"
        android:alignmentMode="alignBounds"
        android:columnOrderPreserved="false"

        android:columnCount="4"
        >

        <TextView
            android:text="MainTitle"
            android:textSize="32dip"
            android:layout_columnSpan="4"
            android:layout_gravity="center_horizontal"
            android:id="@+id/textView1"
            />


        <TextView
            android:text="Email address:"

            android:layout_gravity="right"
            />

        <EditText
            android:ems="10"
            />

        <TextView
            android:text="Password:"

            android:layout_column="0"
            android:layout_gravity="right"
            />

        <EditText
            android:ems="8"
            />

        <Space
            android:layout_row="4"
            android:layout_column="0"
            android:layout_columnSpan="3"
            android:layout_gravity="fill"
            />

        <Button
            android:text="Next"
            android:id="@+id/imageButton1"
            android:layout_row="5"
            android:layout_column="3"
            />
    </GridLayout>

</android.support.design.widget.CoordinatorLayout>

When running the code, however, no items are added to the main layout. I do not see any other items.

In the end, I want to dynamically add items in a grid layout (columns and rows), which might contain text and icons, and which are clickable (i.e. I can click on an element in this grid-view/layout/whatever, to start a specific action. Maybe this is important information...)

Community
  • 1
  • 1
Alex
  • 41,580
  • 88
  • 260
  • 469
  • why do you do `View view = inflater.inflate(R.layout.activity_main, null)` rather than `setContentView(R.layout.activity_main)`? Are you seeing anything from your layout on screen? – ataulm Nov 22 '15 at 14:28
  • I just took it from the example. The `setContentView(R.layout.activity_main)` is done earlier in the same method... – Alex Nov 22 '15 at 14:29
  • First, replace `getSystemService(Context.LAYOUT_INFLATER_SERVICE)` with `getLayoutInflater()`, so you get the right `LayoutInflater`, configured to take your styles and themes into account. Then, replace your `addView()` call with one that takes a `GridLayout.LayoutParams` as the second parameter, indicating where you want the view to go. Finally, if needed, use Hierarchy View or `uiautomatorviewer` to see where your `TextViews` are winding up. – CommonsWare Nov 22 '15 at 14:34
  • Not sure if I can follow you. Where to find a call that takes a `GridLayout.LayoutParams` as a second parameter? Do you suggest I check every possible method in every android class? I really cannot follow... – Alex Nov 22 '15 at 14:36
  • I kind of got it to work, but the added text is placed at the end of the screen, partly outside the visible edge. How can I decide where the text is being placed? – Alex Nov 22 '15 at 14:40
  • 1
    @Alex `addView(View)` has an overloaded option that takes LayoutParams. – ataulm Nov 22 '15 at 14:43
  • "How can I decide where the text is being placed?" -- by providing a `GridLayout.LayoutParams` instance as the second parameter to `addView()`, where the `GridLayout.LayoutParams` indicates the rules for which you want this child to be placed. – CommonsWare Nov 22 '15 at 15:08
  • And how to create such a param? I tried `GridLayout.LayoutParams params = new GridLayout.LayoutParams(height="50dp");` but this does not work. And there is also no example in the documentation. How can I find the solution on the docs? I cannot find any... – Alex Nov 22 '15 at 15:25
  • The following also does not work: `GridLayout.Spec spec = new GridLayout.Spec(1,1); GridLayout.LayoutParams params = new GridLayout.LayoutParams(spec);` – Alex Nov 22 '15 at 15:26

1 Answers1

0

In general, if you want to add items dynamically to a layout at runtime, you can do it as follows (I have substituted your GridLayout for a LinearLayout because I have never used a GridLayout before and am unaware if it requires special layout parameters).

res/layout/activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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"
    android:fitsSystemWindows="true"
    tools:context=".MainActivity" >

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"/>

    </android.support.design.widget.AppBarLayout>

    <LinearLayout
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:id="@+id/main_grid">

        ... existing views...

    </LinearLayout>

</android.support.design.widget.CoordinatorLayout>

onCreate:

setContentView(R.layout.activity_main);
// `ViewGroup container` is a field
container = (ViewGroup) findViewById(R.id.main_grid); 

anywhere after setContentView:

// `this` would be your activity/application context so it has correct theme info
LayoutInflater inflater = LayoutInflater.from(this); 
TextView[] myTextViews = new TextView[NUMBER_OF_TEXTVIEWS];

for (int i = 0; i < NUMBER_OF_TEXTVIEWS; i++) {
    TextView textView = createNewTextViewWithText("This is row #" + i);

    ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT
    );      

    container.addView(textView, params);

    myTextViews[i] = textView;
}

createNewTextViewWithText(String text):

private TextView createNewTextViewWithText(String text) {
    // I prefer inflating the TextView, as it's easier to
    // specify layout params in XML, IMO
    TextView textView = new TextView(this);
    textView.setText(text);
    return textView;
}

The layout params are important because it tells the ViewGroup how to add the child (the TextView).

ataulm
  • 15,195
  • 7
  • 50
  • 92
  • In general, I'd approach this by trying to it in XML first - that way, you know which layout params will be needed by GridLayout to achieve the effect you want. – ataulm Nov 22 '15 at 14:44
  • Thanks so far, but I have a questions: Where is `item` defined in your example code? – Alex Nov 22 '15 at 14:51
  • The code seems to work now (i.e. the app is not crashing anymore), but except "MainTitle" I do not see anything else... – Alex Nov 22 '15 at 14:55
  • my "item" is "container". It would be helpful to see what you want to accomplish (if you could add a sketch to your question). You mentioned it doesn't crash anymore but the crashing wasn't a symptom indicated in your question.. – ataulm Nov 22 '15 at 14:59
  • This might be a good approximation: http://www-10.lotus.com/ldd/pfwiki.nsf/DAC93629B2CD398C852578CD005797BA/$file/e2e_list_types.jpg I wana to create rows. Each row might contain a text, another text, an icon (to remove an item...) something like that (which I even want to click on to start some action..!!!) Maybe my approach is comppetly wrong, but I just starting to scratch the surface of android ... – Alex Nov 22 '15 at 15:03
  • ah ha, then this may not be the best approach. You'll be after ListView or RecyclerView with a LinearLayoutManagerGridView. I have a previous answer that shows implementation for each - http://stackoverflow.com/a/32028411/494879 – ataulm Nov 22 '15 at 15:09
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/95850/discussion-between-alex-and-ataulm). – Alex Nov 22 '15 at 15:09
  • I have no idea how to insert the ListView or RecyclerView in my code. Where to place it? How to call it? What about the layout.xml? I am very confused! I really do not know where to start here, what even to try... – Alex Nov 22 '15 at 15:13
  • I tried to change GridLayout -> ListLayout, but the latter does not seem to exist... – Alex Nov 22 '15 at 15:16
  • I also tried to specify `GridLayout.LayoutParams`, but I could not find a way to specify the height, for example. I do not see anything helpful in the documentation... – Alex Nov 22 '15 at 15:20
  • @Alex I think you'll find it easier if you review the ListView/RecyclerView documentation and attempt a few demo exercises before continuing on your app. There are literally 100s of examples for ListView on the web (and at least 10s on RecyclerView). – ataulm Nov 22 '15 at 15:40