I have an activity with two fragments, one to display a list and one to show the details of the clicked item. When starting the app the detail part is something static, once I click an item it should get replaced. The problem is that the old fragment is not being replaced, so both views are on top of each other.
My activity layout is:
<?xml version="1.0" encoding="utf-8"?>
<fragment
android:id="#+id/listFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.fragments.FragmentOrderList" >
</fragment>
<fragment
android:id="#+id/detailFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
class="com.fragments.FragmentOrderDetails" >
</fragment>
The layout for the detail fragment is:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:id="#+id/tvOrderDetail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="test view of details fragment" >
</TextView>
And in the above layout we see as well the static text we see initially. The code in my activity to replace the fragment is this
FragmentTransaction transaction = getFragmentManager().beginTransaction();
FragmentOrderDetails newFragment = new FragmentOrderDetails();
newFragment.setArguments(b);
transaction.replace(R.id.detailFragment, newFragment);
transaction.addToBackStack(null);
transaction.commit();
To me it looks like it is not a "replace" but rather an "add". Do I have to remove the old fragment always? Or do I have to follow a different approach here? It seems to me that only the original fragment stays there and on the second, third, ... replace the previous fragment is replaced correctly, just the static one stays there at all times.
Instead of using in layout xml fragment:
<fragment
android:id="#+id/detailFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
class="com.fragments.FragmentOrderDetails" >
</fragment>
Use some container like LinearLayout or FrameLayout with some containerId.
Then programatically firstly add fragment to this container using containerId, and after that replace content of this container with containerId also.
Related
I want to make something like this (photos). When a button is pressed (in this app the red button that says "suchen") a fragment in a portion of the main activity screen is shown. And every time I press an other button, the corresponding activity is shown in the same activity.
So when each
button is pressed you can see the corresponding fragment for this button in the portion of the screen where the layout for the fragment is. I did it like this:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/first_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/second_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/third_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="#+id/forth_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Relativelayout
android:layout_below="#id/first_btn"
android:id="#+id/first_fragment_container"
android:layout_width="300dp"
android:layout_height="250dp">
<fragment
android:id="#+id/fragment1"
android:name="com.example.ulrich.kitchentimer.fragments.FirstFragmentActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/first_fragment_activity" />
</Relativelayout>
<Relativelayout
android:layout_below="#id/first_btn"
android:id="#+id/second_fragment_container"
android:layout_width="300dp"
android:layout_height="250dp">
<fragment
android:id="#+id/fragment2"
android:name="com.example.fragments.SecondFragmentActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/second_fragment_activity" />
</Relativelayout>
<Relativelayout
android:layout_below="#id/first_btn"
android:id="#+id/third_fragment_container"
android:layout_width="300dp"
android:layout_height="250dp">
<fragment
android:id="#+id/fragment3"
android:name="com.example.fragments.ThirdFragmentActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/third_fragment_activity" />
</Relativelayout>
<Relativelayout
android:layout_below="#id/first_btn"
android:id="#+id/forth_fragment_container"
android:layout_width="300dp"
android:layout_height="250dp">
<fragment
android:id="#+id/fragment4"
android:name="com.example.fragments.ForthFragmentActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/forth_fragment_activity" />
</Relativelayout>
</LinearLayout>
As you can see in my code I use four buttons and every button opens an other fragment but at the same place on the main activity. So I have four layouts to contain each of the four fragments. I set each layout to be invisible in the XML code and when each button is pressed to open the corresponding fragment I set the layout to be visible in the Java code. So I have four layout containers in the main activity that are hidden and only shown when the corresponding button is pressed. Is this the right way? Is there a right way?
Thank you in advanced!!!
That's the one way you did to achieve your goal, but that's not the good way. You don't have to make four fragment instead you can have one fragment and replace it when you press the other button. If you want to replace fragments
// Create fragment and give it an argument specifying the article it should show
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Note: When you remove or replace a fragment and add the transaction to the back stack, the fragment that is removed is stopped (not destroyed). If the user navigates back to restore the fragment, it restarts. If you do not add the transaction to the back stack, then the fragment is destroyed when removed or replaced. To allow the user to navigate backward through the fragment transactions, you must call addToBackStack() before you commit the FragmentTransaction.
I am new to android and i have some questions. I created a simple layout with two fragments such as follow:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/fragment1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="#+id/fragment2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
I want to divide this layout as follow :
layout_height of fragment1 : 1/3 height
layout_height of fragment2 : 2/3 height
How can do it?
I used below code to show fragment1 :
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment1, firstfragment);
But I don't know how to show FragmentActivity in fragment2 ?
You can achive this layout like this
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="3"
>
<FrameLayout
android:id="#+id/fragment1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/fragment2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2" />
</LinearLayout>
and in java you must call commit in transaction
//to add Fragment1
FragmentTransaction transaction =
getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment1, firstfragment).commit();
// to add Fragment2
FragmentTransaction transaction1 =
getSupportFragmentManager().beginTransaction();
transaction1.add(R.id.fragment2, secondfragment).commit;
and you can not put any activity inside Fragments. but you can start another activity from your fragments
To put two elements in some ratio - use LinearLayout then set height of contained views to 0dp and add layoutWeight attributes in desired ratio (for example 1 and 2 in your case)
To instantiate fragments just use code as you written twice. You omitted the transaction.commit(); part. You have to cal this twice - once for every fragment you want to add.
Question about adding FragmentActivity is misleading - you can't put Activity into Fragment, you only can insert Fragment(s) into Activities.
i want to separate my layout in two parts:
the bottom for ads, and the other part to the app(few activities).
why i want to do that? because i want the ad appears every time even when new activity started.
http://i.stack.imgur.com/plVeO.png
i realized that is possible to do that with fragment.
I have few questions about fragment:
fragment can hold two activities?
can i start a fragment like activity with intent?
The main question is how TO SEPARATE THE LAYOUT IN TO PARTS while using fragment?
No, fragment can not have two Activities, but vise versa - yes. For dynamic actions with fragments create xml file in which will 2 frames, one attached to the bottom, and read about http://developer.android.com/guide/components/fragments.html, http://developer.android.com/reference/android/app/FragmentManager.html, http://developer.android.com/reference/android/app/FragmentTransaction.html
Try this:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/frame1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
</FrameLayout>
<FrameLayout
android:id="#+id/frame2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="3" >
</FrameLayout>
</LinearLayout>
in Activity:
NewFragment fragment = new NewFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.frame1, fragment);
ft.commit();
Or, static in xml:
<LinearLayout
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" />
<fragment android:name="com.example.android.fragments.ArticleFragment"
android:id="#+id/article_fragment"
android:layout_weight="3"
android:layout_width="0dp"
android:layout_height="match_parent" />
</LinearLayout>
you could make one parent activity which will hold adverts and have free space for content, than you inherit that activity and fill up content from inherited one, maybe inflate other layouts in base. if you will be using more than one layout for content you could make also parent layout and "inherit" it as well.
or you can use one activity which would hold adverts and use fragments for content.
OK, I'm trying to create a universal app that shows 3 tabs in phone view and 3 columns in tablet landscape. As such I created several different XML layouts using Linear Layout.
However, using fragments, I came across a problem - I want to remove the leftmost column when a selection is made in that fragment. I believed I could do this but it turns out I can't remove fragments declared in XML. So now, I'm tring to create the middle and right columns in XML:
<?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:id="#+id/menu_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<fragment
android:id="#+id/classification_fragment"
android:name="uk.colessoft.android.hilllist.fragments.MenuClassificationFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="#layout/list_classifications" >
</fragment>
<fragment
android:id="#+id/map"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>
Then add the first column using
FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MenuCountryFragment countryFragment=new MenuCountryFragment();
fragmentTransaction.add(R.id.menu_layout, countryFragment, "country_menu").commit();
but I have two problems:
a) The above code only puts the fragment at the right hand side of the Linear Layout and I can't specifiy position. It needs to be on the left.
b) XML gave me the freedom to define different weights for the fragment based on screen size/orientation. Setting layout parameters programmatically in the Fragments seems a backward step. I got round this by putting a placeholder view in the xml that I read the layout params from this and assign them in onCreateView but its a hack.
I know I can put the fragment in the correct place by adding it as a child of the first element in the xml but when I do this and remove the fragment it leaves a blank space.
Create a placeholder for the new fragment you want to add (in your XML), something like this...
<?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:id="#+id/menu_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+android:id/realtabcontent"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<fragment
android:id="#+id/classification_fragment"
android:name="uk.colessoft.android.hilllist.fragments.MenuClassificationFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="#layout/list_classifications" >
</fragment>
<fragment
android:id="#+id/map"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
class="com.google.android.gms.maps.SupportMapFragment" />
</LinearLayout>
Then, instead of adding a new fragment at runtime, replace the content of the empty container...
FragmentManager fragmentManager = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MenuCountryFragment countryFragment=new MenuCountryFragment();
fragmentTransaction.replace(R.id.realtabcontent, newFrag).commit();
fragmentManager.executePendingTransactions();
Hope this helps.
I'm trying to replace a fragment in a composite layout. Here's my root layout XML:
<?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
android:id="#+id/buttons"
android:name="com.kippygo.android.touch_talker.ButtonsFragment"
android:layout_width="200dp"
android:layout_height="match_parent"
class="com.kippygo.android.touch_talker.ButtonsFragment" >
<!-- Preview: layout=#layout/buttons_fragment -->
</fragment>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/buffer"
android:name="com.kippygo.android.touch_talker.BufferFragment"
android:layout_width="match_parent"
android:layout_height="80dp" >
<!-- Preview: layout=#layout/buffer_fragment -->
</fragment>
<FrameLayout
android:id="#+id/grid_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/detailsElementBackground" >
</FrameLayout>
</LinearLayout>
</LinearLayout>
As you can see, I have three areas in my layout, a fixed left column containing a fragment with buttons the rest of the layout is divided vertically with a fragment managing a textView at the top and a grid of data in the lower section.
I want to use a common layout to place various GridView elements in the "grid_frame" as I press buttons in the "buttons" fragment. Here is the "grid_fragment" layout that I want to use for each GridView fragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/grid_fragment_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical">
<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="80dp"
android:clipToPadding="true"
android:gravity="center"
android:horizontalSpacing="20dp"
android:numColumns="auto_fit"
android:orientation="vertical"
android:stretchMode="columnWidth"
android:verticalSpacing="20dp" >
<!-- Preview: listitem=#android:layout/simple_list_item_2 -->
</GridView>
<TextView
android:id="#+id/android:empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="22sp"
android:textStyle="bold"
android:text="#string/no_list_items"/>
</LinearLayout>
This composite layout opens up fine when I start my app. and I set my first fragment in the FrameLayout id "grid_frame" in my initial activity with the following code:
// Execute a transaction to put the categoriesFragment in the grid_view
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.grid_frame, new CategoriesFragment(), "category_fragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
This works perfectly fine and I see my buttons on the left, text input box on top and a grid of nicely filled cells to the right of the buttons.
When I click one of the list items in the GridView presented by the dynamic fragment I want to replace the fragment in the "grid_frame" FrameLayout. I do this with the following code in the onItemClick listener method of the "grid_frame" fragment with the following code:
// Execute a transaction to put the categoriesFragment in the grid_view
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.grid_frame, categoryWordsFragment, "category_words_fragment");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
Which looks remarkably similar to the code I used in the activity to set the initial fragment which worked fine.
When I do this my entire screen is replaced with the new fragment layout, which is another GridView with different data. My root layout appears to be totally replaced with the layout that was inflated by the new fragment even though I specify the "grid_frame" FrameLayout as the container view id in the replace method call.
I have tried everything I can find to make my layout stay intact and just change the fragment in the FrameLayout container.
What am I doing wrong please?
Problem solved! It was a very stupid mistake. I had converted my Activity classes to Fragment classes and in this one class I had forgotten to remove the call to setContentView in the class onCreate method. So the fragment was setting a new layout each time I created a new instance