Fragment not loading when clicked from avigation drawer - android

Hi I used android studio wizard to create a drawer activity. Inside MainnActivity I have put this code:
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_movies) {
Fragment newDetail = ListFragment.newInstance(LAUNCH_MOVIES);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, newDetail)
.commit();
} else if (id == R.id.nav_tv) {
Fragment newDetail = ListFragment.newInstance(LAUNCH_TV);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, newDetail)
.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Since I have 2 options I need to launch the same fragment with different arguments, and based on the different arguments the fragment shows different things. But when I click on a navigation drawer item nothing appears on screen nor on the stacktrace.
ListFragment:
public static ListFragment newInstance(int target) {
Bundle args = new Bundle();
args.putInt(ARG_SCOPE, target);
ListFragment fragment = new ListFragment();
fragment.setArguments(args);
return fragment;
}
public ListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scope = getArguments().getInt(ARG_SCOPE);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.content_main, container, false);
switch (scope){
case 1:
//launch Movies
((TextView)rootView.findViewById(R.id.textView)).setText("" + MainActivity.LAUNCH_MOVIES);
break;
case 2:
//Launch tv
((TextView)rootView.findViewById(R.id.textView)).setText("" + MainActivity.LAUNCH_TV);
break;
default:
Log.w(LOG_TAG, "INVALID SCOPE");
}
return rootView;
}
Thank you I am going crazy.
XML files:
activity_main
<android.support.v4.widget.DrawerLayout
...>
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.NavigationView
.../>
</android.support.v4.widget.DrawerLayout>
app_bar_main
<android.support.design.widget.CoordinatorLayout
...>
<android.support.design.widget.AppBarLayout
...>
<android.support.v7.widget.Toolbar
.../>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/container"/>
</android.support.design.widget.CoordinatorLayout>
content_main
<RelativeLayout
...>
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"/>
</RelativeLayout>

Did you try Debuger? You can see code flow using break-points.

I think if you used the Android Studio debugger stepping through line by line you will likely find your problem. Everything seems fine to me but I can't see all the code or XML.
What does MainActivity.LAUNCH_TV and MainActivity.LAUNCH_MOVIES return? They may be returning nothing and leaving you with an empty text view and therefore it may seem like the buttons are not working.
Another problem could be that R.id.nav_movies and R.id.nav_tv are not right but I can't tell as all your XML is not included.
Set the debugger to break on the first line of onNavigationItemSelected and just step one line at a time, the problem should become easier to solve once you know where it is.

Sounds like your navigationView setNavigationItemSelectedListener is not being called. Have you set the listener to your navigationView?
navigationView.setNavigationItemSelectedListener(listener);

I tried your approach.The problem you are facing is replace fragment id.You should use Relativelayout id from content_main.xml file, while replacing the fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit();
Also remove Framelayout from app_bar_main.xml file.

I was able to get it working. Apparenly it was some bug in the way the xml files are organized. The java code was left as it was. Instead in app_bar_main, inside the coordinator layout I put a FrameLayout with id #+id/fragment_container. Also I removed the self-generated <Include content_main.xml> tag.
In the onNavigationItemSelected method I updated every .replace() to target the new FrameLayout like this: .replace(R.id.fragment_container, newDetail).
Then in the fragment's onCreateView i inflated a new layout like this: View rootView = inflater.inflate(R.layout.fragment_list, container, false);, where fragment_list is the layout where I have the recycerView and all of the UI stuff.
The content_main.xml went unused.
I believe the bug was somehow related to the <include> tag and the messy over-complicated way of adding a Drawer. 2/10 never using Drawer again.

Related

FragmentManager replace not working?

I am having a hard time figuring out why my FragmentManager isn't working.
I'm using an Android studio template for nav drawer activity. The most confusing thing is, I have the exact same code in another app and it works just fine.
Here is the code:
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
Fragment fragment = null;
switch (id) {
case R.id.nav_camera:
fragment = new MyFragment();
Log.i("ID", String.valueOf(id));
break;
case R.id.nav_gallery:
break;
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_main, fragment)
.commit();
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Now, when I click on the nav_camera it logs the click just fine, but nothing else happens, the fragment doesn't get replaced. No errors, no exceptions, just the same screen over and over.
Fragment code, nothing here just testing:
public class MyFragment extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_list, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
}
Fragment layout, just a blank:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
The rest of the code is auto generated by andorid studio.
Here is content_main, which I am trying to replace with fm:
<LinearLayout 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:id="#+id/content_main"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.example.goran.mymoviedb.movies.MainActivity"
tools:showIn="#layout/app_bar_main">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
It should replace the layout with a blank one whan nav_camera is clicked but nothing happens, even though correct click is registered.
Actually your code is working but the issue is that you have blank layout and because background of fragment layout is by default transparent you can not see the change. Put background color on your root layout of fragment (LinearLayout) for example: android:background="#android:color/white"
and you will see fragement replacement.

