Tabs and TabContentFactory

Put problem concerning Views, Layouts and other XML-Resources (like AndroidManifest) here.

Tabs and TabContentFactory

Postby rdomloge » Sat Jan 24, 2009 2:26 pm

I'm playing about with Tabs and trying to find a decent way to use them. This is the code I have so far:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1. public class TestActivity extends TabActivity implements TabHost.TabContentFactory
  2. {
  3.        
  4.     public void onCreate(Bundle savedInstanceState)
  5.     {
  6.         super.onCreate(savedInstanceState);
  7.        
  8.         TabHost tabHost = getTabHost();
  9.         tabHost.addTab(tabHost.newTabSpec("tab1")
  10.                 .setIndicator("Bingo", getResources().getDrawable(android.R.drawable.star_big_on))
  11.                 .setContent(this));
  12.         tabHost.addTab(tabHost.newTabSpec("tab2")
  13.                 .setIndicator("Bongo", getResources().getDrawable(android.R.drawable.star_big_on))
  14.                 .setContent(this));
  15.     }
  16.    
  17.     public View createTabContent(String tag)
  18.     {
  19.         if(tag.equals("tab1"))
  20.                 return View.inflate(this, R.layout.tab1, null);
  21.         else if(tag.equals("tab2"))
  22.                 return View.inflate(this, R.layout.tab2, null);
  23.         else
  24.                 return null;
  25.     }
  26. }
Parsed in 0.034 seconds, using GeSHi 1.0.8.4


My question is, what exactly is the point of this approach? From the createTabContent() method, you return a View, but how exactly do then get into it and register action listeners and so forth? How do you setup and manage the view and plumb in the functionality?

My preference so far has been to use Intents which start a new activity in each tab. This works well in many ways, since each activity is a discrete component which is responsible for setting itself up and managing state etc. The issue I am having then is that the activities are too discrete - when they need to communicate between each other there are some real complications. These, I have more or less managed to cope with using Handlers. My latest issue with this approach is that the root class that extends TabActivity must reinitialise each tab when you rotate the screen. This causes the dialog management mechanism to fail. If a tab is showing a dialog and you rotate the screen, the dialog is not reinstated in the new tab that replaces it after rotation.

So I have been looking into alternative ways to set up tabs, which brings me to the code above....

Anyone got any links? Any example code? I have been searching for a few days now and cannot find any authoritative tutorial or resource which takes you through the different mechanisms for using Tabs and it's starting to look like I will have to do like others have and roll my own which seems.... drastic...
rdomloge
Junior Developer
Junior Developer
 
Posts: 24
Joined: Sat Jan 24, 2009 2:11 pm

Top

Postby rdomloge » Sun Jan 25, 2009 12:58 pm

To clarify, I guess the essence of my question is, "What is a common/decent strategy for attaching business logic to the view objects that are inflated from the XML?"

Using the strategy described in the code, there is a very neat and encapsulated way to create the 'view' but I now need to combine the view with the 'controller' a la Model View Controller (MVC).

My first thought is either I can put all of the code in the TabActivity class, but that's really only a short term, small app solution.

Assuming that each tab will have a fairly complex view, it would be preferable to delegate each view's controller code to another object. (The Intent/Activity-per-tab approach makes this simple). So I could create some delegate objects that would be presented with their view and would plumb in the functionality as required. But then if you take this approach, how would you cope without managed dialogs, lifecycle events etc?

I'm starting to feel that I should go back to using Intents/Activities-per-tab and find some way to deal with the horrible fact that, when you rotate the screen and the TabActivity needs to recreate the tabs, it will destroy any dialogs - in effect, managed dialogs do not work with TabActivity.
rdomloge
Junior Developer
Junior Developer
 
Posts: 24
Joined: Sat Jan 24, 2009 2:11 pm

Postby darolla » Sun Jan 25, 2009 11:57 pm

hi,

maybe I can help you. first of all you define the view inside the main.xml

although not often found on the internet you can fill the subviews there.

I have an example for that here:

http://www.anddev.org/making_own_theme-t4052-s15.html (starting with my post "I just build a basis for us...").

The other way is a class MyTabActivity extends TabActivity, load the XML, and sets up the different subview as own activities.

Let me search for code on this...

