Building a Dynamic UI with Fragments - android

I want to design a dynamic UI for my application so in screens with more than 500dp width it will show 2 fragment and otherwise it shows a single fragment.
Here is my layout files:
layout/activity_main:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frag_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
layout-w500dp/main_activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment android:name="ir.focusmag.focus.PostsFragment"
android:id="#+id/posts_frag_container"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent"
tools:layout="#layout/fragment_posts" />
<fragment android:name="ir.focusmag.focus.PhotosFragment"
android:id="#+id/photos_frag_container"
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="match_parent"
tools:layout="#layout/fragment_photos" />
</LinearLayout>
in MainActivity.java there is a check to see whether frag_container is present or not and if it's there it will load the PostsFragment into it:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check whether the activity is using the layout version with
// the fragment_container FrameLayout. If so, we must add the first fragment
if (findViewById(R.id.frag_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
firstFragment = new PostsFragment();
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragm_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.frag_container, firstFragment).commit();
}
}
And there is a Listener for clicking on a post to replace the fragment with the details fragment.
The important point here is if we're being restored from a previous state it doesn't do anything.
In usual scenarios this method works but if the user stars the application in landscape mode ( screen width > 500dp ) MainActivity checks for frag_container and as it's not there It will do nothing and then the user will rotates the device to portrait mode and as the savedInstanceState is not null anymore nothing will be loaded into frag_container.
If I remove the check for savedInstanceState, whenever the user rotates the device PostsFragment will be loaded and it's not wanted. for example the user is checking the details and rotates the device and it shows the posts instead of the details.
What can I do to stop this kind of behavior?
I'm following Android Developer's tutorial to do this.
Thanks in advance

This approach is a little bit outdated. If you just started playing with Android and want to see how to handle things modern way, watch Developing Android Apps video course from Google by Google. They will show you how to deal with Master/Detail pattern properly. If you would like to jump immediately to the code, start your Android Studio and create new Activity with the wizard and pick Master/Detail form.
Your new activity's onCreate() method would look like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_list);
if (findViewById(R.id.item_detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-large and
// res/values-sw600dp). If this view is present, then the
// activity should be in two-pane mode.
mTwoPane = true;
// In two-pane mode, list items should be given the
// 'activated' state when touched.
((ItemListFragment) getFragmentManager()
.findFragmentById(R.id.item_list))
.setActivateOnItemClick(true);
}
// TODO: If exposing deep links into your app, handle intents here.
}
Comparing to your current approach, this time for single pane mode fragment is added within XML layout so you don't have to bother with unexpected behavior. You will also see there how layout aliases works.
I know it's not a simple answer you may expect buy it may be the last moment for your application to apply this change. I really encourage you to do it.
If this change is not an option for you consider modifying single pane layout and include fragment there instead adding dynamically. Probably, at the moment, your are not benefit from dynamic fragment at all anyway.

Related

Detail fragment re-starts even when rotated from landscape to vertical. (Master-Detail Flow)

