I am developing an applications that is aimed at Tablets and Google TVs. It will be like many standard Google TV applications with a LeftNavBar and a top Search bar that is common to all application screens. It will look something like the following image:
The RED area will be different for all other screens. It may contain data like following screens mockups:
Activity One loaded into main container
Activity Two loaded into main container
So you can see that completely different sections can be loaded in the main area.
Screen 3 can be loaded as a detailed section when selecting any list item in Screen 2 (say in fragment list) OR it can be loaded as a result of selecting a tab (which will appear in LeftNavBar).
Here is how I am trying to implement it.
Step 1. I Created a main Activity with the following XML:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#9ccc" > <!-- Top Bar --> </LinearLayout> <FrameLayout android:id="@+id/mainContainer" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <!-- main Red Container that will load other Activities --> </FrameLayout> </LinearLayout>
mainContainer is the RED container where I want to load the Activities.
LeftNavBar will be added to this Activity as its the parent of All.
Step 2 I created
ActivityTwo with two & three Fragments in them respectively (as shown in above second & third image).
*Step 3 I am trying to load the
ActivityOne in main page’s mainContainer FrameLayout… But I cannot add it.
I tried by adding the
mainContainer as follows:
View v = (new ActivityOne()).getWindow().getDecorView(); FrameLayout mainContainer = (FrameLayout) findViewById(R.id.mainContainer); mainContainer.addView(v);
Other issue occurs because all the data comes from a remote services .. so please also suggest how would I be able to hold references to all the loaded Activities in
mainContainer in a some kind of stack … so I can just reload the already loaded activity instead of creating its new instance.. This will be used on BACK button press.
Instead of loading an activity into the above RED container, I should create two Activities each with their own Fragments & a LeftNavBar. This might be easier than the aforementioned approach. or this might be the only solution…. however I feel that saving state for BACK buttons might get messy .. but I will try implementing this
What would you do if you had to create this type of application?
How would you design the UI layout for best performance/practice?
Your suggestions in helping me setting this app’s layout are much appreciated.
This is where fragments can get tricky. The problem would be simple if Activity 1 & 2 had identical layouts so that you could simply attach/detach fragments and use the fragment back stack to unwind.
Because you want 2 unique layouts to house your fragments, things are going to be a little more involved. If at all possible I would try to use the same layout so that you can take the easy path.
As another option, you could use two activities as you outline above and send data back and forth with Intents.
That said, if I really had to implement this solution as written, here is what I would do. Note that I am not advocating this solution but myself do not know of a better way of doing things.
Create a FragmentActivity whose view would be Main Screen as you’ve defined above. The layout for the Main Screen would contain:
- Left nav bar
- Top bar
- 2 layouts. layout1 and layout2. These would be contained in a parent layout i.e. RelativeLayout or LinearLayout and would contain the necessary FrameLayout elements for your fragments.
Example using your XML (note, tags are a bit brief):
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="50dp" android:background="#9ccc" > <!-- Top Bar --> </LinearLayout> <LinearLayout android:id="@+id/layout1"> <FrameLayout android:id="@+id/listFragment" /> <FrameLayout android:id="@+id/contentFragment" /> </LinearLayout> <LinearLayout android:id="@+id/layout2"> <FrameLayout android:id="@+id/imageFragment" /> <FrameLayout android:id="@+id/boxFragment1" /> <FrameLayout android:id="@+id/boxFragment2" /> <FrameLayout android:id="@+id/boxFragment3" /> </LinearLayout> </LinearLayout>
The main idea is that you then show/hide layout1 & layout2 i.e. set android:visibility=”gone” based on the state of your app.
The disadvantages of this method are:
- Using fragment backstack may be impossible, instead you’ll have to track where the user is in your UI flow and manage the back button to show/hide layout
- You may need to take special care to attach/detach fragments when you show/hide their parent view to reduce resource consumption while the fragments are invisible
The advantages are:
- Easy communication between fragments and the base activity since only 1 activity is used
Re: The nested Fragments problem
To get around the ‘nested Fragments’ problem in our application where (as you correctly note)
Fragments cannot add
Fragments I hosted a single templating Fragment under the activity whose only purpose was to define a set of place holders for other fragments to anchor to. When adding further Fragments to the activity past this point I used the templating Fragment’s view place holder
[email protected]s to identify the “root” or parent view Id for the Fragment being added.
getSupportFragmentManager().beginTransaction().add(#someIdFromTheTemplateFrag, fragment, fragmentTag).commit();
The Fragment I was adding then knew where to anchor itself in the current layout and of course then went about it’s merry way of add it’s view. This had the effect of attaching a Fragment to another Fragment hence achieving the desired visual ‘nesting’…