I'm looking for some advice on the best way to handle fragments which launch other fragments.
I'm converting an app which I started writing using a more Activity based approach and have since begun moving it over to using Fragments. I have some Fragments which used to launch a new Activity and I want to move them over to launching other Fragments in the same view that the current Fragment is residing.
For example - I have an Activity which has a WebView which uses a WebViewClient to handle internal js->java interactions. My WebViewClient can launch other Activities, which I used to do with :
i = new Intent(context, GoogleMapActivity.class);
startActivity(i);
This webview activity can either be fullscreen or in a view with a menu on the side, but I want the webview to respect the layout - so if the menu is present, it should stay present when launching new Fragments - I just don't know the best approach to writing the code which launches the Fragments.
So...is there a way, within a Fragment, of essentially telling a new Fragment to load in to the same space as the current Fragment or does there need to be some interaction with the Activity?
** EDIT **
Given that there are a few different layouts which could be used, I don't always know which id I should be targeting to put the fragment in - hence I need to know if there's a way to do this without knowing the id (as in the replace method for example).
getFragmentManager().beginTransaction()
.replace(((ViewGroup) getView().getParent()).getId(), fragment)
.addToBackStack(null)
.commit();
This should replace parent container with desired fragment.
That should be doable via FragementManager.replace(). Have a look at the documentation for Fragment and especially the longer example in the "Layout" section there.
If you want to add Fragment rather replace it, use:
getFragmentManager().beginTransaction().add(R.id.fragment_container, new Fragment()).commit();
Related
how to make button to open another fragment. being within a fragment. kotlin
I'm starting in kotlin and I'm having a hard time trying to open a fragment with a button, how do I?
You need to use FragmentManager and FragmentTransaction to add your fragment on the fly. you can call a function similar to this in your button's onClick method. But it is recommended for the parent activity to handle each fragment's lifecycle and the fragments
are not supposed to interact each other. The following is taken from the developer docs, that can be found here.
"Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done either through a shared ViewModel or through the associated Activity. Two Fragments should never communicate directly."
fun createFragmentonTheFly(){
var mFragmentTransaction: FragmentTransaction = getSupportFragmentManager().beginTransaction()
mFragmentTransaction.add(R.id.fr_container,new ProductListFragment())
mFragmentTransaction.commit()
}
The best way to do it would be to add an interface let say onFragmentDetachedLisetner and add one method replaceFragment() or something and make your Activity implement this interaface and had it replace as soon as the fragment is detached and make your fragment that contains your button finish itself when user clicks the button, then your activity will replace it with the one you wanted to start. And also consider reusing fragments, as that is the main purpose of fragments at the first place.
So I am trying to integrate Google Maps into my application, I came across a concept that I don't entirely understand. I have seen that adding google maps into an app and it seems the most common way to do so is with an activity.
I found some websites and a SO question showing how to put Google Maps in a fragment, but would that be an issue if the user is constantly clicking on profiles and going back? Causing the map to be recreated or resumed constantly. Would that performance be better if the map was an activity instead?
Basically, Im not sure the best way to transition from an activity GUI to a fragment? I've had an app that only used 1 activity, I just used multiple different fragments changing them with this code
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = getFragmentManager().findFragmentById(R.id.framecontainer);
if (fragment == null) {
ft.add(R.id.framecontainer, frag, tag);
} else {
ft.replace(R.id.framecontainer, frag, tag);
}
ft.addToBackStack(null);
ft.commit();
I am confused because when I created my main activity, I called
setContentView(R.layout.baselayout);
This layout contained only a frame container, I would then add in a HomeScreenFragment right away and when I needed to change, I would use the FragmentTransaction code above.
However, if my new MapActivity used setContentView(R.layout.maplayout); how would I best change screens? If R.id.maplayout does not contain a framelayout, is it best to start a new activity that uses many fragments like the one I mentioned before? I remember hearing that calling setContentView more than once or outside onCreate() is bad practice.
It seems I am missing something because so far it seems like there is 2 ways of using activities with different layouts
Starting a new activity every time and just trying to minimize the amount of activities.
Make an activity with a FrameLayout and just swap fragments everytime
To address my actual problem
I want my users to click another user marked on the map which will bring them to a profilelayout and view that user's profile, should I use one of the 2 methods above or how should I go about doing so?
Do you guys have any input to point me in the best direction? Thanks!
If your current application is already fragment heavy, have you considered using MapFragment? I think if you're cleaning up your objects/resources appropriately it shouldn't really be a performance issue.
Also according to the documentation it says the following about the MapFragment:
It's a wrapper around a view of a map to automatically handle the necessary life cycle needs.
I think it's also good to note that it's possible for you to do layout manipulation by adding/removing views using the LayoutInflater.
So I basically have a button in 'DemosFragment' and when I click it, I want it to open another fragment (SettingsFragment), I understand now that I need an activity to fix this issue, as the button currently has an onClick method using intent/startActivity, so how would I go about creating an activity that just holds my fragment? I know that may sound weird they way I wrote it, I just started Android development, but basically I have a fragment and because I want a fragment to have a button to open another fragment, I figure I need an activity for the fragment I am trying to open, so how do I create that activity and what do I need to put in it? Thanks.
You need an activity with the following code:
public class ShowFragmentActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_fragment);
}
}
You also have to create a layout xml file called activity_show_fragment.xml in your res/layout folder:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment class="com.example.yourFragmentsClassName"
android:id="#+id/fragment_id"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
This should work for just displaying your fragment.
To launch the activity, paste this code in your button's onClick method:
Intent i = new Intent(this, ShowFragmentActivity.class);
startActivity(i);
It's always a good decision to look at the official docs: http://developer.android.com/reference/android/app/Fragment.html.
Hope that helps!
Wow! Your question requires a long answer, however is a good practice (and madatory too) that Fragments cannot communicates between each others, but they can be hosted by an Activity; in that case an Activity can manage the communication flow between them (fragments) and can be developed in several ways, Bundle, Intent and the Handler. Have a look to the ufficial Android documentation here:
http://developer.android.com/training/basics/fragments/index.html
The android docs section on building a flexible UI is a good example of how to start/load a Fragment from an Activity. In the example you will see that a FrameLayout in the Activity XML is used a the fragment container. This will be the View in which all of your fragments are displayed.
When you load your fragment with a FragmentTransaction the contents of your fragments layout will be displayed in the container View. In the above referenced example this takes place with SupportFragmentManager a class included with the android support library, for facilitating fragment transactions in earlier version of the operating system. SupportFramgnetManager requires that you extend FramentActivity and not just Activity. If you're not worried about backwards compatibility and are extending activity, not fragment activity, you can simply use getFragmentManager() instead.
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
After the initial add transaction you can switch between fragments using the replace method for your fragment transaction. Replace does exactly what it sounds like, it swaps one fragment for another. To accomplish this from within your firstframgnet use
SecondFragment secondFragment = new SecondFragment();
getActivity().getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, secondFragment).commit();
Notice that from within the fragment I used getActivity(). This allows you to reference the context of the host activity to access the fragment manager. When you are within the activity you do not need to use getactivity because the fragment manager is already accessible from that context.
Just a general question about working with Fragments and Activitys for android development: where does the business end of the functional code go for Fragments loaded into an Activity dynamically? (i.e. a fragment's OnClickListeners, OnCheckedChangedListeners, button logic methods...)
Do they go in the Fragment class, or the Activity class?
All the GUI logic for views attached to a fragment should be contained inside the fragment itself.
Thus a fragment should be as self contained as possible.
You can, though, if necessary do callbacks to your activity based on fragment GUI interaction. This can easily be done like this inside the fragment:
#Override
public void onAttach(Activity activity) {
if (!(activity instanceof SherlockFragmentActivity)) {
throw new IllegalStateException(getClass().getSimpleName()
+ " must be attached to a SherlockFragmentActivity.");
}
mActivity = (SherlockFragmentActivity) activity;
super.onAttach(activity);
}
In this specific case the reason for gaining a reference to SherlockFragmentActivity is to gain access to the support menu inflater mActivity.getSupportMenuInflater(), hence the construction can of course also serve to gain information from the underlying activity.
This probably depends on how much the Fragment's functionalities have in common, and how many, let's say Buttons, have to be handled.
I personally (and it's probably most common practice) handle onClick(...) events separately for each Fragment, meaning that I let each Fragment implement it's own OnClickListener.
Furthermore, when handling everything through the Activity, probably not all the components that react to click-events are in memory at all times and can be reached via findViewById(...), depending on which Fragment is currently displayed and how your user-interface is built up in general.
they always in fragment class because fragment is one type of component in android which we can reuse it. if we put onclick and oncheckchanged in activity then what meaning of reusing that component??
for more information about please go through following step:
Link 1 for basic level of information about fragment and how to handle them
Link 2 for dealing with multi pane fragment
Standard site for fragment
It depends:
If fragment can handle logic which is self sufficient(complete) then that code can be handled by fragment. e.g. on click call phone number.
If fragment have UI whose action is activity specific, then you want to add listener in activity.
e.g. master detail view like email client, on tablet user click on title fragment1 which have list of email titles, then handler on click in activity can show detail fragment2 in activity.
In all you want to keep fragment reusable.
I am a bit confused about what is the ideologically correct way of using fragments.
As the Android Developers states,
A Fragment represents a behavior or a portion of user interface in an
Activity. You can combine multiple fragments in a single activity to
build a multi-pane UI and reuse a fragment in multiple activities. You
can think of a fragment as a modular section of an activity, which has
its own lifecycle, receives its own input events, and which you can
add or remove while the activity is running (sort of like a "sub
activity" that you can reuse in different activities).
And also:
Fragments decompose application functionality and UI into reusable
modules Add multiple fragments to a screen to avoid switching
activities
And my usage of fragments goes the following way:
I have only one main Activity and a whole bunch of fragments. Instead of starting activities, I prefer replacing fragments.
For example, I have FeedsFragment, FriendsFragment, MessagesFragment, and when I select something from sliding menu, my Activity just replaces the main Fragment. If I'm launching a Fragment from other Fragment, I put the previous one in backstack.
Some fragments require the Activity to change the actionbar, an I do it directly by
((MainActivity)getActivity()).setupActionBar();
Currently I don't have any code that supports tablet layouts (as seen in examples on android developers), but I'm planning to add it.
So, is this the right way of doing things? Or am I completely missing something?
As you know fragment has their own lifecycle, and you can use its event when ever you want from the activity lifecyle.
But Fragments lifecycle depens on activity lifecycle So when actvity destroyed, fragments destroyed also.
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Yo can use the fragment transaction, to replace them in one activity, I think you use the same way,
i think you arent wrong way and there are no problem to use fragment instead of using different activites.
But you should think about, you realy need to use them in one activty ? If you dont need to show them in one activity you dont need to use fragment.
A fragment must always be embedded in an activity and the fragment's
lifecycle is directly affected by the host activity's lifecycle. For
example, when the activity is paused, so are all fragments in it, and
when the activity is destroyed, so are all fragments. However, while
an activity is running (it is in the resumed lifecycle state), you can
manipulate each fragment independently, such as add or remove them.
When you perform such a fragment transaction, you can also add it to a
back stack that's managed by the activity—each back stack entry in the
activity is a record of the fragment transaction that occurred. The
back stack allows the user to reverse a fragment transaction (navigate
backwards), by pressing the Back button.
As a result , it is not wrong , but i think if you dont need, creating different activity is easy to maintain.