In an Activity, lets call it MasterActivity, I want to load the detail fragment with media playback only in landscape mode. The media automatically starts when ready.
Master-Detail Flow setup: I have two xmls, activity_master and activity_master.xml(land). The container view with id "detail_container" is only in the landscape xml. The purpose of the landscape xml with a detail container is to show master-detail both on the same screen, on width >900.
In onCreate(), this is how I'm determining the screen orientation though checking the existence of the "detail_container", like so:
if (findViewById(R.id.detail_container) != null) {
// The detail container view will be present only in the
// large-screen layouts (res/values-w900dp).
// If this view is present, then the
mTwoPane = true;
}
and also in OnCreate() of the activity, I have the following code to automatically load the fragment when activity is in two pane mode (landscape on large-screen layouts)
if (mTwoPane) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.detail_container,
someFragment.newInstance(MEDIA_URI))
.commit();
}
Problem:
When I start the activity in vertical, the fragment isn't loaded (expected).
When I start the activity in landscape, the fragment is loaded (expected).
On screen rotation, fragment is destroyed (expected, playback stops and resources released only in onDestory());
The problem is when I start activity in landscape but rotate it to vertical, the fragment restarts, and media playback start again (unexpected).
My Goal: I want the fragment to automatically load when the device is in landscape on large screen devices, on device rotation the fragment shouldn't load again.
EDIT: In vertical mode, the fragment shouldn't load automatically, user would click in master activity, opens the detail activity, and the detail activity would host the detail fragment.
How should I go about this? Thank You in Advance
Extra Info: Test physical device is a 7' tablet running Android 5.0 API 21, the issue is also present in emulator.
When a config change occurs, Android will make sure all fragments that are attached to an activity are recreated and reattached back to the new activity's FragmentManager ; this is separate of whether or not the fragments took setRetainInstance(...) into consideration.
So it looks like what you want to do is go against the automatic reattaching of fragments. I was curious about this too so I took a little deep dive into FragmentActivity.onCreate(...) and FragmentManager but I couldn't find anything exposed that allows developers to disallow this automatic process. You can, however, work around the process with a FragmentTransaction by performing the following in your code:
FragmentManager manager = getSupportFragmentManager();
if (mTwoPane) {
// set up your two pane
manager.beginTransaction()
.replace(R.id.detail_container,
someFragment.newInstance(MEDIA_URI),
someFragment.TAG)
.commit();
} else {
// this is not two pane, so remove the fragment if it is attached
Fragment detail = manager.findFragmentByTag(someFragment.TAG);
if (detail != null) {
manager.beginTransaction()
.remove(detail)
.commit();
}
}
I don't know how your layout XML looks like but I suggest to define the Fragment in your "landscape" layout file only by creating a new directory called /res/layout-land if it not exists.
Layout may look similar to this:
<SomeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<fragment android:name="com.example.YourPlaybackFragment"
android:id="#id/playback_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
...
</SomeLayout>
Here's a useful link on the official Android doc.
Then the Fragment is only inflated in landscape mode and Android takes care of that. Same procedure can be done for bigger screens. That frees your MasterActivity from layout logic.
Your playback logic goes into the Fragment. If the Activity, for whatever reason, needs access to the Fragment then you pull it in with
YourPlaybackFragment fragment = (YourPlaybackFragment) getFragmentManager().findFragmentById(R.id.playback_fragment);
Hope that gives you the right direction.
Edit:
In that case your best bet is to add the Fragment programmatically in the onCreate() method similar to this.
if (findViewById(R.id.detail_container) != null) {
// detect the landscape
Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_90) {
// add the fragment
getSupportFragmentManager().beginTransaction().add/replace(...)
}
}
Disclaimer: not tested.
Since you have two different activities, the fragment no longer exists in the same context so that might be a little difficult to produce the behavior you're looking for. Try to do the following:
Portrait : xml layout with only one container for the MasterFragment. Swap this container with the DetailFragment when selected.
Landscape : xml layout with two containers, one for MasterFragment and one for DetailFragment. If DetailFragment already exists (user was viewing it in portrait before the orientation change), the fragment manager knows about it. Find the existing fragment and attach it to the appropriate container.
Assuming you're letting your activity be recreated on orientation changes, if you're using setRetainInstance(true), the fragment manager can hold onto your existing fragment and should re-attach the same one automatically on orientation change. If you want it to reattach, you should check to make sure the fragment doesn't exist yet before calling replace(...). If you want to attach it somewhere else, you can grab the existing one and put it in a different container.
if (mTwoPane) {
if (getSupportFragmentManager().findFragmentByTag(someFragment.TAG) != null) {
// fragment already exists so either do nothing (auto reattach to R.id.detail_container)
// or manually attach it to a different container
return;
}
fragment = someFragment.newInstance(MEDIA_URI);
getSupportFragmentManager().beginTransaction()
.replace(R.id.detail_container,
someFragment.newInstance(MEDIA_URI),
someFragment.TAG)
.commit();
}

Android. Fragment stays in activity after screen rotation issue

