To put it simply. From a context menu on a TabActivity how can I initiate executing the intent for the current tab? I am trying to force a refresh.
The tabs all initiate activities displaying a subset of people names. While in one list you call up an edit activity which allows you to associate the name to one of the other lists in the TabHost. Using the back button to get back to the tabhost (onResume fires) and the list has not updated. I would like to have a context menu item to refresh the current tab.
I know about using one activity for all the views in a tabhost but for many reasons I have not chosen that method.
You can also try adding a flag to the intent when you set up the tabs in the first place.
Intent i = new Intent().setClass(this, YourClass.class)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
TabHost.TabSpec spec = tabHost.newTabSpec("name")
.setIndicator("Class",res.getDrawable(R.drawable.ic_tab_something))
.setContent(intent);
Tabhost tabHost.addTab(spec);
I think due to the activity lifecycle, you will have some problems 'restarting' the activity (Activity lifecycle - startActivity()) - if you were to move any logic you have inside the onCreate method into another method, then call the method from onCreate and onResume, so it rebuilds the tab content for you.
Alternatively you could add a menu item to call this method, so onCreate calls the logic method on first run, and your user can call it from the menu to refresh the contents.
Related
I have a Tabbed Activity, which contains three tabs, which are initialized as follows:
TabHost tabHost = getTabHost();
TabSpec porabaspec = tabHost.newTabSpec("Tab1");
porabaspec.setIndicator("Tab 1", getResources().getDrawable(R.drawable.icon_tab1));
porabaIntent = new Intent(this, PorabaActivity.class);
porabaspec.setContent(porabaIntent);
...
tabHost.addTab(porabaspec);
...
This Tabbed activity has a button event that calls an Async Task which executes a second activity that returns some data back to the Tabbed Activity. At this point I would like to update the Tab 1 Activity (porabaIntent) with this new data that I received.
How do I do this? If I pass the bundled data when I initialize the tabs, the data won't update when it's changed, however if I try and send it in the onPostExecute() method of the Async Task I cannot seem to bind it to porabaIntent.
I found that the solution to this problem is to use static variables in the main tabbed activity, which can be accessed and modified by its child tabbed activites.
I have an app that can create tabs dynamically. And when I create a tab I initiate an activity as an intent. Like so:
private void addTab(Context packageContext, Class<?> newClass, TabHost mTabHost, String tabId, String tabLabel){
// newClass is my Activity class that I want to start in the tab
Intent intent = new Intent().setClass(packageContext, newClass);
TabHost.TabSpec spec;
spec = mTabHost.newTabSpec(tabId).setIndicator(tabLabel)
.setContent(intent);
mTabHost.addTab(spec);
mTabHost.setCurrentTabByTag(tabId);
}
Pretty standard. And it works great. Now, suppose that I have a button (or menuitem, whatever) in the activity that I instantiated inside of my tab. When the user presses this button, I want the activity, and the tab it is inside of, to be removed and destroyed.
I can't seem to find a simple way to do this. I have found the TabHost.clearAllTabs() function, but this destroys all tabs and activities, I just want to remove one.
Someone suggested I save a list of all Tabs that I have opened, and then call clearAllTabs(), after which I recreate all of my other tabs except for the one I don't want.
Something like this:
public static ArrayList<TabHost.TabSpec> list = new ArrayList<TabHost.TabSpec>();
I add this line to my addTab() function so that every tab I create is remember in my ArrayList:
list.add(spec);
And then when I want to remove my tab I run this function:
public static void removeTab(){
list.remove(list.size()-1); // remove it from memory
mTabHost.clearAllTabs(); // clear all tabs from the tabhost
for(TabHost.TabSpec spec : list) // add all that you remember back
mTabHost.addTab(spec);
}
This removes my tab from my ArrayList, removes all tabs, then recreates all the tabs remaining using my ArrayList. In theory it should work, but I get the following error when I try call this function:
FATAL EXCEPTION: main
java.lang.NullPointerException
at android.widget.TabWidget.setCurrentTab(TabWidget.java:342)
at android.widget.TabWidget.focusCurrentTab(TabWidget.java:366)
at android.widget.TabHost.setCurrentTab(TabHost.java:323)
at android.widget.TabHost.addTab(TabHost.java:216)
at com.example.myapp.TabManager.removeTab(QuikBrowser.java:86)
at com.example.myapp.TabManager.TabWindow.onOptionsItemSelected(TabWindow.java:91)
at android.app.Activity.onMenuItemSelected(Activity.java:2205)
For some reason, when adding a tab, it attempts to set the current tab, and it hits a null pointer exception.
If you guys could suggest another way of achieving what I want to do, or a way to fix my current method, I would appreciate it.
Try changing current tab to 0.
Something like:
getTabHost().setCurrentTab(0);
getTabHost().clearAllTabs();
I was reading that calling clearAllTabs(); will throw a nullpointerexception if you don't set the tabhost to the first tab (.setCurrentTab(0)) before calling (.clearAllTabs())
Also this answer may help? (How to remove tab from TabHost)
I would suggest a different approach. You can use an ActivityGroup to build your own TabControl. As you are using normal Buttons (or similar controls just as you like) you can easyly arrange/create/remove them as needed.
I can't dump the whole code here but that is basically what I did when I had the same problem:
Create an Activity inherited from ActivityGroup
Place a ViewGroup in your layout where you want to show the sub-activities
Setup your buttons as needed (LinearLayout works fine with a variable count of buttons)
Start activites thru getLocalActivityManager().startActivity() as needed
You can now add/remove buttons as you like. The Activites follow the Android lifecycle so you don't have to delete them yourself.
You might have to implement onBackPressed on your ActivityGroup to properly handle the history but that depends on the project.
I'm trying to notify my activity when the relevant tab is selected.
Consider the follwoing situation:
MainActivity:
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, HomeActivity.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec("home").setIndicator("Home",
res.getDrawable(R.drawable.ic_tab_home))
.setContent(intent);
tabHost.addTab(spec);
// Do the same for the other tabs
intent = new Intent().setClass(this, ProceduresActivity.class);
spec = tabHost.newTabSpec("procedures").setIndicator("Procedures",
res.getDrawable(R.drawable.ic_tab_checklist))
.setContent(intent);
tabHost.addTab(spec);
Now, the first time my second tab is selected, the onCreate method of ProceduresActivity is called.
What I want to be alble to do is, within ProceduresActivity, to be notified whenever tab 1 and tab 2 (mine) are selected.
I tryed overriding onPause and onResume within ProceduresActivity however those are only called when the MainActivity is pasued / resumed and not when I switch tabs...
So in other words I want ProceduresActivity to do something whenever the user selects second tab, and not only the first time.
Can someone help me please?
Thanks, Luca.
Hmmm. This seems like it might be a little difficult (I'm not even sure it's possible) to achieve. There are two ways I can see that you could achieve the same results.
The first way is by have the first tab refresh it's data/information when the user goes back to it. This can be done in the onResume() and by adding a flag to it. Pretty simple.
If you need your activity to do something that will take some time, you can make an ActivityGroup. It's basically a controller for multiple activities. It starts them all at the same time and just chooses which one is shown at once. This means that (in your case) both activities would be running, but only one would be shown. When you want the first tab to do something while the user is using the second tab, you go to the ActivityGroup (which is like a controller) and tell it to do whatever you want with the first tab.
The only problem I see with the ActivityGroup route is binding it to your tabs, but there are many workarounds for this.
Maybe this can help you, i use this to perform an action when the tabs change. But maybe you can alter it to do a specific action with every tab?
getTabHost().setOnTabChangedListener(new OnTabChangeListener() {
public void onTabChanged(String tabId) {
//TODO, action to be performed
}
}
});
am not too experienced in android and i am just using the TabActivity, so please bear with me. i keep seeing post about not using activites in Tabhost but views. and am not sure which is which and if thats the reason of my latest headache? i have a code with 4 tabs like this:
// Category TabActivity class
tab.setContent(new Intent(this, Mylist.class));
tab1.setContent(new Intent(this, Mylist.class));
tab2.setContent(new Intent(this, Mylist.class));
and each tab is showing the result of a method in the Mylist Activity.
is that using an activity in a tab or displaying a view? whats the difference?.
i have a context menu on an item selected in the Mylist Activity which updates the list. how can i reflect the changes in the list back to the tab in other to display that particular method in the Mylist class, that was set as the tabs content. obviously this will change if i updated or deleted an item from the list when the tab is shown. i think its possible with onResume(), but don't know what to call there or is there any better way?
in the Mylist class, i have tried this little piece of code to restart the TabActivity:
myAdapter.deleteItem(id);
fillData(); //
Intent refereshCategory = new Intent(this, Category.class);
startActivity(refereshCategory);
its restarting the activity after the item have been deleted, but how can i only show the tab whose view was in focus when it restarts and i don't want fillData() method to be shown as it does not have to do with the tabs. i hope i made myself clear enough. Thanks
Any help will be greatly appreciated. Thanks for your time.
With tab.setContent(new Intent(this, Mylist.class)); You are telling the application to display a new MyList Activity in that tab.
I'm not sure of the activity lifecycle for tabbed activities but I think it is safe to assume they follow the same standards as regular activities. onResume is called every time the activity shown (which would include being switched from another tab's activity to this activity). So any kind of updating you want to do to the list every time it is shown should go here and not in onCreate(Bundle savedInstanceState)
To create any kind of Android application you should become familiar with the Component Lifecycle
I have an Android application which has four tabs (I use a main TabActivity with TabHost and TabSpecs).
In one of my sub activity (activity opened in a tab), i need to open a tab not by clicking on the tab title and i don't know how to do this.
For example, i have a button in my activity and when i click on it, it opens a different tab.
For the moment, it is what i do:
Intent intent = new Intent(myActivity.this, myTabActivity.class);
intent.putExtra("ComeFrom", true);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Then in the TabActivity, if i get true reading the "ComeFrom" extra i open the wished tab but the problem is that it kills all the other activies. So, if someone knows a better (cleaner) way to do that trick, please tell me...
Found an easier (I think) answer:
on the TabActivity declare a public, static and self variable and populate it on the onCreate method. F.e.:
public class TheActivity extends TabActivity {
public static TheActivity self;
...
#Override
public void onCreate(Bundle savedInstanceState) {
self=this;
on any Activity running in a tab, when you want to change the one shown on your app. you can do this:
TabHost tabHost = TheActivity.self.getTabHost();
tabHost.setCurrentTab(0);
Worked ok for me, hope serves someone else!
You have to use TabHost's "setCurrentTab(...)" for that. In one of my projects, I created a static method in the main Activity (the one with the TabHost), named "swtichToTab(int tab)". In my subactivites (those inside the tabs) could then just call "MainActivity.switchToTab()" to trigger switching.
It may not be the cleanest method, I'm sure you can achieve this using broadcast intents too.
You can create a BroadcastReceiver and send a broadcast with the index of the tab as extra
You can use views instead of activities for the content of the tabs. This way, the code is simpler and doesn't use as much memory. Plus, you then can use the setCurrentTab(tabIndex) method to easily switch between views.
I have a simple tutorial here. It has a tab activity with a list and map view. When you you click on an item in the list, the activity dynamically goes to the map view (using the setCurrentTab(tabIndex) method). You can easily modify this to have a button switch views.