Replaced fragment still visible behind new fragment

I try to implement an activity which can load different fragments into one container view element. I follow the Building a Flexible UI Training. Problem: When replacing a fragment, I can still see the replaced fragment in the background.
I see that my question has already been asked numerous times. However all the answers I found seem to be just a workaround (setting the background-color of fragments) or do not apply.
Here is what I have setup so far:
The activity's XML layout contains one FrameLayout as a container for the fragments:
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
The id fragment_container is used nowhere else in the project.
The complete XML layout of the first fragment:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="First Fragment" />
The complete XML layout of the second fragment:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#ff0000"
android:text="Fragment Second" />
The class file of the first fragment looks like this (class for second fragment analogous):
public class FirstFragment extends Fragment {
public FirstFragment() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_first, container, false);
}
}
In the activity's onCreate method I load the first fragment:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// load first fragment
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new FirstFragment())
.commit();
}
}
When selecting a menu item I try to replace the first fragment with the second fragment with this code in the activity's onOptionsItemSelected method:
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new SecondFragment())
.addToBackStack(null) // <-- does not make any difference if left out
.commit();
The result is that the text "Fragment Second" is printed in red above the text "First Fragment".
What is the "right way" (i.e. not just setting a background-color) to fix this problem?
I noticed this in onCreate:
getSupportFragmentManager()
and this in onOptionsItemSelected:
getFragmentManager()
There are actually both versions of the FragmentManager in AppCompatActivity and they know nothing about each other. So when you tell android.app.FragmentManager to replace a fragment that was added by android.support.v4.app.FragmentManager, it doesn't know anything about a FirstFragment so the operation acts more like an add than a replace.
I've made this mistake more than once. You'll need to comb through your code and make sure you are consistent about using the support class vs. the regular class.

Naviagation Drawer Stuck with Fragments Injection

I am trying to add to the navigation drawer using fragments as follows using the onNavigationDrawerItemSelected But the compiler is giving me a incomparable type I do not no how I am new to Andriod I used the NaviagationDrwaer Template app to give me heads start.
I am hopeing someone can point me in the right direction with this been driving me nuts. Also any ideas with this apporach how one would handle icons in the menu ?.
public void onNavigationDrawerItemSelected(int position) {
Fragment fragment;
switch(position){
case 0:
fragment = new HomeFragment(); --- This line is where the error comes
break;
}
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager()
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
My HomeFragment Class Conists Of
public class HomeFragment extends Fragment {
View rootview;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootview = inflater.inflate(R.layout.home_layout, container, false);
return rootview;
}
}
And my home_layout file as follows
<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" tools:context="com.example.davidbuckley.cautioapp.home">
<!-- TODO: Update blank fragment layout -->
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</RelativeLayout>
One of your fragments is probably a 'support' Fragment: http://developer.android.com/reference/android/support/v4/app/Fragment.html
While the other is probably a native Fragment: http://developer.android.com/reference/android/app/Fragment.html

java.lang.IllegalArgumentException: No view found for id 0x1020002 (android:id/content) for fragment

