How to communicate between Android tabs - android

Im trying to setup some tabs for my android application, but i got stuck.
I cant find a way to communicate between the tabs..
I got 2 tabs.
|Search|Result|
The search tab is simply showing a TextEdit and a "Search" button.
Hitting the search button should make my app change to the result tab and display the result.
i have added the tabs as activities using new intents as
TabHost host=getTabHost();
host.addTab(host.newTabSpec("one")
.setIndicator("Search")
.setContent(new Intent(this, SearchTabActivity.class)));
host.addTab(host.newTabSpec("Result")
.setIndicator("Android")
.setContent(new Intent(this, ResultTabActivity.class)));
Now i cant find a way for SearchTabActivity to display ResultTabActivity and alter its view...
Im looking forward for any tip.

You definitely want to reconsider using Activities as the content of your tabs. The more standard approach is to use one Activity that uses Tabs to only show part of the layout when a particular tab is selected.
The Android documentation has an excellent worked example, check out Hello, TabWidget.
Alternative
If for some reason you do need to use Activities, you can pass information between them by either adding values to the extras bundle within the Intent your using to open each Activity, or by extending the Application class.
By extending the Application class (and implementing it as a Singleton) you get an object that will exist whenever any of your application components exist, providing a centralized place to store and transfer complex object data between application components.

Related

Advantages of using Tabs over Intent

I just found out that we can use overridePendingTransition(0,0) to make a very simple transition between Layouts that override the current Android transition.
switch(v.getId()){
case R.id.btnCorner:
Intent i = new Intent(MainActivity.this, Settings.class);
startActivity(i);
overridePendingTransition(0,0);
break;
}
What is the advantage of using tabs over such a simple procedure?
My opinion is that tabs facilitate the transmission of variables between one "window screen" to another. Rather than passing the variable through intents.
Please note that I am not familiar with using Tabs and I hope someone can clarify the idea of using Tabs in an application.
Jonathan Hugh, nice questions really helpful for users , here i am going to give you brief description for both like : Intent take an example of any master-detail form where we want by using click on any ListView item row need to call another activity in this case i recommend you to use Intent because in same flow you require your result to be done, and other side, using tab it will give you more convenience to put your wishlist features in app using separate-separate tabs for all....
Tabs Like:-
private void setTabs()
{
addTab("Tab1", R.drawable.tab1, tab1.class);
addTab("Tab2", R.drawable.tab2, tab2.class);
addTab("Tab3", R.drawable.tab3, tab3.class);
addTab("Tab4", R.drawable.tab4, tab4.class);
}
What do you meen under tabs? There are several ways in Android to implement Tabs pattern. Some of them are better, other are not very good or deprecated. Not all of them are :
facilitate the transmission of variables
For example, using 3 different Activity, will significatelly increase amount of code, increase code connectivity and decrease code quality.
According to my point of view, in tabs, you can organize your work more systemically as compare to Intent.

Pass fragments between activities

I want to make an application that can support portrait and landscape. The layout has two panes, on the left is the options and the right shows the result. When an option is selected the right pane shows it. But for portrait there is not enough room, so a separate activity is needed. Each option produces a different type of fragment, so I don't want to make an activity for each option when all that changes between activities is what fragment is being added there. I want to pass a fragment from the main activity to the new one, how would I do this?
EDIT: Moved what asker actually wants to top.
If you want to pass data to an Activity when creating it, call a version of Intent.putExtra() on the intent that is used in startActivity(). You can then use getIntent().getStringExtra() to (for example) get a string extra in the activity.
Say you have a piece of string data in your first activity called myString.
Intent intent = new Intent(this, SecondActivity.class);
intent.putExtra(EXTRA_NAME_CONSTANT, myString);
startActivity(intent);
Now in your new activity in onCreate you would do:
String myString = this.getIntent()
.getStringExtra(EXTRA_NAME_CONSTANT, "default return value here");
A few notes:
For that EXTRA_NAME_CONSTANT, I do mean to make a string constant of the form "your.package.name.SomeString" for example "com.example.MyString". Personally I'd even use a resource (accessed in the form getString(R.string.extra_my_string)) for the extra's name. They recommend you prefix it with your package name.
You can put and get many types of data from strings to arrays to even serializable data.
Instead of making a separete activity for different layout orientations consider using resource qualifiers to provide alternative layouts.
To summarize, make two layouts in a structure like so:
/res/layout/yourlayout.xml
/res/layout-land/yourlayout.xml
Where both XML files are named the same. Then make your default portrait layout in one and a landscape version in the other.
When you inflate the layout in onCreate (and when it does so automatically on a layout change during runtime) it will select the correct layout for you.
I want to pass a fragment from the main activity to the new one, how would I do this?
You wouldn't. At most, you would follow #Ribose's answer -- pass a flag into the activity via an extra to indicate what set of fragments to create.

Removing a tab and the activity (intent) inside of it from a TabHost

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.

How to pass the data through tabs?

