简体   繁体   中英

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

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.

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.

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))) {


            }
        }
    }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM