Search code examples
androidandroid-layoutandroid-tabhostandroid-tabactivity

How can I access views in activities within a TabActivity?


I've got a TabActivity containing other activities intended to split up a form. The TabActivity has in its layout a button intended to collect the data from all the form-related views across all the activities contained within the TabActivity and store it. The problem I'm running into is that the TabActivity doesn't appear to have access to these views; when I call findViewById() with one of them, I get a NullPointerException.

The documentation seems sparse about exactly how TabActivity works with respect to controlling the activities it contains. If it destroys an activity when switching from it to a different one, the situation I'm in would make sense. I'd like to know the best approach for accomplishing the goal described above.

src/com/vendor/MyTabActivity.java:

public class MyTabActivity extends TabActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_tab_activity);
        final Button saveButton = (Button) findViewById(R.id.save_button);
        saveButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // NullPointerException happens here
                String fieldValue = ((TextView) findViewById(R.id.text_field)).getText().toString();
            }
        });
    }
}

res/layout/my_tab_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost">
    <LinearLayout>
        <TabWidget android:id="@android:id/tabs"/>
        <FrameLayout android:id="@android:id/tabcontent" />
        <Button android:id="@+id/save_button"/>
    </LinearLayout>
</TabHost>

src/com/vendor/NestedActivity.java:

public class NestedActivity extends Activity {  
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nested_activity);
    }
}

res/layout/nested_activity.xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android">  
    <RelativeLayout>
        <EditText android:id="@+id/text_field"/>
    </RelativeLayout>
</ScrollView>

Solution

  • Your problem comes from these two lines in MyTabActivity...

    setContentView(R.layout.my_tab_activity);
    

    ...and...

    String fieldValue = ((TextView) findViewById(R.id.text_field)).getText().toString();
    

    ...although you obviously know the findViewById(R.id.text_field) is what's causing it.

    Using findViewById(...) only works when trying to access UI elements which have been inflated as part of your current Activity. As there isn't a TextView with the resource id of R.id.text_field in the my_tab_activity.xml, it's never going to work.

    Accessing activities which are tab content from the TabHost / TabActivity is tricky. My suggestion would be to use SharedPreferences which can be accessed from everywhere in your app. Once a TextView (or any other user-input item) is changed, save it to a SharedPreferences using a 'key' which identifies which activity/tab it came from. From then on, the TabActivity can collate the data easily.