I have a two variants of activity_main.xml (for portrait/landscape orientation). In this activity, user can choose items and browse detailed information about selected item.
In portraint orientation, fragments added to flFragmentContainer dynamically, after item choosing, details fragment replaces list fragment:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/flFragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"></FrameLayout>
</LinearLayout>
In landscape orientation, fragments described in XML file statically:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="#+id/frgTaskList"
android:name="com.exprod.xchecklist.fragments.TaskListFragment"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
tools:layout="#layout/fragment_task_list" />
<fragment
android:id="#+id/frgTaskDetails"
android:name="com.exprod.xchecklist.fragments.TaskDetailsFragment"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
tools:layout="#layout/fragment_task_details">
</fragment>
</LinearLayout>
</LinearLayout>
Here is the code of onCreate() method (of MainActivity).
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getSupportFragmentManager();
TaskDetailsFragment taskDetailsFragment = (TaskDetailsFragment)fragmentManager.findFragmentById(R.id.frgTaskDetails);
isDynamicMode = taskDetailsFragment == null || !taskDetailsFragment.isInLayout();
if(isDynamicMode){
FragmentTransaction transaction = fragmentManager.beginTransaction();
Fragment taskListFragment = new TaskListFragment();
if (savedInstanceState == null) {
transaction.add(R.id.flFragmentContainer, taskListFragment, TaskListFragment.FRAGMENT_TAG);
}else{
transaction.replace(R.id.flFragmentContainer, taskListFragment, TaskListFragment.FRAGMENT_TAG);
}
transaction.commit();
}
}
PROBLEM: When I rotate device to landscape orientation, I get twice calls of creation methods in first fragment (TaskListFragment) (onCreateView(), onActivityCreated(), ... ). This indicates that the old fragment remains in activity and recreated on orientation change.
How I can finally destroy old fragment?? I did not find the answer on the Internet.
P.S: Sorry for my bad English...
I see at least two approaches to do what you want.
Handle orientation change yourself:
As described in this document, you can prevent automatic Activity destroy and re-creation and handle orientation change yourself. In this case, you would remove the old Fragment before inflating a new layout into Activity.
Remove the old Fragment after Activity re-creation:
You could also add some logic that determines the orientation as described here (or use your current heuristic that sets isDynamicMode), and manually remove the unnecessary Fragments during onCreate().
The better way:
Although it is possible to do what you want, I can't undertand why would you like to do it this way - you use TaskListFragment in both portrait and landscape configurations, therefore the most logical thing to do is to reuse it. Except for simplifying things, it will also let you keep the state of that Fragment on orientation change (which, I believe, is desirable in your case).
Thanks for Vasiliy answer. I follow this link
and add
android:configChanges="oritentation"
to my manifest file:
<activity android:name=".MyActivity"
android:configChanges="orientation"
android:label="#string/app_name">
and the annoying behavior (fragment not attached to activity) when screen is rotated disappears
Just add to your activity
#Override
public void onSaveInstanceState(Bundle outState) {}
because implementation of this method in Android's Activity that is a parent of all Activities, saved Fragment.

Two fragments hold by another fragment - findViewById returns null

I need help for my first Android application. I have a single activity with an Action Bar at the top and Navigation Tabs. Because of these navigation tabs I had to convert my Activities into Fragments.
So one of those Activities (which is now a Fragment) held two fragments, one ListFragment on the Left and a DetailFragment on the right, so that the user is able to select an item from the list and directly sees details on the right.
But now as the Activity has been transformed into the Fragment, it's the Fragment that holds the List- and the DetailFragment. This works fine until I want to change the DetailsFragment.
First of all, here is the code of the Fragment holding the other two:
public class BlackboardFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
return inflater.inflate(R.layout.fragment_layout, container, false);
}
}
Here is the fragment_layout.xml file (saved in layout-land):
<?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="horizontal" >
<fragment
android:id="#+id/interfaces"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_marginRight="20dp"
android:layout_weight="0.60"
class="org.fawkesrobotics.app.InterfaceFragment" />
<FrameLayout
android:id="#+id/viewer"
android:layout_width="0px"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
So, the ListFragment is named InterfaceFragment, here is the code:
public class InterfaceFragment extends ListFragment {
boolean mDualPane;
// some other code
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
create_list();
View viewerFrame = getActivity().findViewById(R.id.viewer);
mDualPane = viewerFrame != null
&& viewerFrame.getVisibility() == View.VISIBLE;
if (savedInstanceState != null) {
mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
}
}
// some other code
}
This is, where it doesn't work. The Fragment actually shows the list (that is created in create_list() where the ListAdapter and everything else is set), but my problem is, that viewerFrame is null. I declared the id viewer in the xml file above, so I don't understand why he cannot find the id. Does it "belong" to the BlackBoardFragment or to my overall activity? Because in BlackboardFragment I also tried it with getActivity().findViewById and it worked. Why is InterfaceFragment not able to find it?
I also tested, if he really uses the fragment_layout.xml in layout-land and he does. So he should know the id viewer, but obviously doesn't.
If you need more code or the code from the DetailsFragment, I can post it.
Thank you in advance for your help! :)
use FragmentManager to get Fragment......
ExampleFragment fragment = (ExampleFragment) getActivity().getFragmentManager().findFragmentById(R.id.example_fragment);
Nested Fragments are not supported by the Android SDK. That is, you can't have a "fragment within a fragment" in your Android application. Sorry.
EDIT:
Nested Fragments are now part of the official Android 4.2 SDK! Yay!

Determining whether or not previous Activity can handle multiple Fragments in current orientation

