Sheehan Alam
Sheehan Alam

Reputation: 60869

Why aren't my Android Tab's Working Properly?

I have a TabActivity that has a TabHost with two tabs. Each tab has its own intent. It seems like the intent's onResume() fires before I can detect if a tab was changed. How can I resolve this?

TabActivity code:

public class TabHostActivity extends TabActivity {
    static final int SHOW_SHARE_ACTIVITY = 0;
    static final int SHOW_LOGIN_ACTIVITY = 1;

    private TabHost tabHost;
    private ImageButton composeImageButton;
    private SharedPreferences prefs;
    private Bundle b;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.tabhostactivity);       
        prefs = getSharedPreferences(Constants.PREFS_NAME, 0);
        //Setup the ActionBar
        composeImageButton = (ImageButton) findViewById(R.id.composeImageButton);
        composeImageButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if(prefs.getBoolean("isLoggedIn", false))
                {
                    showShareActivity();
                }
                else
                {
                    Intent intent = new Intent(TabHostActivity.this, LoginActivity.class);
                    startActivityForResult(intent, SHOW_LOGIN_ACTIVITY);
                }
            }
        });

        b = new Bundle();
        //Setup the Tabs
        Resources res = getResources(); // Resource object to get Drawables
        tabHost = getTabHost();  // The activity TabHost
        tabHost.setOnTabChangedListener(new OnTabChangeListener() {
               @Override
              public void onTabChanged(String arg0) {
                   if(tabHost.getCurrentTab() == 0) //Check if the Watchlist tab was clicked so we can prompt login
                   {
                        //Toast toast = Toast.makeText(getApplicationContext(), "TRENDING = YES", Toast.LENGTH_SHORT);
                        //toast.show();
                        b.putBoolean("isTrendingTab",true);
                   }
                   else
                   {
                       Toast toast = Toast.makeText(getApplicationContext(), "TRENDING = NO", Toast.LENGTH_SHORT);
                       toast.show();
                       b.putBoolean("isTrendingTab",false);
                   }
              }     
        });  

        TabHost.TabSpec spec;  // Resusable TabSpec for each tab
        Intent intent;  // Reusable Intent for each tab

        // Create an Intent to launch an Activity for the tab (to be reused)
        intent = new Intent().setClass(this, ARActivity.class);
        intent.putExtras(b);

        // Initialize a TabSpec for each tab and add it to the TabHost
        spec = tabHost.newTabSpec("trending").setIndicator("Trending",res.getDrawable(R.drawable.icon)).setContent(intent);
        tabHost.addTab(spec);

        // Do the same for the other tabs
        intent = new Intent().setClass(this, WatchlistActivity.class);
        intent.putExtras(b);
        spec = tabHost.newTabSpec("watchlist").setIndicator("Watchlist",res.getDrawable(R.drawable.icon)).setContent(intent);
        tabHost.addTab(spec);

        tabHost.setCurrentTab(0);
    }

    private void showShareActivity()
    {
        Intent intent = new Intent(TabHostActivity.this, ShareActivity.class);
        startActivityForResult(intent, SHOW_SHARE_ACTIVITY);
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == SHOW_LOGIN_ACTIVITY)
        {
            //Login was successful so lets show the compose box!
            if (resultCode == RESULT_OK) {
                showShareActivity();
            }
        }
    }
}

Here is the onResume in the Intent for one of my Activities:

public void onResume()
    {
        super.onResume();

        Bundle bundle = getIntent().getExtras();

        if(bundle.getBoolean("isTrendingTab"))
        {
            Toast toast = Toast.makeText(getApplicationContext(), "TRENDING!", Toast.LENGTH_SHORT);
            toast.show();
        }
        else
        {
            Toast toast = Toast.makeText(getApplicationContext(), "WATCHLIST!", Toast.LENGTH_SHORT);
            toast.show();
        }
    }

Upvotes: 1

Views: 841

Answers (4)

Martin Stone
Martin Stone

Reputation: 13007

There's no need to use onTabChanged().

Here's how I do it in my app (with some of your values pasted in). I add the boolean flag to the intent, not an extra bundle:

Intent intent = new Intent(action) // see notes below about "action"
    .setClass(this, ARActivity.class)
    .putExtra("isTrendingTab", true); 
TabHost.TabSpec spec = tabHost.newTabSpec("trending")
    .setIndicator("trending", getResources().getDrawable(drawableId))
    .setContent(intent);
tabHost.addTab(spec);

Then in onResume():

if (getIntent().getBooleanExtra("isTrendingTab", false)) {...

I found that when using the same class for multiple tabs, I had to differentiate them with a different action string in each Intent constructor, as above. Otherwise it wouldn't create a new activity when switching between tabs of the same class. You don't appear to be doing this (yet), so you can continue to leave it out. I thought I'd mention it, since passing isTrendingTab suggests you might be heading down this route.

Upvotes: 0

Hades
Hades

Reputation: 3936

The oncreate of your class ARActivity.class will be called before your onresume method of your tab host.

So do whatever the processing you want in your ARActivity.

Also since your tabHost.setCurrentTab(0); your starting tab will always be ARActivity.

And if you want to activate code depending your tab change, figure out which tab you are on using using the main tabhost ontabchange and use the id and then send a request to a inner broadcast receiver.

if (tabHost.getCurrentTab() == 0) {
                    i.setAction(getString(R.string.br_refresh_home_tab));
                    sendBroadcast(i);
                } else {
                    i.setAction(getString(R.string.br_refresh_sports_tab));
                    sendBroadcast(i);
                }

In your ARActivity,

protected class RefreshList extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(
                    getString(R.string.br_refresh_home_tab))) {


            }
        }
    }

Upvotes: 0

neteinstein
neteinstein

Reputation: 17613

If i understood correctly the problem is that you try to put

b.putBoolean("isTrendingTab",true); 

(or false) on the intent you're going to launch by detecting change.

That's the wrong approach.

The change event will always occur after the activity is launched, you should do the logic different. You have to rethink it.

Upvotes: 1

Anthony Graglia
Anthony Graglia

Reputation: 5435

Have you looked at Activity life cycle? The resume is being called when the activity is being created too and the line bundle.getBoolean("isTrendingTab") does not have a default value in case it has not been set yet...

Can you set it first in the onCreate to a default value? I think that is your issue. The code is a little sloppy. You are trying to pass variables to each activity but they still both exists in the tab activity. Views would be a better method so they all see the same variables in the tab activity.

Upvotes: 0

Related Questions