I am trying to move from one fragment to another.. It shows following error during fragment transaction-
java.lang.IllegalArgumentException: No view found for id 0x1020002 (android:id/content) for fragment PhotosFragment2{41a57218 #3 id=0x1020002}
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:930)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1115)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1478)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:446)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
at dalvik.system.NativeStart.main(Native Method)
Below are the classes.I have used following code for fragment transaction
Fragment fragment = new PhotosFragment2();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
PhotosFragment.java
public class PhotosFragment extends Fragment {
private FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.photos, container, false);
rootView.setVerticalScrollBarEnabled(false);
int[] mThumbIds = {
R.drawable.album8, R.drawable.album3,
R.drawable.album4, R.drawable.album8,
R.drawable.album6, R.drawable.album7,
R.drawable.album12, R.drawable.album10,
};
int[] mThumbIds2 = {
R.drawable.album8, R.drawable.album3,
R.drawable.album4,
R.drawable.album6, R.drawable.album7,
R.drawable.album9, R.drawable.album10,
R.drawable.album11, R.drawable.album12, R.drawable.album8,
R.drawable.album8, R.drawable.album3,
R.drawable.album4,
R.drawable.album6, R.drawable.album7,
R.drawable.album9, R.drawable.album10,
R.drawable.album11, R.drawable.album12, R.drawable.album8,
};
CustomGridSingle2 adapter = new CustomGridSingle2(myContext, mThumbIds);
GridView grid = (GridView)rootView.findViewById(R.id.gridView);
final ImageView img= (ImageView)rootView.findViewById(R.id.imageView7);
grid.setFocusable(false);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fragment fragment = new PhotosFragment2();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
}
});
CustomGridSingle2 adapter2 = new CustomGridSingle2(myContext, mThumbIds2);
GridView grid2 = (GridView)rootView.findViewById(R.id.gridView2);
grid2.setFocusable(false);
grid2.setAdapter(adapter2);
grid2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Fragment fragment = new PhotosFragment2();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
}
});
return rootView;
}
}
PhotosFragment2.java
public class PhotosFragment2 extends Fragment {
private FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext = (FragmentActivity) activity;
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View rootView = inflater.inflate(R.layout.photos2, container, false);
myContext.getActionBar().hide();
return rootView;
}
}
Activity xml file
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="#+id/left_drawer_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#drawable/bgmenu"
android:orientation="vertical">
<RelativeLayout
android:id="#+id/profilelayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0"
android:paddingTop="10dp">
<ImageView
android:id="#+id/drawer_profile_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/drawer_profile_background"
android:layout_alignLeft="#+id/drawer_profile_background"
android:layout_alignRight="#+id/drawer_profile_background"
android:layout_alignTop="#+id/drawer_profile_background"
android:layout_marginBottom="7.667dp"
android:layout_marginLeft="6.5dp"
android:layout_marginRight="8.3dp"
android:layout_marginTop="7.667dp"
android:scaleType="centerCrop"></ImageView>
<ImageView
android:id="#+id/drawer_profile_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:scaleType="centerCrop"
android:src="#drawable/profileblock">
</ImageView>
<ImageView
android:id="#+id/settingicon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/drawer_profile_background"
android:layout_marginLeft="-15dp"
android:layout_toRightOf="#+id/drawer_profile_background"
android:background="#drawable/settings" />
<textview
android:id="#+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/drawer_profile_background"
android:layout_centerHorizontal="true"
android:layout_marginTop="5dp"
android:text="Name"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textColor="#android:color/white" />
</RelativeLayout>
<ListView
android:id="#+id/list_slidermenu"
style="#style/buttonStyle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="30dp"
android:layout_weight="2"
android:cacheColorHint="#android:color/transparent"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="1dp"
android:listSelector="#android:color/transparent"
android:scrollbars="none" />
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
When you use fragmentTransaction.replace(R.id.container,fragment) it will remove any fragments that are already in the container and add your new one to the same container.
Now i can suggest you 2 things.First, if you want to use fragmentTransaction.replace(android.R.id.content, fragment); which you are doing right now,then don't set content for your Activity using setContentView.This should work fine then.To know what exactly android.R.id.content is you can refer this stackoverflow question and answer
Or Secondly, In the layout of your Activity have a FrameLayout whose id is content. And then use
fragmentTransaction.replace(R.id.content, fragment);
fragmentTransaction.addToBackStack(null);//add the transaction to the back stack so the user can navigate back
// Commit the transaction
fragmentTransaction.commit();
Hope this helps.
More Info:
From your comments it seems that you are having some problem in getting the idea of using FrameLayout in your Activity's layout(Not of any of the Fragment's layout).From the Documents
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organize child views in a way that's scalable to different screen sizes without the children overlapping each other.
So the main purpose of FrameLayout is to block the area required to fit the largest child view. If you use a FrameLayout as Fragment Container you can ensure that you always have the space available to accommodate the largest Fragment's layout.
So you can have your FrameLayout something like this in your Activity's layout xml file
<FrameLayout
android:id="#+id/content"
android:layout_height="match_parent"
android:layout_width="match_parent">
<!--you can put your existing views of your current xml here, so yes your entire xml is now inside this FrameLayout -->
</FrameLayout>
I don't use getSupportFragmentManager().
I use getChildFragmentManager() and it worked for me.
You can try it.
If you are trying to put Fragment into Fragment, use getChildFragmentManager()
If you are using ViewPager, use getChildFragmentManager() for pager adapter
viewPager.setAdapter(new ItemsAdapter(getChildFragmentManager()));
You have to set a content view in your Activity that your PhotosFragment is attached.
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_main);
//...
}
i know this is very late. But it may work for other's.
I declared the id for each layout, like (3rd line bellow)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
Since Android 4.2 (API 17) nested fragments become avaliable.
See this
To place fragment inside other fragment use getChildFragmentManager()
Also available in support library.
I had the same error and after trying a lot of things I found that the problem was with the "id" and "getActivity().getSupportFragmentManager()".
Before i implement i like these
txt_more.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getChildFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, new OpportunitiesFragment())
.commit(); }
});
Then i changed to these
txt_more.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
## Heading ##
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(android.R.id.content, new OpportunitiesFragment())
.commit(); }
});
Put this block of code in PhotosFragment2 onCreateView method:
View rootView = inflater.inflate(R.layout.photos2, null);
instead of:
View rootView = inflater.inflate(R.layout.photos2, container, false);
in my case I had to change
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.sample,
container);
to
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.sample,
container, false);
This answer highlights a silly mistake that may occur, that arises when nesting fragments or you are converting activities to fragments.
If you are trying to replace a fragment within a fragment with the fragmentManager but you are not inflating the parent fragment that can cause an issue.
In BaseFragment.java OnCreateView:
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.replace(R.id.container, new DifferentFragment())
.commit();
}
return super.onCreateView(inflater, container, savedInstanceState);
Replace super.onCreateView(inflater, container, savedInstanceState);
with inflating the correct layout for the fragment:
return inflater.inflate(R.layout.base_fragment, container, false);
The problem may be that you add a fragment and beginTransaction in some fragment like
getFragmentManager().beginTransaction().replace(android.R.id.content, ImageBrowseFragment.newInstance(bundle),"ImageBrowseFragment")
.addToBackStack(null).commit();
I just change getFragmentManager() to getActivity().getSupportFragmentManager()
Then everything goes fine
When you add a fragment in a fragment use android.R.id.content Or Window.ID_ANDROID_CONTENT,I guess it represents the root container of your fragment not the activity. So change to getActivity().getSupportFragmentManager() works it out
If you use ViewPager with fragments (pages) and try to show a new fragment from a page, you will get this error. I think, you cannot reference to a container of an Activity from a ViewPager's page.
In this case you should call getActivity(). Then in Activity write a method that will open a new fragment.
class YourActivity : AppCompatActivity() {
fun showNewFragment(title: String) {
val fm = supportFragmentManager
fm?.beginTransaction()?.apply {
val fragment = NewFragment.newInstance(title)
replace(R.id.container, fragment, NewFragment.TAG)
addToBackStack(null)
}?.commit()
}
}
class PageFragment : Fragment() {
private fun show() {
(activity as YourActivity).showNewFragment("New fragment")
}
}
If you call getParentFragment() and add a new fragment, then you will place a new fragment inside ViewPager:
class ViewPagerFragment : Fragment() {
fun showNewFragment(title: String) {
val fm = childFragmentManager
fm?.beginTransaction()?.apply {
val fragment = NewFragment.newInstance(title)
replace(R.id.container, fragment, NewFragment.TAG)
addToBackStack(null)
}?.commit()
}
}
class PageFragment : Fragment() {
private fun show() {
(parentFragment as? ViewPagerFragment)?.showNewFragment("New fragment")
}
}
Make sure the fragment id you are calling is in the class listed in setcontent in onCreate method. For my case, I was editing the layout from linear to constraint. So as not to mess with the working code, I made another layout but messed an id in the process so that what was on oncreate was the edited layout but the fragment being called was from the old layout. Apparently, in the new layout I gave it a different id name. Search the id of your fragment using ctrl+shift+f and see if the search results point to the layout you specified in the oncreate method. Goodluck.
The most common mistake that can be happened is, If you have more than one version of XML layout (let say v21 and v23) and you added <fragment> tag in lower version of XML only (or vice-versa).
So, please check you added <fragment> tag (or pageGroup, etc) in both of the versions.
You are trying to open fragment which fragmentContainer(the view in which you are trying to open fragment) is one or more level above from your current fragmentContainer.
Try to change your fragment hierarchy architecture.