I am developing an app that is very similar to the typical newsreader app. I have a Listview in a fragment on the left side of the screen and the right side shows the details of the selected item if we're in landscape view. Otherwise the details fragment is shown in its own Activity. I have this working just fine.
However there is one caveat: I only want it to behave this way on larger screen sizes (probably only tablets but that's subject to change). On smaller devices I want to see only the the Listview fragment and launch the details fragment in its own activity no matter the orientation. I also have this working.
The problem I currently have is in the Details Activity and how to determine when to finish() and return back to the previous activity to show the fragments side by side. I have the following code that works for larger devices but doesn't allow smaller devices to view this activity and thus the details fragment at all:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
How can I determine that going back to the previous activity will allow the fragments to be displayed side by side?
Eureka! My solution is to provide an alternate layout for the Details Activity that was empty. After I inflate the layout I can check to see if the fragment I am expecting is in the layout and if it isn't then I finish().
details_view.xml in /res/layout:
<?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="horizontal">
<fragment
android:name="com.website.DetailsFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:id="#+id/details_fragment"
android:layout_weight="75">
</fragment>
</LinearLayout>
details_view.xml in /res/layout-[screen size]
This one is for any screen size that you do not want to display the Details fragment in its own activity in landscape mode (more or less tablets in my case).
<?xml version="1.0" encoding="utf-8"?>
<!-- Note: This file has an empty layout to notify
DetailsViewActivity that we should go back to landscape
and view the fragments side by side -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
</LinearLayout>
Simply put the empty details_view.xml file in any layout directory that has the layout file that allows to show the fragments side by side.
Finally the code for DetailsViewActivity to exit if we want to go back to side by side:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details_view);
mDetailsView = (TopicViewFragment)getSupportFragmentManager()
.findFragmentById(R.id.details_fragment);
// We can handle the fragments side by side in the previous activity
// so lets go back there
if ((mDetailsView == null || !mDetailsView.isInLayout()) &&
getResources().getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
I would have liked a little less duplication of data but this solution isn't bad. It only forces you to copy one extra layout file into the same directory that you have the side by side fragments layout file. Not too bad really.
I think the following also work without the the usage of an empty layout.
package de.vogella.android.fragments;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.widget.TextView;
public class DetailActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Need to check if Activity has been switched to landscape mode
// If yes, finished and go back to the start Activity
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
finish();
return;
}
setContentView(R.layout.details_activity_layout);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String s = extras.getString("value");
TextView view = (TextView) findViewById(R.id.detailsText);
view.setText(s);
}
}
}

layout with fragment and framelayout replaced by another fragment and framelayout