Greetings,
DaRolla
User avatar
darolla
Master Developer
Master Developer
 
Posts: 273
Joined: Thu Sep 25, 2008 5:16 pm
Location: Dortmund, Germany

Postby darolla » Sun Jan 25, 2009 11:59 pm

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class WettscheinActivity extends TabActivity {
  3.  
  4.  
  5.  
  6.         @Override
  7.  
  8.         public void onCreate(Bundle icicle) {
  9.  
  10.                 super.onCreate(icicle);
  11.  
  12.                 setTitle("Wettschein");
  13.  
  14.  
  15.  
  16.                 mFlingHelper = new FlingHelper(this);
  17.  
  18.  
  19.  
  20.                 final TabHost tabHost = getTabHost();
  21.  
  22.  
  23.  
  24.                 TabSpec ts1 = tabHost.newTabSpec("Einzel");
  25.  
  26.                 ts1.setIndicator("Einzel", getResources().getDrawable(
  27.  
  28.                                 R.drawable.keyboard));
  29.  
  30.                 Intent i = new Intent(this, EinzelwetteListActivity.class);
  31.  
  32.                 ts1.setContent(i);
  33.  
  34.                 tabHost.addTab(ts1);
  35.  
  36.  
  37.  
  38.                 TabSpec ts2 = tabHost.newTabSpec("Kombi");
  39.  
  40.                 ts2.setIndicator("Kombi", getResources().getDrawable(
  41.  
  42.                                 R.drawable.key_bindings));
  43.  
  44.                 i = new Intent(this, EinzelwetteListActivity.class);
  45.  
  46.                 ts2.setContent(i);
  47.  
  48.                 tabHost.addTab(ts2);
  49.  
  50.  
  51.  
  52.                 TabSpec ts3 = tabHost.newTabSpec("System");
  53.  
  54.                 ts3.setIndicator("System", getResources()
  55.  
  56.                                 .getDrawable(R.drawable.ktouch));
  57.  
  58.                 i = new Intent(this, SystemwetteListActivity.class);
  59.  
  60.                 ts3.setContent(i);
  61.  
  62.                 tabHost.addTab(ts3);
  63.  
  64.  
  65.  
  66.                 // <img src="http://www.anddev.org/images/smilies/smile.png" alt=":)" title="Smile" />))
  67.  
  68.                 tabHost
  69.  
  70.                                 .setBackgroundDrawable(getResources()
  71.  
  72.                                                 .getDrawable(R.drawable.bg));
  73.  
  74.  
  75.  
  76.                 tabHost.setCurrentTab(1);
  77.  
  78.         }
  79.  
  80.  
Parsed in 0.035 seconds, using GeSHi 1.0.8.4


Using Intents I use EinzelwetteListActivity and SystemwetteListActivity for the subview.

Greetings,
DaRolla
User avatar
darolla
Master Developer
Master Developer
 
Posts: 273
Joined: Thu Sep 25, 2008 5:16 pm
Location: Dortmund, Germany

Postby darolla » Mon Jan 26, 2009 12:08 am

okay, I read your post twice, now I understand your question better.

maybe you should leave the typical position of application thinking.

although thinking as if u were a webapplication is wrong (since you dont have something like session / context / ...)

every activity is a whole program, a whole application. using many views inside this application is a strange thing. I have this problem, too.

you can save your date in the properties like save mechanism, or in the db.

or you can give data between the activities using intents.

and that the way we need to think.

maybe thinking as stateless webpages (in static html times) is the best way. you need to pass the data through the url (intent) to the next webpage (activity).

the page flipping problem is another. maybe it helps thinking as if you had to develop your own ajax framework. first thing to handle is the history problem. you need to take care of it yourself. store your states in a map, so you can reinstate them after a page flip.

the other way is to stop the phone from flipping using some manifest xml parameter.

hope I could help...


greetings,
darolla
User avatar
darolla
Master Developer
Master Developer
 
Posts: 273
Joined: Thu Sep 25, 2008 5:16 pm
Location: Dortmund, Germany

Postby rdomloge » Wed Jan 28, 2009 12:41 am

Wow! Thanks Darolla!

So you are saying that a single application using tabs should avoid using Intents/Activities to form tabs? OK.... so if I build the tab layout using XML, I can use a LayoutInflater to create the Views for each tab - got it.

So now, I have a TabActivity class which creates each view from XML.

The next bit is crucial - how do I go about adding in the listeners and so on to each View? My preference would be to use delegation, so I guess I would have a delegate Object which would be responsible for managing each tab?

Then, when one of the delegates wants to show a dialog, they would have to call back to the TabActivity class to use its showDialog() method? And when onSaveInstance() is called in the TabActivity, it would need to call a similar method in each of the delegates so that they can also save their state..?

Am I on the right track?
rdomloge
Junior Developer
Junior Developer
 
Posts: 24
Joined: Sat Jan 24, 2009 2:11 pm

Top

Postby vvestnes » Mon Jul 06, 2009 1:49 pm

Im using the approach with having each tab to be its own activity by using intent.

Now, my problem is, how can i communicate between the tabs...

i have one tab that shows a search box, and another tab showing results... when i do a search, i want to switch to the result tab and make it present the search result...

So for this, the search tab needs a referance to the tabhost to tell it to switch to the result tab, and at the same time send some parameters to the result tab so the result tab knows what to display...


Anyone? I looking forward to any respons as i have't found any good answers yet...
vvestnes
Freshman
Freshman
 
Posts: 5
Joined: Mon Jul 06, 2009 1:43 pm

Postby rdomloge » Mon Jul 06, 2009 11:32 pm

My solution was to create a couple of classes to deal with this.

TabFacade is a top-level class that receives all the API calls to onPause(), onKeyDown(), onCreateDialog() etc etc and it passes these on to a collection of TabControllers which it maintains.

A TabController essentially represents a Tab.

The TabControllers communicate via Intents broadcast by the TabFacade.

If this is of interest to you, just say and I'll PM them to you. They work fine for my FTP client app that I have entered on the Market.
rdomloge
Junior Developer
Junior Developer
 
Posts: 24
Joined: Sat Jan 24, 2009 2:11 pm

Postby vvestnes » Tue Jul 07, 2009 7:53 am

Thanks for the respons


From the manual <receiver>:
Declares a broadcast receiver (a BroadcastReceiver subclass) as one of the application's components. Broadcast receivers enable applications to receive intents that are broadcast by the system or by other applications, even when other components of the application are not running.


Seems like Broadcast and reciever is ment for other applications or other system components.


At the moment im thinking of setting the content of the tabs by R.id.xxxx and not by new Intent(..).
This way I will end up with only one Activity which holds the tabhost. But I will get a fairly large layout xml. But It might work if I use <include> statements for the tab layouts...

Any other suggestions are verry welcome, because im abit afraid im going to have a large activityclass...
vvestnes
Freshman
Freshman
 
Posts: 5
Joined: Mon Jul 06, 2009 1:43 pm

Postby rdomloge » Tue Jul 07, 2009 10:27 am

The poblem (as far as I can see) with setting the content of the tabs with XML is that the business logic for every single tab would need to be in a single class.

In my opinion, that is awful.

To avoid this I created the two classes described above, to use a delegation model, so that the logic for each tab could be contained in a seperate class.

I use the broadcast and receiver model extensively to communicate between the tabs and it works great.
rdomloge
Junior Developer
Junior Developer
 
Posts: 24
Joined: Sat Jan 24, 2009 2:11 pm

Postby Premier » Wed Aug 12, 2009 10:21 am

Yes, derolla solution works fine, and you need broacast intent to allow tabs comunicate
Premier
Junior Developer
Junior Developer
 
Posts: 21
Joined: Fri Jul 10, 2009 4:04 pm

Postby binhsoledas » Mon Oct 12, 2009 12:41 pm

Hi !
I have the same problem, Communication between 2 tabs.

My Applcation have 2 tabs (tab1 (current) and tab2). in every tab, i display 1 list, at tab1, i will init list, and to tab2, i dont want to init it, i want to get list from tab1. I use sendBroadcast and BroadcastReceive, but i dont understand delegate. How do you do it ?. Can you guide me ? my mail : binhsoledas@yahoo.com

Thanks
binhsoledas
Junior Developer
Junior Developer
 
Posts: 10
Joined: Wed Sep 16, 2009 4:16 am

Top

Return to View, Layout & Resource Problems

Who is online

Users browsing this forum: No registered users and 5 guests