When the user clicks an element in a ListView in one fragment, the listener is notified through an interface and it should change the fragment next to the menu.
My current code looks like this
Fragment f = null;
switch(fragmentId) {
case 0:
f = new xFragment();
break;
case 1:
f = new yFragment();
break;
...
}
System.out.println(f.getClass().getName()); // Prints the name of the class correctly
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragmentContainer, f);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
transaction.commit();
When I select some option from the menu, this function in the activity that contains the fragment is called. It correctly prints the fragmentId and the name of the class is correct as told in the code sample.
However, the fragment isn't changed. I tried to replace the f variable in the replace method by new xFragment() but it didn't help.
The XML layout file looks this.
<?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" >
<fragment
android:id="#+id/menuFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:name="fi.peltoset.mikko.home.Navigation" />
<LinearLayout
android:id="#+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
The LinearLayout fragmentContainer is the container for the fragments.
At startup I use the same code I showed above except I changed replace to add to add the right fragment when the application starts. This works fine.
What's wrong?
Are you attempting to replace the fragment whose ID is 'menuFragment'? If so then you cannot do this as any fragment specified in the XML layout cannot be replaced.
Can you try to replace the LinearLayout by FrameLayout?
please refer to https://groups.google.com/forum/#!topic/android-developers/gAhaoLlBob4 even though nobody explain why.
What version of Android are you targeting?
Try using the support fragment manager:
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
http://developer.android.com/reference/android/support/v4/app/FragmentActivity.html#getSupportFragmentManager()
First of all, "fragmentContainer" is not a fragment itself. Also, you can't replace static fragments with each other. They must be "dynamically added" fragments. Take a look at this post
To replace dynamically created fragments, take a look at this post.
Related
First le me start by stating I am fairly new to Java and Android Studio, so please bear with me. my background has been in Visual Basic going way back.
I have an activity that tries to verify that what was entered is a valid Item Number by UPC entered. When only one match all is good. My problem starts when the UPC entered brings back more than one matching item. What I am attempting to do (First time using fragments) is Replace part of the screen with a recycler view showing the matching items and descriptions.
When comes backs with multiple items I call an event called setupMulitpleItems with the following code:
public void setupMultiItems(String mScan){
Timber.d("Multiple matching Items");
Bundle bundle = new Bundle();
bundle.putString("valuesArray",mScan);
SelectItemFragment fragobj = new SelectItemFragment();
fragobj.setArguments(bundle);
FragmentManager fragmentManager=getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.include2, fragobj);
fragmentTransaction.commit();
Not sure how many parts of this code will actually work but I am getting underline on the replace line.
"'replace(int, android.app.Fragment)' in 'android.app.FragmentTransaction' cannot be applied to '(int, com.procatdt.stockright.activities.SelectItemFragment)'"
meesage.
I am using the following imports for Fragments.
import android.app.FragmentTransaction;
import android.app.Fragment;
import android.app.FragmentManager;
Figured I would also include the XML for the activity that is currently running when I want to use Fragment.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorBackgroundGray"
tools:layout="#layout/fragment_select_item"
tools:context="com.procatdt.stockright.activities.PutAwayAreaActivity">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<include
android:id="#+id/include2"
layout="#layout/frm1"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="left" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:paddingLeft="5dp"
android:orientation="vertical">
<include
android:id="#+id/include"
layout="#layout/layout_numpad5"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="220dp"
android:layout_weight="1"
android:layout_gravity="right"
/>
</LinearLayout>
</RelativeLayout>
I am trying to replace include2 with Fragment.
Hope this enough info but if anyone needs to see more let me know and I ill attach code.
You just need to pass the object of your fragment to replace method, there is no need to pass the class declaration and type of class
so just remove
// this is enough
fragmentTransaction.replace(R.id.include2, fragobj);
// remove this
//fragmentTransaction.replace(R.id.include2,android.app.Fragment SelectItemFragment);
I have a fragment (fragment_1) which gets displayed when the main activity starts and displays a full screen layout (layout_1). Now i have added a button, clicking on which will start a new fragment (fragment_2)and replace the entire layout (layout_1) with my new layout (layout_2).
My first fragment (fragment_1) has a ScrollView as my root view.
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#fff"
android:scrollbarSize="0dp"
android:id="#+id/scroll_main"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
....
</RelativeLayout>
</ScrollView>
Now i want to start a new fragment (fragment_2) on a button click and display another layout (layout_2) but i don't know how to do that.
My main activity had a frame layout like this
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/root_container">
And i used to set this as my default layout using
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
After this i start my first fragment and display the layout_1.
Now from fragment_1 i want to start fragment_2 and display the layout_2. I have read online articles and documentation where i can't find and solution regarding this. Pleas Note :" I don't want to simply replace a part of my layout_1 and replace it with my layout_2 rather i want my layout_1 totally gets replaced with layout_2 on a button click"
Replacing fragments seems like a job for the fragment manager.
This answer might help you Replacing a fragment with another fragment inside activity group
The Android developer documentation for fragments says this:
"Note: When you add a fragment to an activity layout by defining the
fragment in the layout XML file, you cannot remove the fragment at
runtime. If you plan to swap your fragments in and out during user
interaction, you must add the fragment to the activity when the
activity first starts, as shown in the next lesson."
And partly because of this I got into the habit of always using the fragment manager to add/remove fragments to/from my user interface (even if I did not want to "hot swap" them at runtime). I am 100% certain that when I tried to remove/replace "hard wired" XML fragments at runtime my app crashed with an exception.
I haven't really worked with XML fragments for months, but today, on a lark, I decided to play around and I find that I am able to swap XML fragments for other fragments and...it works? I can't find anything online that discusses a recent change in this behavior. It just works.
My layout code is here:
<?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/fl_frag"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="mobappdev.demo.myapplication.MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/frag"
android:name="mobappdev.demo.myapplication.BlankFragment"/>
<Button
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="#string/click_me"
android:onClick="clickMe"/>
</LinearLayout>
And here is the code that replaces the fragment:
public void clickMe(View view) {
FragmentManager manager = getSupportFragmentManager();
BlankFragment newFrag = BlankFragment.newInstance();
Fragment oldFrag = manager.findFragmentById(R.id.frag);
Log.i("TESTING", "old frag is null: " + (oldFrag == null));
manager.beginTransaction()
.replace(R.id.fl_frag, newFrag)
.commit();
}
It works without any problems. I've tried variations (putting the XML fragment in a FrameLayout for example) and it all seems to work just fine. I even tried variations such as remove/add and just remove and it all works without a problem.
So what am I missing?
Instead of replacing the fragment itself, you're adding a new fragment on top of that one. It's just a small issue with IDs, but you're replacing using the FragmentManager on the container (LinearLayout) instead of doing it on the fragment itself (R.id.fl_frag instead of R.id.frag)
My school assignment has an activity that contains a ListFragment and a Fragment. The MainActivity creates the ListFragment, and then each item on the list should open the regular Fragment that just contains a picture, and then when I click on the picture it should go back to the ListFragment.
In all cases, I call the fragments using this code (edited for the specific case of course):
Fragment fragTwo = new FragmentTwo();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_place, fragTwo);
ft.addToBackStack(null);
ft.commit();
It calls the fragments OK, except that the second fragment will appear OVER the ListFragment, and I can still select things from the list while the second fragment is open. Do I need to create a new fragment object every time I navigate? And how do I disable/enable a fragment from it's own onclick listener?
main_activity.xml:
<?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" >
<fragment
android:name="com.example.w0068332.fragmentstest.FragmentOne"
android:id="#+id/fragment_place"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
1- Yes you need to create a fragment for each item.
Bundle arguments = new Bundle();
arguments.putInt(FragmentTwo.ARG_ITEM_ID,R.drawable_pic);
FragmentTwo fragment = new FragmentTwo();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment)
.commit();
I suppose that you display pictures from resources
2- To disable selection from ListFragment while displaying the second one.
In the parent layout of the second fragment you have to add background and make it clickable as below:
android:background="#color/white"
android:clickable="true"
3- To navigate back for the ListFragment add a click listener for the ImageView and onClick call onBackPressed of the Activity:
getActivity().onBackPressed();
you can also have a look on a template from Android studio for Master and details activity
at the moment I'm calling and building fragments like this:
if (getSupportFragmentManager().findFragmentById(R.id.fragment_list) == null) {
list = new MyListFragment();
getSupportFragmentManager().beginTransaction().add(R.id.fragment_list, list).commit();
}
But I wonder if this is so called best practice, because this seems to me to be much boilerplate code. Are there better ways?
Use XML layouts and Fragment classes. Here I create a layout with 2 fragments. The class inflates the layout fragment_actionbarcompat.xml (that code isn't shown here but it's a basic layout file). And I create a layout file for the activity that houses the 2 fragments.
The ActionBarCompatFragment class overrides the onCreateView method to inflate it's layout. That gets injected into the fragment tag layoutwise.
In your case normally you don't just add in a plain ListFragment, you extend ListFragment and add your custom code into it. It's a way of better supporting fancy patterns like Model-View-Controller. Fragments are meant to be isolated compartments so you can reuse them between activities if you'd like. In most cases your class will hold the logic to load the data that the fragment needs.
ActionBarCompatFragment.java
#Override
public final View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedInstanceState) {
final int layoutId = R.layout.fragment_actionbarcompat;
return inflater.inflate(layoutId, root, false);
}
File: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment
android:id="#+id/ActionBarCompatFragment"
android:layout_width="#dimen/ActionBarSize"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
class="com.packagename.app.ActionBarCompatFragment" >
<!-- Preview: layout=#layout/fragment_actionbarcompat -->
</fragment>
<fragment
android:id="#+id/ComposerFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_toRightOf="#id/ActionBarCompatFragment"
class="com.packagename.app.ComposerFragment" >
<!-- Preview: layout=#layout/fragment_composer -->
</fragment>
</RelativeLayout>