I asked a question a while back:
Replacing Fragments isn't working/Am I executing this the proper way?
Because I was having a really tough time wrapping my head around the entire concept. Past Google I/O videos have also helped, but I still didn't really have a reason to use fragments. I have encountered my problem again, and with more searching and Google I/O 2013 videos, I've hit another fork in the road. After starting a bounty to get a more expert opinion on this subject, I was guided to use FrameLayouts, yet in this I/O 13 video at 19:05 into the video it shows <fragment>. Can someone clear up any discrepencies or misconceptions I have?
Do I use <fragment> or <frameLayout>? Bonus points if you look at my original question to know where I'm coming from.
There are 2 seperate questions I see in here; (1) what is the <fragment> element? (2) am I (meaning you) doing what I tried to do in my previous question in the best way possible by using a FrameLayout?.
I will try to answer both.
The <fragment> XML tag is just another way to implement a fragment. As a refresher, a Fragment is like a part of an activity. It is a stand alone class, however, referring back to the fragment documentation, because a Fragment is intended to be modular, all fragments must be housed within a seperate FragmentActivity. Think of this as FragmentActivity as a container. By loading your Fragment into the FragmentActivity the FragmentActivity provides other valuable functions that the Fragment class does not have access to on its own. It also offers you the chance to swap out fragments dynamicly, allowing for a more flexable user experience.
How you load your Fragment into its containing FragmentActivity depends on what you are trying to acomplish. One way to do this is to use the <fragment> tag. With this approach, rather than declaring the Fragment in the activity java code and then loading it with a FragmentTransaction as you did in your earlier question, the Fragment class is loaded via the XML layout for the containing FragmentActivity.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
android:name="com.example.android.fragments.HeadlinesFragment"
android:id="#+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
You can see the fragment declared here in the example taken from the android docs. The fragment is then loaded by the FragmentActivty when setContentView() is called onCreate.
public class MainActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.news_articles);
}
}
The other way to display fragments is as you have done it in your prior example. Using a FragmentManager you can create a new instance of your Fragment class and load it programatically within the java code.
So which technique makes sense when? As the example from the android docs demonstraits, the XML fragment method makes sense when you are using stationary fragments, i.e. you are not dynamically swapping fragments in and out. This is because you cannot edit the XML layout you create on the fly the same way you can the java code. Also, from what I can tell, using the XML approach treats the fragments more like layout elements alowing for different control. In the android example, they use the XML approach to display 2 fragmens side by side on a tablet. By controling the fragments more like layout elements, e.g. having the ability to adjust layout_weight you can achieve a better result for that purpose.
However, if you are designing a highly dynamic UX, say with a ViewPager or some other feature where fragments will be rotated regularly, it makes more sense to use seperate Fragment classes and replace those Fragments as they become necessary.
Based on your prior question and the need to swap fragments dynamicly I think you made the right choice for that implementation.
Related
i have this app that i want to have a specific way of navigation. And so i made a research but i got confused. And i am begginer in android development.
i want to ask what kind of layout or anything i can use to achieve that. I dont search for super specific answer, just what is the thing that is doing the job i want. So there it is:
the blue block("choose a brand" view) has to be on that position at all times and only changing the text if needed. I want when one image button is clicked the whole green block with the image grid change into another xml layout. I want to call multiple layouts in the green block when i interact with the buttons of those layouts. Atm the green block is an <include layout ="layout.xml"/>
I really apreciate any answer. Sorry if is basic but i really tried to find the thing i need but so far i see solutions that prevent me from using simple inflaters. Thanks in advance
You have to use fragments for this scenario.
You will have a LinearLayout where the first element will be your blue block.
The second element will be a FrameLayout that you will change into the Fragment you need (usually it will have the ID container).
Create a Fragment and set the layout your layout.xml file.
Create a second Fragment with the desired layout you would like to change the green block.
As you click on a imageButton you will have to change the current Fragment with the desired one. Here you will see how to send objects to fragments.
You can find here a way to switch between fragments. In the ft.replace method the first id is the FrameLayout you will use as a container(see above).
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.container, new NewFragmentToReplace(), "NewFragmentTag");
ft.commit();
Be careful when you import fragments. If you use the support package you will have to use getSupportFragmentManager();
Read more on the android developer about fragments
I think what you are looking for is Fragment class, which can be used as reusable code that can be linked to a UI/layout.
From android documentation:
To create a dynamic and multi-pane user interface on Android, you need to encapsulate UI components and activity behaviors into modules that you can swap into and out of your activities. You can create these modules with the Fragment class, which behaves somewhat like a nested activity that can define its own layout and manage its own lifecycle.
Read more here
So, I am using Activity Recognition API to know the state of the user, and implementing it like Google FIT does.
I have written all the logic for the app in main_activity.java and a class I made for ActivityRecognition. And I have my XML in activity_main.xml
PRetty usual stuff till now.
Well the problem arises now when I want to integrate the code in Tab layout material design which uses fragments and viewpager to display.
If I copy my activity_main.xml to Fragment_one.xml, Do I have to copy the logic for ActivityRecognition API to Fragment_one.java too or not ?
Very confused, any help will do.
My main xml file has a FrameLayout, with one fragment defined in the XML. At runtime, I am adding another fragment on top of this, and then a third fragment on top of this. When I add the runtime fragments, I don't give containerIds to attach them to. This is all fine until the orientation changes. After the orientation change, the third fragment has gone beneath the second fragment. But obviously I want the z-order to stay how it was before the orientation change, i.e. the last fragment added should be on top and visible.
I've tried using containerIds when adding the fragments, and adding them to the FrameLayout defined in XML, but when I put in containerIds, the runtime fragments simply don't show up at all.
So I'm wondering why the fragments added at runtime don't show when I use a containerId. Is it because they are being added to a container which already contains a fragment (the one defined in XML)? How can I get around this? I've tried adding additional containers to the XML to hold the runtime fragments, but this doesn't seem to work. The only way to get the fragments to show is to remove the containerId from the call to FragmentTransaction.add().
Also, is it possible to change the z-order of fragments manually? I've searched Google quite a lot to find this out and haven't found any answers. I've tried using ViewGroup.bringChildToFront() and using the view returned by the fragment's getView() but this hasn't worked. I've also found out that you can nest fragments on Android 4.2+ with getChildFragmentManager(), but I'm supporting older APIs, and this method doesn't seem to be in the support library.
Any help greatly appreciated!
The way I got around this was to manually recreate the third fragment after the orientation change, and remove the one created by the system.
I have spent the better part of two days searching for an answer that solves my question, I have found plenty that come close but not specific to what I need:
I would like to add a new FragmentActivity to a viewPager from inside a current FragmentActivity by calling the FragmentPageAdapter (or at least, this is how I see I need to solve my problem).
For example: In fragment 1 I would like to press a button to update and replace Fragment 2 with new data, and then set Fragment 2 as the currently viewed fragment.
What you could do is implementing a custom FragmentPagerAdapter or FragmentStatePagerAdapter (If you have lots of more complex fragments).
Documentation: http://developer.android.com/reference/android/support/v4/app/FragmentPagerAdapter.html
The Adapter handles your contents so whatever calls or operations you wanna make on a certain fragment could be done quite easy from there.
You could pass the adapter itself to every fragment that its holding or just implement listener interfaces so that the fragments can trigger the changes through the adapter.
I hope this helps you out if its still an issue!
I'm looking at some demo code that shows how to use a Fragment Adapter (Tab Adapter in this case). I'm curious as to what exactly the instantiate() method does. I see it used in the following demo code on this page:
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
(see the getItem() method within the TabsAdapter class)
If I'm reading the demo code correctly, every time a user clicks on one of the tabs, a new Fragment is created? And thus the fragment starts the entire life-cycle again (onAttach()...onCreate()... etc)? This sounds awfully inefficient. I would think that the fragment that will represent the content for each tab should be instantiated only once (perhaps in the addTab() method), and then saved into some collection where it can be fetched when getItem() is called.
Please correct me if I'm mistaken in any of this. I'm trying to better understand how to manage fragments.
My money would be on that the setCurrentItem() function doesn't actually destroy the existing Fragment being shown in that tab. Otherwise there's really not much of a reason for the adapter to have a List of available tabs. Likely, when you switch from one tab to another, setCurrentItem() just detaches the UI from the currently active Fragment (or calls its onPause() method) and then re-attaches the UI for the newly selected Fragment (or calls its onResume() method).
But, if you're in doubt, you could read the source :)
Hope it helps,
David
I was able to find an explanation for my question here