I have three tabs.. Personal info,profile info and FinalStep...
First of all i need to move to another tab using a button in one tab activity..
how to do it?
Secondly how to save data in these tabs... as i have a FinalStep tab which contains the final registration button...so i need to obtain data from the other tabs also(personal and profile)
How to do it?
I always save data as a public variable in the TabHost activity. You can access it via getParent().
You simple TabActivity-TabView combination for implementing this. While doing you will get a structure with 4 classes:
1) TabHostActivity: this will host your tabview.
2) Tab1Activity: this will be the view of first tab.
3) Tab2Activity and 4) Tab3Activity similarly will hold the view of tab2 and tab3.
Now for going to one activity to other use can use the TabHost variable used in TabHostActivity and set its currentTab function.
HelloTabWidget.tabHost.setCurrentTab(2);
And yes for saving the data, you can use public variables in TabHostActivity and use it as per your requirements.
For more details on how to use tabview, go to this link:
http://developer.android.com/resources/tutorials/views/hello-tabwidget.html
PS: this is a general idea of doing and yes, you can optimize it more as per your needs and requirements and this may not be the best method of doing this.

How to use intent between tabs in java/Android?

I would need to know how to handle the intent between tabs. For example, I have a tab activity with two tabs. First on content is a text view. another one is a map view. When i click that text view it redirects to the tab2. it can be easily achieved by setCurrentTab(1) or setCurrentTabByTag("tab2") methods. But i want to pass lat and long values to that Map Activity to drop pin. What is the better way to use intents or getter/setter in java? What do you prefer? if your answer is "Intents". How?
A interesting problem. I understand it that you want to change to the second tab on a click in the first tabview but also pass special data to the second tab that is dependent on the action in the first tab.
I would generally start your views inside the tabs with an activity. However this is done at the moment the tab host is configured. That means both intents the one for the activity that lets the user choose lat long and the one that shows lat long are openend at the same time.
Therefore you can't add the information to the intent used to intialize the tab host.
I don't like the solution but the only thing that comes to my mind (using different activities for the tabs) is using a custom application that stores a reference to an object containing the data that you need to update the view in the second tab. You have to extend application with an own class and add this class in you manifest, now you can call getApplication in the first tab cast it to your application class set lat and long just before you call setCurrentTab. In the second tab you can call getApplication() again and you will then get the application object that is the same for every activity at every moment of your app running. You then have cast it again to your application object and retrieve lat and long value. See this page in the google refs on how to use a custom application class.
To use a custom application class add the following to your application tag in your manifest:
<application
...
android:name=".somepackage.CustomAppClass"
This will tell Android to instantiate the CustomAppClass as your Application class at the moment your app starts. You need to extend Application to avoid errors on start up.
Another solution but not the one I would prefer is to initialize the views yourself and initialize the tabhost with views and not activities. With a map view in one of the tabs this could be very memory heavy.
If you want to pass values between activities, I suggest looking at
http://developer.android.com/reference/android/content/SharedPreferences.html
the best way to get values from one itent to another.
With sharedPrefrences, there is only one instance of the class for the whole application, which means that you can store values in the files, switch intents or activities, and then recall those sharedPrefrence files that have the data in them.
The only downside is that you have to pass primitive types (int, string, boolean) but I'm sure you'll figure ways around this :).
I dont see the Problem here:
Maybe its a little bit of hackish but following Code works for me:
public boolean onClick(View v) {
//get your data you wanna send.
//If it is an Object it would be good if it is Parcelable
Object o = getYourData();
// or Parcelable p = getYourData
Activity activity = getParent();
//I'm assuming were inside an Activity which is started by TabActivity
if (activity instanceof TabActivity){
TabActivity ta = (TabActivity)activity;
//now determine the Tab you wanna start
ta.getTabHost().setCurrentTabByTag("yourTag");
//or ta.getTabHost().setCurrentTab(yourID);
Activity current = ta.getCurrentActivity();
//check if the Activity is the one you wanna start
if (current instanceof YOUR_ACTIVITY_YOU_WANNA_START){
//Cast to your Activity
YOUR_ACTIVITY_YOU_WANNA_START yourActivity =
(YOUR_ACTIVITY_YOU_WANNA_START)current;
// you only need to put Data inside your Intent
Intent intent = new Intent();
intent.putExtra("EXTRA_DATA_TAG", o);
//your Activity must Override onNewIntent and make it public,
//or simply add another method
//with whatever You like as parameter
yourActivity.onNewIntent(intent);
return true;
}
}
return false;
}
this way you don't have to mess with Application, SharedPrefs or other unnessesary stuff mentioned here
If you make the intent you are using to start the second tab activity a global intent.
You can then add extra's to this intent in the onPause() of the first tab. Note: you have to define all your tabs in separate activitys than your tabhost TabActivity as this activity's onPause() is never called.
This also help's with the answer above, if you are using a global variable saved in your activity that extends application, you can set this in the onPause() as it is fired before the activity is switched, which you might find an issue if setting this elsewhere

Categories

Resources