Dynamically adding a child to LinearLayout with getting each child's position

38,135

Solution 1

your problem is resources.... you use the setText(int) method (that index is int...) which looks for resources and not string, this is not StringBuilder for which you can throw any type and get a string. you needs to replace

tv.setText(ll.indexOfChild(v));

with

tv.setText(Integer.toString(ll.indexOfChild(v)));

and if you want even little bit of efficiency:

public class TestActivity extends Activity {

    private String[] categories;

    private LinearLayout ll;
    private TextView tv;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        categories = getResources().getStringArray(R.array.categories);

        tv = (TextView) findViewById(R.id.text);
        ll = (LinearLayout) findViewById(R.id.hsvLinearLayout);

        for(int i = 0; i < categories.length; i++) {
            Button btn = new Button(this);
            btn.setText(categories[i]);
            btn.setOnClickListener(buttonClick);
            ll.addView(btn);
            int idx = ll.indexOfChild(btn);
            btn.setTag(Integer.toString(idx));
        }
    }

    OnClickListener buttonClick = new OnClickListener() {
        public void onClick(View v) {
            String idxStr = (String)v.getTag();
            tv.setText(idxStr);
        }
    };

}

Solution 2

You must setContentView before start findViewById

setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.text);
Share:
38,135
nenito
Author by

nenito

Updated on July 13, 2020

Comments

  • nenito
    nenito almost 4 years

    I have a problem with getting the child's position of LinearLayout. First I'm adding dynamically a number of buttons and then I'm trying to return each child's index and display it into a TextView. Here I'm sharing code:

    java source:

    private String[] categories;
    
    private LinearLayout ll;
    private TextView tv;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        categories = getResources().getStringArray(R.array.categories);
    
        tv = (TextView) findViewById(R.id.text);
        ll = (LinearLayout) findViewById(R.id.hsvLinearLayout);
    
        for(int i = 0; i < categories.length; i++) {
            Button btn = new Button(this);
            btn.setText(categories[i]);
            btn.setOnClickListener(buttonClick);
            ll.addView(btn);
        }
    }
    
    OnClickListener buttonClick = new OnClickListener() {
        public void onClick(View v) {
            tv.setText(ll.indexOfChild(v));
        }
    };
    

    xml structure:

    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    
    <HorizontalScrollView
        android:id="@+id/Footer"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        android:fadingEdge="none"
        >
    
        <LinearLayout
            android:id="@+id/hsvLinearLayout"
            android:orientation="horizontal"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            >
    
        </LinearLayout>
    
    </HorizontalScrollView>
    
    <TextView
        android:id="@+id/text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />
    

    resources:

    <string name="today">Today</string>
    <string name="life">Life</string>
    <string name="corner">Corner</string>
    <string name="banks">Banks</string>
    <string name="it">IT</string>
    <string name="fun">Fun</string>
    
    <array name="categories">
        <item>@string/today</item>
        <item>@string/life</item>
        <item>@string/corner</item>
        <item>@string/banks</item>
        <item>@string/it</item>
        <item>@string/fun</item>
    </array>
    

    The dynamically adding is fine, but the way I'm setting the OnClickListener produce some error. Any help will be useful! The purpose of that is if I want to add one or more button(s) to the HorizontalScrollView not to be necessary to edit many files, and just to go to sting.xml and create a new item into the categories-array!

    This is what LogCat produced:

    07-12 22:37:17.680: INFO/System.out(331): waiting for debugger to settle...
    07-12 22:37:17.900: INFO/System.out(331): debugger has settled (1441)
    07-12 22:37:20.870: INFO/ActivityManager(61): Displayed activity com.test/.TestDynam: 10203 ms (total 10203 ms)
    07-12 22:37:25.552: WARN/ResourceType(331): No package identifier when getting value for resource number 0x00000000
    07-12 22:37:26.871: DEBUG/dalvikvm(132): GC freed 190 objects / 8976 bytes in 901ms
    

    To clarify - the application starts without any errors, but when I click on a button it produces this line from the above log:

    07-12 22:37:25.552: WARN/ResourceType(331): No package identifier when getting value for resource number 0x00000000
    

    And this is from debugger:

    TestDynam [Android Application] 
        DalvikVM[localhost:8611]    
            Thread [<3> main] (Suspended (exception Resources$NotFoundException))   
                ViewRoot.handleMessage(Message) line: 1704  
                ViewRoot(Handler).dispatchMessage(Message) line: 99 
                Looper.loop() line: 123 
                ActivityThread.main(String[]) line: 4203    
                Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
                Method.invoke(Object, Object...) line: 521  
                ZygoteInit$MethodAndArgsCaller.run() line: 791  
                ZygoteInit.main(String[]) line: 549 
                NativeStart.main(String[]) line: not available [native method]  
            Thread [<13> Binder Thread #2] (Running)    
            Thread [<11> Binder Thread #1] (Running)
    
  • nenito
    nenito almost 13 years
    I don't think this is the problem and why do you think I should call setContentView() before findViewById() ?
  • Anh Tuan
    Anh Tuan almost 13 years
    setContentView will inflate layout resource and create a ViewGroup represent that layout resource. From that ViewGroup, you can use findViewById to get child view.
  • nenito
    nenito almost 13 years
    The dynamically setting of the OnClickListener causes unexpected error, but I'm still new and I can't figure it out!
  • codeScriber
    codeScriber almost 13 years
    first anh Tuan is write, trying to get view before setting content view will always bring you null. second if you would share your stacktrace it would make it easier to know what's the problem. Thrid take the findViewById out of the loop, you need it only once. Forth try to use ll instead of vg, most likly u get nullPointerException snce you never initalize vg.
  • codeScriber
    codeScriber almost 13 years
    oh and one more thing :-) LinearLayout basically (basically!) doesn't change position of views unless you force it to, meaning if you add them before other views so if the view was empty you can be sure that each index is i = 0; and i +1 for each new item you add, in addition if you use more then 8-10 items i think ListView would be better option memory wise since Views gets recycled....
  • nenito
    nenito almost 13 years
    this is the Log of LogCat and is there a way to use horizontal ListView?
  • codeScriber
    codeScriber almost 13 years
    i'm not sure, i think there was a thread about it... Gallery does just that but it's for images only...the logcat seems lacking, please on't post it as a commnet but as code sample in your original post, i don't see any Exceptions in what u just post...
  • nenito
    nenito almost 13 years
    actually, this is the Log after the changes I've made, regarding your previous comments.
  • nenito
    nenito almost 13 years
    I guess the way I'm adding a Button to the LinearLayout is problematic, but not sure. exception Resources$NotFoundException
  • nenito
    nenito almost 13 years
    ...or tv.setText(""+ll.indexOfChild(v)); anyway thanks a lot, such a small mistake!