Fragment duplication on Fragment Transaction

Ok, whenever I try to replace a fragment in my application, it only adds the fragment inside of the container the other fragment is, and leaves the current fragment. I've tried calling replace and referencing the view the contains the fragment, and by referencing the fragment itself. Neither of these work. I can add a fragment to a view with the fragment transaction manager, but even if I try to remove it after its been added, it doesn't work. Any help would be appreciated. Here are my files.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//Setup the actionabar. Use setDrawableBackground to set a background image for the actionbar.
final ActionBar actionbar = getActionBar();
actionbar.setDisplayShowTitleEnabled(false);
actionbar.setDisplayUseLogoEnabled(true);
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionbar.addTab(actionbar.newTab().setText(R.string.home_tab_text).setTabListener(this),true);
actionbar.addTab(actionbar.newTab().setText(R.string.insert_tab_text).setTabListener(this));
Fragment fragment = new insert_button_frag();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.button_fragment, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
Here is the layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:id="#+id/button_fragment_container"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<fragment
android:name="com.bv.silveredittab.home_button_frag"
android:id="#+id/button_fragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<fragment
android:name="com.bv.silveredittab.quick_insert_frag"
android:id="#+id/quick_insert_frag"
android:layout_width="350dip"
android:layout_height="fill_parent" />
<fragment
android:name="com.bv.silveredittab.editor_frag"
android:id="#+id/editor_frag"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
</LinearLayout>
And here is the fragment code
public class insert_button_frag extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
return inflater.inflate(R.layout.insert_buttons,container, false);
}
}
Like I have said. I have tried referencing the fragments parent view to replace it, and the fragment itself (by id) and still, it only adds the new fragment, inside the containing view the original fragment is in.
I solved this by using a placeholder in my Layout and then attaching my Fragment to it at runtime.
Like you, if I instantiated my Fragment within my xml layout then the contents would remain visible after replacing it with another Fragment at runtime.
The problem is this line:
transaction.replace(R.id.button_fragment, fragment);
replace has two overloaded forms. In both of them, the first argument is the container of the Fragment to be replaced, not the Fragment itself. So, in your case, you need to call
transaction.replace(R.id.button_fragment_container, fragment);
edit: I see in your question that you have tried both. I have tested and verified the behavior. This appears to be a bug in the FragmentTransaction API.
Edit2: not a bug after all. You simply cannot replace fragments added statically in a layout file. You can only replace those you have added programmatically ( Android: can't replace one fragment with another )
I had the same issue. Take a look at this link: Android Fragment Duplication
I wonder if the fact that you're passing the container into the inflater.inflate() method causes it to create the new fragment inside of the old one instead of a wholesale replace. I've been providing 'null' to my inflaters in the working version.
Here's the essentials from the version I have working...
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View newFrag = new View(getActivity().getApplicationContext());
newFrag = inflater.inflate(R.id.frag, null);
return newFrag;
}
The google developer guide is quite confusing because it shows first to implement hard coded fragment in you xml. But if you really want to replace existing fragment with the new one, then you should add it(the first) at runtime.
What official site state is
FragmentTransaction replace (int containerViewId, Fragment fragment, String tag)
Replace an existing fragment that was added to a container. This is
essentially the same as calling remove(Fragment) for all currently
added fragments that were added with the same containerViewId and then
add(int, Fragment, String) with the same arguments given here.
You should noticed that it says that Replace an existing fragment that was added to container
So, your xml should look like
someActivity.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
tools:context="someActivity">
<ImageView
.../>
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="bottom"/>
</RelativeLayout>
And than in your activity do in OnCreate()
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
[...]
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, new FirstFragment).commit();
}
Than you may easily replace fragment with your animations and event add it to back stack in order to save its state.
private SecondFrag getSecondFrag(){
if(secondFrag == null)
secondFrag = new SecondFrag()
return secondFrag;
}
private void openRechargeFragment(){
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.show_frag, R.anim.hide_frag,
R.anim.show_frag, R.anim.hide_frag);
ft.replace(R.id.fragment_container, getSecondFrag(), "myTAG");
ft.addToBackStack(null);
ft.commit();
}

Categories

Resources