EDIT:
So after the comments below, I revisted and realized what was hanging me up.
Imagine my client list and client details activity be started by :
public class ClientsMainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//StudioTabOpenHelper db;
setContentView(R.layout.main_client_activity);
}
}
So this works great, starts up my main_client_Activity (defined in a layout below, and i call this activity when a button on my main screen is clicked):
Intent intent = new Intent(getActivity(), ClientsMainActivity.class);
startActivity(intent);
Easy the issue is, the ClientsMainActivity does not call a OnCreateView or anything, just sets the layout to the layout that defines my Fragment, and my ListFragment. This is fine cause I am not trying to pass anything into the ClientsMainActivity, but if I have a hypothetical activity like:
SessionMainsActivity that is called when they click on the session edit of a client, then I would not be calling the SessionsMainActivity the same way (starts activity that just sets to alayout), i would want that layout set as it defines how my fragments are split up. But I would also want to pass in data to that and then to the subsequent fragments (like which session they clicked on to be editing/mucking with.
So I wonder if the above makes sense, I am sure its a simple thing I just cannot wrap my brain around. I have no issues calling FragmentActivities from other fragments, they take up the whole screen but it works. So I guess the big issue is that ClientsMainActivity is from some example I found online for doing recipes that shows you how to make multiple fragments to a screen. The thing that gets me all that FragmentActivity does is sets the content view, to a layout that does all the work it seems, so that's why I cannot figure out how I would code it to do the same thing but let me pass in values to the fragments the layout defines etc...
END EDIT
So I am using this nice little tutorial here:
http://developer.android.com/guide/topics/fundamentals/fragments.html
It has gotten me a long way and utilizing what they say to do for the main activity, and the fragment_layout.xml, I got a nice client list on the left (Thats a listfragment) and a details fragment on the right.
Then i added the ability to edit session information on a client (or edit client details) both of which were full screen fragments. This worked great.
Now I decided my Session edit ui would best be served splitting the information up into two panes again.
This is not working as I thought, like I said I have a main_Activity that does this in the onCreate:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_client_activity);
}
with the main_client_activity.xml being defined in two layouts but the one for landscape tablets is here:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.viciousbytes.studiotab.subactivities.ClientListView"
android:id="#+id/client_list" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" />
<FrameLayout android:id="#+id/client_details" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground"/>
</LinearLayout>
This all works great! In which case I handled everything else as a full screen activity that started its own fragment:
EditSessionActivity
EditClientActiivyt both of which use getSupportFragmentManager().beginTransaction and I could pass information into it from the .newInstance call.
I had my session_edit.xml layout defined with buttons, textviews etc..and that was working great. Thats what i loaded in my SessionEdit fragment "launched" by my EditSessionActivity But now since I want to split it apart I ran into a snag. Above I defined a client_list and a client_details id, are these placeholders on my screen? do I reference those when I wanna replace whats there with totally different fragments?
or do i build another fragment layout called something like fragment_session_layout which defines something like:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.viciousbytes.studiotab.subactivities.SessionEdit"
android:id="#+id/session_edit" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent" />
<FrameLayout android:id="#+id/invoice_details" android:layout_weight="1"
android:layout_width="0px" android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" />
</LinearLayout>
Sorry don't know what to title this on the tip of my tongue of what I am asking, basically how to get two panes of fragments twice over. THe demo online shows how to do one (and a simple ListFragment at that).
I have done all the above and I just cannot figure out how to pass into the fragment the data I need, I was using this in my EditSessionActivity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int clientID = getIntent().getIntExtra(THE_SELECTED_CLIENT, -1);
int sessionID = getIntent().getIntExtra(SELECTED_SESSION,-1);
SessionEdit edits = SessionEdit.newInstance(this.getBaseContext(), false, clientID, sessionID);
mUIListener = (OnUpdateUI)edits;
getSupportFragmentManager().beginTransaction().add(android.R.id.content, edits).commit();
}
that worked, but to try to adhere to the earlier fragment example, i assumed my EditSessionActivity was sorta like making another MainActivity (cause it has two panels in it like the main one). so I recoded the onCreate in EditSessionActivity with this:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_session_fullview);
}
Which after fighting in my EditSession fragment dealing with the onCreateView, I got this to finally work but couldn't pass in the data cause there is no instantiation of the object using like the previous onCreate which had the edits=SessionEdit.newInstance(...)
So is it good practice to be doing the other fragment layout that has two pains in it and starting that up when the right action is triggered. Or is one supposed to replace the two already created fragments?? from my main_client_activity.xml somehow?
I assume editing clients and editing sessions are two distinct activities. When you switch from "editing clients" to "editing sessions" mode, both the "list" and "details" panes would change?
I would go with two layout files, instead of trying to reuse the same layout and reload fragments in it.
If you tried to reuse the same layout, you would have to:
Change #+id/invoice_details to something like #+id/right_pane. Otherwise it would look confusing to load something related to sessions into "invoice_details" placeholder.
replace fragment definition with another FrameLayout and load either ClientListView or SessionListView (or however it's called) fragment there at runtime.
This would add more complexity than having another layout xml file in my opinion.
So
Take your existing code that works with client list and client details
Duplicate all involved parts, and change what needs to be changed so it's now session list and session details
Remove duplication where it's easy to do (common functions go to utility classes, common layout elements to layout includes). Leave the things that are hard to de-duplicate as-is.
Re-evaluate later, when you have more fragments, more layouts and more experience.
UPDATE, about two different approaches fragments can be embedded in activity
As the Android documentation states, there are two main ways you can get a fragment to show up in your activity:
declare the fragment in layout's XML file (<fragment class=.... />)
put a placeholder FrameLayout in layout's XML file and load fragment at runtime
First approach is fine when fragment doesn't need to receive any arguments. Like, for example, if the logic to retrieve single and only list of clients is hardcoded in fragment's code.
Second approach lets you pass arguments to the fragment, and therefore is appropriate for "details drilldown" type of fragments.
From updated question I understand that,
each client has a separate list of sessions
the components in play are: EditSessionActivity that hosts two fragments, one for displaying list of sessions, another for displaying session details
If that's correct, then indeed you'd need to load both fragments programmatically because both needs parameters to be passed to. So your layout would have two FrameLayouts. The EditSessionActivity would start with getting some parameters from intent ("which list of sessions are we working with?"), and load "list of sessions" fragment with these parameters. When user selects list item in that fragment, the other fragment would be loaded with session details.

Categories

Resources