10

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
  • 1,214
  • 6
  • 19
  • 33

2 Answers2

15

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);
        }
    };

}
codeScriber
  • 4,582
  • 7
  • 38
  • 62
2

You must setContentView before start findViewById

setContentView(R.layout.main);
tv = (TextView) findViewById(R.id.text);
Anh Tuan
  • 1,728
  • 1
  • 13
  • 25
  • I don't think this is the problem and why do you think I should call `setContentView()` before `findViewById()` ? – nenito Jul 12 '11 at 10:00
  • setContentView will inflate layout resource and create a ViewGroup represent that layout resource. From that ViewGroup, you can use findViewById to get child view. – Anh Tuan Jul 12 '11 at 10:05
  • The dynamically setting of the OnClickListener causes unexpected error, but I'm still new and I can't figure it out! – nenito Jul 12 '11 at 10:13
  • 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 Jul 12 '11 at 14:47
  • 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.... – codeScriber Jul 12 '11 at 15:00
  • this is the Log of LogCat and is there a way to use horizontal ListView? – nenito Jul 12 '11 at 19:31
  • 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... – codeScriber Jul 12 '11 at 21:07
  • actually, this is the Log after the changes I've made, regarding your previous comments. – nenito Jul 12 '11 at 21:55
  • I guess the way I'm adding a _Button_ to the _LinearLayout_ is problematic, but not sure. `exception Resources$NotFoundException` – nenito Jul 12 '11 at 22:56