Question

I'm trying to use a tabhost with 4 widgets, I've tested this on android 4.2 and it works like a charm, however on android 2.2 it gives me a nullpointerexception when I change tabs

I know there is a known problem with tabhosts and android 2.1/2.2 however I can't seem to get it to work with the other fixes people have suggested on other threads.

NOTE: I'm using Android Annotations

Here's the LogCat :

03-23 10:29:08.869: E/AndroidRuntime(423): FATAL EXCEPTION: main
03-23 10:29:08.869: E/AndroidRuntime(423): java.lang.NullPointerException
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.widget.TabWidget.focusCurrentTab(TabWidget.java:367)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.widget.TabHost.setCurrentTab(TabHost.java:320)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.widget.TabHost$2.onTabSelectionChanged(TabHost.java:129)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.widget.TabWidget$TabClickListener.onClick(TabWidget.java:453)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.view.View.performClick(View.java:2408)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.view.View$PerformClick.run(View.java:8816)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.os.Handler.handleCallback(Handler.java:587)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.os.Handler.dispatchMessage(Handler.java:92)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.os.Looper.loop(Looper.java:123)
03-23 10:29:08.869: E/AndroidRuntime(423):  at android.app.ActivityThread.main(ActivityThread.java:4627)
03-23 10:29:08.869: E/AndroidRuntime(423):  at java.lang.reflect.Method.invokeNative(Native Method)
03-23 10:29:08.869: E/AndroidRuntime(423):  at java.lang.reflect.Method.invoke(Method.java:521)
03-23 10:29:08.869: E/AndroidRuntime(423):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
03-23 10:29:08.869: E/AndroidRuntime(423):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
03-23 10:29:08.869: E/AndroidRuntime(423):  at dalvik.system.NativeStart.main(Native Method)

Here's my code :

@NoTitle
@EActivity(R.layout.activity_base)
public class BaseActivity extends TabActivity {

    Context mContext;

    @ViewById
    Button btnBaseDeconnecter;

    @ViewById
    TextView txtBaseInfos;

    @AfterViews
    void afterViews() {
        mContext = this;
        TabHost tabHost = getTabHost();

        /* tid1 is firstTabSpec Id. Its used to access outside. */
        TabSpec firstTabSpec = tabHost.newTabSpec("0");
        TabSpec secondTabSpec = tabHost.newTabSpec("1");
        TabSpec thirdTabSpec = tabHost.newTabSpec("2");
        TabSpec fourthTabSpec = tabHost.newTabSpec("3");


        /* TabSpec setIndicator() is used to set name for the tab. */
        /* TabSpec setContent() is used to set content for a particular tab. */
        firstTabSpec.setIndicator(
                prepareTabView(mContext, getResources().getDrawable(R.drawable.enlevement))).setContent(
                new Intent(this, EnlevementActivity_.class));
        secondTabSpec.setIndicator(
                prepareTabView(mContext, getResources().getDrawable(R.drawable.travaux))).setContent(
                new Intent(this, TravauxListActivity_.class));
        thirdTabSpec.setIndicator(
                prepareTabView(mContext, getResources().getDrawable(R.drawable.compte))).setContent(
                new Intent(this, CompteActivity_.class));
        fourthTabSpec.setIndicator(
                prepareTabView(mContext, getResources().getDrawable(R.drawable.contact))).setContent(
                new Intent(this, ContactActivity_.class));
        tabHost.setup();
        /* Add tabSpec to the TabHost to display. */
        tabHost.addTab(firstTabSpec);
        tabHost.addTab(secondTabSpec);
        tabHost.addTab(thirdTabSpec);
        tabHost.addTab(fourthTabSpec);
        tabHost.getTabWidget().setStripEnabled(false);
        tabHost.getTabWidget().setDividerDrawable(R.drawable.empty_divider);


    }
    public static View prepareTabView(Context context, Drawable background) {
        View view = LayoutInflater.from(context).inflate(R.layout.fake_native_tab, null);
        ImageView img = (ImageView)view.findViewById(R.id.fakeNativeTabImageView);
        img.setImageDrawable(background);
        return view;
    }




}
Était-ce utile?

La solution

Use tabHost.getTabWidget().setDividerDrawable(null); instead of R.drawable.empty_divider.

Reasoning:

Looking at the stacktrace and the Android 2.2 source for TabWidget.java, there seems to be an issue in the getChildTabViewAt(int index) method where if the dividerDrawable is not null, it skips over the divider views in the tab bar to get the actual tabview.

public View getChildTabViewAt(int index) {
    // If we are using dividers, then instead of tab views at 0, 1, 2, ...
    // we have tab views at 0, 2, 4, ...
    if (mDividerDrawable != null) {
        index *= 2;
    }
    return getChildAt(index);
}

I think what happens when you use R.drawable.empty_divider for the dividerDrawable the divider views don't get drawn, so they should be treated as if they were null. As you can see, that doesn't happen, so that would explain the NullPointerException and the strange behaviour where you click one tab and it selects another.

Autres conseils

Use backword compatible library means add android.support.v4.jar in libs folder and try to use the same class from this library which will compatible with both lower and higher version

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top