In my android app, I have defined a fragment in my xml layout. The code is below:
<fragment
android:id="#+id/list_fragment"
android:layout_width="220dp"
android:layout_height="fill_parent"
android:layout_marginLeft="62dp"
android:layout_marginTop="20dp"
class="com.example.shantaportfolio.ListFragment" />
But I need to change the class attribute of the fragment from my java code. How can I do it? which method use?
You need to change <fragment/> by <FrameLayout/> in your .xml file
<fragment
android:id="#+id/list_fragment"
android:layout_width="220dp"
android:layout_height="fill_parent"
android:layout_marginLeft="62dp"
android:layout_marginTop="20dp"
/>
and then use java code to add fragment programatically
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
ListFragment fragment = new ListFragment();
fragmentTransaction.replace(R.id.list_fragment, fragment);
fragmentTransaction.commit();
you can get more details from
http://developer.android.com/guide/topics/fundamentals/fragments.html
If you just want to replace a Fragment implementation in the layout insert a "container element" into your layout and set the Fragment there:
in the layout:
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp">
</FrameLayout>
In the code:
final FragmentTransaction tx = this.getFragmentManager().beginTransaction();
tx.replace(R.id.fragment_container, aFragment);
tx.commit();
You cannot intercept LayoutInflator instantiating the declared fragment. But You can replace() any fragment in your Activity with another afterwards.
Update:
You can use an Implementation of LayoutInflator.Factory, and use its onCreateView() method to do something different for some particular tags in layout.
You provide this factory implementation to LayoutInflator using setFactory()
You cannot alter Fragments which are declared in XML. Instead, declare a container where a fragment will belong and in the onCreate() method of your activity, attach a Fragment to this container. When you want to swap Fragments, simply use the replace method and specify which fragment you want to swap.Note: containers are usually made with a LinearLayout by arranging them to the specific size. Below is a simple XML layout which provides a layout on the left which is 2/3 the screen size and another on the right which is 1/3
<?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:baselineAligned="false"
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/fragment_container_parent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
<LinearLayout
android:id="#+id/fragment_container_child"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
Related
Is it legal to use a static fragment inside another fragment.
I just want to reuse an old fragment and add some design to it.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000" >
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="com.example.android.camera2video.Camera2VideoFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/camera_fragment">
</fragment>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello from another fragment"
android:layout_centerInParent="true"
android:textColor="#ffffff"
android:textSize="18sp"/>
</RelativeLayout>
You shouldn't do this. It is explicitly called out as something that won't work in the documentation about nested Fragments:
Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>. Nested fragments are only supported when added to a fragment dynamically.
See https://developer.android.com/about/versions/android-4.2.html#NestedFragments
Create a container to hold that Fragment instead and add it programmatically using the parent Frament's FragmentManager returned by getChildFragmentManager.
Yes, that's fine. Now doing a transaction and replacing a nested fragment has some issues.
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 have this view:
<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"
android:background="#color/DeepSkyBlue"
tools:context=".MainPreviewActivity"
android:weightSum="5">
<fragment
android:name="com.apps.foo.bar.CleanPreviewFragment"
android:id="#+id/clean_preview_fragment"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent"/>
<fragment
android:name="com.apps.foo.bar.ProcessedPreviewFragment"
android:id="#+id/processed_preview_fragment"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent"/>
<View
android:id="#+id/center_dummy_view"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_width="match_parent"/>
<ListView
android:layout_height="0dp"
android:layout_weight="2"
android:layout_width="match_parent"
android:id="#+id/lvImageProcessChoices"/>
</LinearLayout>
I want fragment with id clean_preview_fragment to be replaced with fragment with id processed_preview_fragment.
My app needs to have a camera running in the background so it gets the frames, processes them and displays them in the processed_preview_fragment.
Here is my code:
processedPreviewFragment = (ProcessedPreviewFragment) fragmentManager.findFragmentById(R.id.processed_preview_fragment);
if(getResources().getConfiguration().orientation == getResources().getConfiguration().ORIENTATION_PORTRAIT){
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.clean_preview_fragment, processedPreviewFragment);
fragmentTransaction.commit();
}
That is in my MainActivity, onCreate.
I get this error:
java.lang.IllegalStateException: Can't change container ID of fragment ProcessedPreviewFragment{41b14770 #1 id=0x7f0e0050}: was 2131624016 now 2131624015
You cannot replace a fragment that was declared via XML. If you want to add fragment to container in runtime, you should use FragmentManager to add it. In this case container should be some layout, e.g. FrameLayout.
So, replace your <fragment> tag in XML with <FrameLayout> and add CleanPreviewFragment there in runtime. Then, when you need to replace it, use FragmentTransaction like you do it now. You shouldn't get that exception anymore.
I've viewpager with 5 fragments, in one of them I want to completely replace it by button click. I also want to be able to hide child fragment by back button.
Here this fragment layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/contacts_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#null">
<LinearLayout
android:id="#+id/import_contacts"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<include layout="#layout/listview_filter"/>
<Button
android:id="#+id/btn_my_clusters"
android:background="#drawable/btn_wide_arrow_bg"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="#color/TEXT"
android:text="#string/btn_my_clusters_text"
android:layout_marginBottom="10dp"/>
<ProgressBar
android:id="#+id/progress_bar"
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:layout_gravity="center"/>
<ListView
android:id="#+id/contacts_list"
android:divider="#null"
android:listSelector="#android:color/transparent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone"/>
</LinearLayout>
When I try replace contacts_layout like this:
ImportContactsFragment importContactsFragment = new ImportContactsFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.contacts_layout, importContactsFragment).commit();
it doesn't work (I mean there is no error, but my ImportContactsFragment not showing at all). But when I try replace import_contacts view like this:
ImportContactsFragment importContactsFragment = new ImportContactsFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.import_contacts, importContactsFragment).commit();
everything is ok, ImportContactsFragment shown.
So I wonder is it possible to replace all fragment content by child fragment? Maybe I can do it in some other way?
The replace transaction doesn't remove the current views from the target layout container so when you use the first pice of code the new Fragment is added to the contacts_layout LinearLayout but it will not be seen as the previous views cover the entire screen(height).
With the second piece of code the LinearLayout to which you add the new Fragment is the first child of the parent LinearLayout and it has space so its visible.
For what you're doing I advise you to wrap the initial layout in a Fragment class placed in a wrapper layout which you could then later replace very easy.
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.