Let's say I have 2 fragments, one contain a list view and another contain a loading text. I want when I click on one list item, the loading text fragment appears on top of the list view. I have adjusted the opacity of the loading text background to: android:background="#33FFFFFF" . But still it just shows the loading text on a solid grey background.
<?xml version="1.0" encoding="utf-8"?>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#android:id/list"
android:background="#e8e9ee"
android:divider="#ccc"
android:dividerHeight="1dp"/>
Fragment that contains a textview:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="#string/loadingText"
android:id="#+id/loadingText"
android:textColor="#e8e9ee"
android:background="#33FFFFFF"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true" />
My java code is basically something like this: onItemClick:
FragmentTransaction transaction=manager.beginTransaction();
transaction.show(loadingFragment);
transaction.commit();
I did it and it works perfectly but instead of using .show I used .add:
Activity layout:
<RelativeLayout
android:id="#+id/layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginRight="5dp"
android:layout_marginEnd="5dp">
<FrameLayout
android:id="#+id/list_view_container"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">
</FrameLayout>
<FrameLayout
android:id="#+id/loading_text_fragment_container"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true">
</FrameLayout>
</RelativeLayout>
In the Activity:
First add your List View:
ListViewFragment listViewFragment = new ListViewFragment();
fragmentManager.beginTransaction().add(R.id.list_view_container, listViewFragment).commit();
Then the loading text:
// Create a new Fragment to be placed in the activity layout
YourFragment yourFragment = new YourFragment();
// Add the fragment to the 'loading_text_fragment_container' FrameLayout
fragmentManager.beginTransaction().add(R.id.loading_text_fragment_container, yourFragment).commit();
In YourFragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.your_fragment_layout, container, false);
}
And the your_fragment_layout.xml has a common TextView without any special attribute.
Hope it to be useful,
regards!
I think you are actually replacing the original fragment rather than overlaying it. You should create two framelayouts that cover the full screen and then assign the loading fragment to the overlaying frame layout
in you activity
<FrameLayout id="#+id/ListFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<FrameLayout id="#+id/LoadingFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
and then to load them
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.ListFragment, listFragment);
transaction.commit();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(R.id.LoadingFragment, loadingFragment);
transaction.commit();
Related
i'm trying to do a three page which contains list fragment in an activity. All of the pages are fragment(from v4 support library) but i need list fragment inside them. When i tried that i have encountered a problem(https://stackoverflow.com/questions/29473626/viewpager-gives-error-if-i-turn-page) then i have done some research and learned that there can not be fragment(i mean xml fragment tag not adding dynamically nested fragment) in fragment. But for instance, in the last android update of whatsapp there are three page in one activity and one of them has list fragment(chat list) so i wonder how whatsapp have done that? Thanks.
my xml layout which contains list fragment:
<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/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="17dp"
android:text="Welcome to newsfeed" />
<Button
android:id="#+id/nfButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="52dp"
android:text="#string/signout" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="vertical" >
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/nfListFragment"
android:name="com.comp.buzz.newsfeed.NFQuestionFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
tools:layout="#layout/item_question" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
onCreativeView method of main fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_newsfeed, container, false);
Fragment fragment = new ListFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.swipe_container, fragment).commit();
return view;
}
You can nest fragments with a few restrictions (according to the doc):
Android 4.2 or higher
You can nest them only programmatically
Update 1
Something like this should do the job:
Fragment fragment = new YourFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.swipe_container, fragment).commit();
I have a tab that contains a linear layout with a searchview and a listview. When the user clicks one of the search results, I want to replace that layout with another layout containing the details of the selection.
What happens when I replace the search fragment only the listview portion of the layout gets replaced; the searchview is still visible and active on the screen.
Here is my search layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/search_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<SearchView
android:id="#+id/public_calendar_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:iconifiedByDefault="false"
</SearchView>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:choiceMode="singleChoice" />
<TextView
android:id="#android:id/empty"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:gravity="center"/>
</LinearLayout>
Here is the detail layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/detail_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="vertical" >
<Space
android:layout_width="0dip"
android:layout_height="20dip"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:orientation="horizontal" >
<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".1" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".8"
android:text="#string/label_Name" />
<Space
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".1" />
</LinearLayout>
.........
</LinearLayout>
And my code to replace the search fragment:
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack.
DetailFragment fragment = DetailFragment.newInstance(cal);
transaction.replace(R.id.search_layout, fragment);
transaction.addToBackStack(null);
transaction.commit();
Detail fragment creation:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.detail_layout, container, false);
return v;
}
static DetailFragment newInstance(String cal) {
DetailFragment d = new DetailFragment();
return d;
}
What am I doing wrong? How can I get the entire search layout to be replaced.
Thanks!
I figured out my problem. Marco wasn't exactly right but he pointed me in the right direction.
The problem was the the container ID I was passing to the replace method was the ID of the fragment I was replacing, not the ID of the fragment container. This seems to explain why some of the original fragment controls were remaining after the replace - that entire fragment wasn't being replaced.
I changed it to get the fragment container view ID, and that worked! Here's the code:
transaction.replace(((ViewGroup)(getView().getParent())).getId(), fragment);
I found the answer for getting the container view ID of a fragment here, Get fragment's container view id.
I was using the correct ID, then also it wasnt going away. Turns out that you need to set the Background color to your needed color in new Fragment layout, like this.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white_color">
To solve the problem, set the android:background property to “?android:windowBackground” in the fragment layout files.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground"
tools:context=".MainFragment">
...
</LinearLayout>
In Fragment_2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground"
tools:context=".SomeFragment">
...
</LinearLayout>
I was having the same problem, and the solution didn't work for me. Maybe this will help someone...
I had added a fragment inside the activity layout xml file. This caused a lot of issues.
Instead, add a frame layout in your xml file, and then programatically add and replace fragments. This causes the whole fragment to be replaced.
I had the same problem once, and this is my solution.
Try to do this, use FrameLayout instead of fragment in your layout file. Just like this:
<fragment android:id="#+id/your_fragment" />
Then, add your default fragment in activity method onCreate().
getFragmentManager().beginTransaction()
.add(R.id.your_fragment, YourFragment)
.commit();
Now, the old fragment can be replaced correctly, it looks great.
This worked for me, and I hope it helps you too.
I am trying to create an activity with 2 Fragment
First fragment show a list of galleries using a LisFragment
Second fragment show the preview images of the gallery selected in the first fragment
When I declare the fragment in the view it works. But now I want to manage fragment dynamically :
GalleriesFragment gfs = new GalleriesFragment();
GalleryFragment gf = new GalleryFragment();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.layout_m,gfs);
ft.add(R.id.layout_m,gf);
ft.commit();
My 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"
android:id="#+id/layout_m">
</LinearLayout>
When doing this only the first fragment added is shown, I tried to invert their order when adding fragment...
When I was working on the layout I could set my fragment width with:
android:layout_width="400dp"
Now I have 2 questions :
How can I make my 2 fragments to display?
How can I set the width (programmatically?) of the 1st fragment and the second to fill the remaining width?
Thanks for your help!
PS:
GalleriesFragment doesn't have a layout and is not overriding onCreateView, but has an ArrayAdapter returning view like this for each rows:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="#+id/idimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10sp"
android:layout_marginLeft="10sp"
android:layout_marginTop="10sp"
android:contentDescription="preview"
>
</ImageView>
<LinearLayout
android:id="#+id/LinearLayout01"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/texttitre"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5sp"
android:layout_marginRight="7sp"
android:layout_marginTop="10sp"
android:background="#layout/roundcorner"
android:gravity="center"
android:text="Title here" >
</TextView>
<TextView
android:id="#+id/itemdescription"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10sp"
android:layout_marginRight="10sp"
android:text="description" >
</TextView>
</LinearLayout>
</LinearLayout>
GalleryFragment :
<?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" >
<Gallery
android:id="#+id/gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Update 2 :
I added an onCreateView in my GalleriesFragment class :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FrameLayout.LayoutParams lparams = new FrameLayout.LayoutParams(400, LayoutParams.MATCH_PARENT);
container.setLayoutParams(lparams);
return super.onCreateView(inflater, container, savedInstanceState);
}
This fixes the first fragment's width, but the second one is still not showing...
How can I make my 2 fragments to display ?
Your current approach will make the first fragment supplied to the add method to take all the space of your container layout. One solution is to use a layout that reserves space for each of the two fragments that get added, something like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layout_m"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<FrameLayout
android:id="#+id/frame1"
android:layout_width="100dp"
android:layout_height="match_parent" />
<FrameLayout
android:id="#+id/frame2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Then in code:
ft.add(R.id.frame1, gfs);
ft.add(R.id.frame2, gf);
ft.commit();
How can I set the width (programmatically ?)of the 1st fragment and
the second to fill the remaining width?
Fragments are not just ordinary views but one way to do that is to use your single LinearLayout layout file and set the LayoutParams of the fragment's view in onActivityCreated:
getView().setLayoutParams(new LinearLayout.LayoutParams(100, LinearLayout.LayoutParams.WRAP_CONTENT));
Of course this will make your fragments to be tied to the parent container, also I don't know how well this will work in the overall fragment system.
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
I have a layout of
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="wrap_content" >
<LinearLayout android:id="#+id/linearLayout1" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_width="wrap_content">
<LinearLayout android:id="#+id/linearLayout13" android:layout_height="wrap_content" android:paddingRight="70dp" android:orientation="vertical" android:paddingLeft="70dp" android:layout_width="wrap_content">
<ImageView android:id="#+id/baby_icon" android:layout_height="wrap_content" android:src="#drawable/baby" android:clickable="true" android:layout_width="wrap_content"></ImageView>
</LinearLayout>
</LinearLayout>
<fragment
android:name="com.nicu.health.FragAFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/yellow_cardlist_fragment"
android:layout_weight="1"
>
</fragment>
</LinearLayout>
On the startup this does show the correct fragment(FragAFragment). Now on the button click for baby_icon I try to remove the current fragment and add a new one(FragBFragment) which has an entirely different layout.
Though I see that the onCreateView method is called and it does return a non-null view but the UI on the screen of the new fragment does not get updated. I use the below code to update the fragment.
Fragment baby = FragBFragment.newInstance(1);
FragmentTransaction ft = getFragmentManager().beginTransaction();
// ft.remove(getFragmentManager().findFragmentById(R.id.yellow_cardlist_fragment));
// ft.add(R.id.yellow_cardlist_fragment, baby);
ft.replace(R.id.yellow_cardlist_fragment, baby);
ft.addToBackStack(null);
Log.i(TAG, "Code for commit = "+ft.commit());
I had tried all combinations of remove, replace and add to get the fragment thing workng, but in vain!
Also further I tried with the code as
<fragment
android:name="com.nicu.health.FragBFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/yellow_cardlist_fragment"
android:layout_weight="1"
>
and this does work to show the second fragment on startup!!!!
Help will be reeally appreicated.
Thanks,
Answer to my question is
Android: can't replace one fragment with another
I added dynamic fragments on start of the main activity and onclick I did a ft.replace to replace the old fragment!
Ok, my first guess: You forgot to say ft.commit();
My second guess:
Lets say u have Activity AB which controls Fragment A and Fragment B.
You also have 3 layouts. Layout_ActivityAB, Layout_FragA, Layout_FragB.
So setContentView(R.layout.Layout_ActivityAB) is called inside Activity AB. That will be the layout in which u tell android where to place the fragment in the screen.
Inside Fragment A or Fragment B:
#Override
//onCreateView is called when an instance of this class is first created.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.Layout_FragA, container, false); return rootView;
}
R.layout.Layout_FragA is called inside the Fragment. Layout_FragA is the actual content of the Fragment.