I have 2 fragments in Main Activity when I click on first fragment's FAB it will be replaced with the second fragment, when I pressed back button in Fragment 2nd it will back on Fragment 1st, but it not show one big part of the layout, look this images to understand the problem:
1: When the app launched
2: when I pressed back button in 2nd fragment and cames back to 1st fragment
In 1st fragment xml I have 3 part main Item:
<androidx.coordinatorlayout.widget.CoordinatorLayout
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"/>
<com.google.android.material.appbar.AppBarLayout>
...
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView>
...
</androidx.core.widget.NestedScrollView>
<com.google.android.material.floatingactionbutton.FloatingActionButton/>
</androidx.coordinatorlayout.widget.CoordinatorLayout >
actually, NestedScrollview and its subItems Not show when I came back from 2nd fragment to 1st fragment.
In Fragment 1st I start Fragment 2nd with these codes:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_first, container, false);
FloatingActionButton fab = view.findViewById(R.id.fabAddWord);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getFragmentManager()
.beginTransaction()
.addToBackStack(TAG)
.replace(R.id.fragment_container, SecondFragment.newInstance(),
WordSearchFragment.class.getSimpleName())
.commit();
}
});
return view;
}
you should override the onBackPressed and show the first fragment when the back button pressed
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 1)
getFragmentManager().popBackStack();
else
super.onBackPressed();
}
After 2 days I solved the problem, The problem Was for FrameLayout That I used as Fragment Container. I learned Use FrameLayout as Container and see in everywhere that people use Framelayout, but in fact, FrameLayot not adapted for complex Layout Fragments.
So in MainActivity.xml, I changed FrameLayout To ConstraintLayout and worked!
Related
I've incorporated a horizontal slide navigation component (which required making the class extend Fragment). The slide part works fine. Here i have respective onClick() buttons which open a new activity. If I add a button into one of those activities I'm not finding a way to have the displayed activity subsequently refresh. I would think inflating an activity from a button within a fragment would be possible but anything I try stops the emulator.
There's not much to my code so far, so I'm not going to clutter my question with the associated layout part. Any help is certainly appreciated.
Fragment #1’s Java code
public class TasksFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tasks, container, false);
Button ID = (Button) rootView.findViewById(R.id.button_create_appraisal_rpt);
ID.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
AppraisalReportActivity appraisalRptAct = new AppraisalReportActivity();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.child_fragment, appraisalRptAct);
fragmentTransaction.setTransition(fragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
return rootView;
}
}
Fragment #1 (portion), which has the button that should initiate aa refresh of this Fragment #1 with Fragment #2
Fragment #2 that's to supersede/refresh the previous fragment when Fragment #1's button is clicked
I don't really understand what you mean. Do you want to click Button in Fragment to jump to another Activity?
If it is,I think maybe you can try use getActivity() to make Activity are working.
for example:
getActivity().startActivity(new Intent(getActivity(),Activity.class))
I hope my answer will help you
I am using Fragments and Activity extended by AppCompatActivity in an application.
Working:
I have two fragments "Dashboard" and "Order". I am replacing fragment after clicking "Order Button" from Dashboard Fragment, and coming back to "Dashboard Fragment" after pressing back button.
Problem
I have called an API on onCreateView() of Dashboard Fragment. When I press back from Order Fragment then I come to "Dashboard Fragment" the it recall the API. I don't want to recall the API if I come to the fragment by back press.
Thanks in advance.
Code to replace dashboard fragment with order fragment
// Click event of Order
#OnClick(R.id.ll_order)
void openOrder() {
if (isOrderNotClicked) {
OrderFragment fragment = new OrderFragment();
this.getFragmentManager().beginTransaction().replace(R.id.flContent, fragment, "Order").addToBackStack(null).commit();
isOrderNotClicked = !isOrderNotClicked;
}
}
I did had same problem so i solved by `View view;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (view == null) {
//inflate layout and codes
}
return view;
}` but i dont know it is the best solution
I have a view that shows a List of Properties, at the bottom of the screen there's a button that opens a fragment containing a MapView.
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.find_property_btn_map:
PropertyMapFragment fragment = PropertyMapFragment.newInstance(false, null);
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(((ViewGroup) getView().getParent()).getId(), fragment, PropertyMapFragment.class.getSimpleName())
.commit();
break;
}
}
The onCreateView method for my Properties fragments is as follows
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
mRootView = inflater.inflate(R.layout.fragment_properties_list, container, false);
getmBtnMap().setOnClickListener(this);
getmBtnSaveSearch().setOnClickListener(this);
getmBtnSort().setOnClickListener(this);
getmListView().setAdapter(getPropertyAdapter());
getmListView().setOnItemClickListener(this);
getmListView().setOnScrollListener(this);
getmListView().setScrollingCacheEnabled(false);
searchProperties();
return mRootView;
}
searchProperties(); takes care of calling a Web Service and filling the ArrayAdapter.
The thing is that, when I open the MapFragment and then press the back button, my Property fragment is blank and the buttons do not respond to onClick events.
I tried debugging and saw that onCreateView() is being called when coming back to Property fragment, but the buttons are no longer working and the listview is nowhere to be seen.
What am I doing wrong?
If you are trying to launch that web view from a fragment, then try to use add fragment instead of replace.
For example :
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.replace(YOUR_CONTAINER_ID, fragment, PropertyMapFragment.class.getSimpleName())
.commit();
The code above is replace that fragment container with the new one and not adding that fragment on top of that. So when you do a replace fragment with that ID, it just replaces that view with new one.
Now,
Same code but with add:
getActivity().getSupportFragmentManager().beginTransaction()
.addToBackStack(null)
.add(YOUR_CONTAINER_ID, fragment, PropertyMapFragment.class.getSimpleName())
.commit();
Now, that web view fragment that you have will be added to the view/fragment and now when you press back from that web view, you previous fragment will be visible.
Just make sure that that the ID you are replacing is the same as the one in which you have all the other properties.
Maybe i misinterpreted the question so please correct me in that context.
Hope this helps.
addToBackStack() <--dont include this for your first fragment.-->
if(getSupportFragmentManager().getBackStackEntryCount() !=1){
fragmentTransaction.addToBackStack(null);
}
I have an activity that has a ViewPager in the layout.
I have two fragments which display, one for each tab.
One of the fragments is designed to host other fragments - this is the CustomerMainFragment which inflates fragment_customer_main:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lyt_customer_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/fragment_customer_content"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
This then adds CustomerSearchFragment to the FrameLayout which inflates fragment_customer_search.
CustomerSearchFragment also has the following override to switch out the search fragment for a detail fragment on a button press:
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button btnSearch1 = (Button) view.findViewById(R.id.button1);
if (btnSearch1 != null) {
btnSearch1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// This is important bit
Fragment customerDetailFragment = new CustomerDetailFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.replace(R.id.fragment_customer_content, customerDetailFragment).commit();
}
});
}
}
After clicking the button I get the following error:
java.lang.IllegalArgumentException: No view found for id 0x7f080006
(com.chrisbeckyapps.sample:id/fragment_customer_content) for fragment
CustomerDetailFragment{4280b0b8 #0 id=0x7f080006}
I'm new to fragments and understand the concepts, but I'm stumped by this. I originally had the search fragment going straight into the pager, but then replacing it with the detail fragment mean it just showed over the top, and my research led to this being a better solution.
I have wondered about trying to move the search logic to the CustomerMainFragment but this means hooking up a lot of logic and I thought you could embed logic within fragments.
Suggestions?
Sorry, just found such a simple fix.
In my onclick handler, I just had to change from getChildFragmentManager to getFragmentManager
I have a tab + ViewPager layout and in one of these tabs I have a list view. When I replace that list fragment upon the onclick I can still see the old fragment under the new fragment. See:
Code:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
HallsInStateFragment hallsForState = new HallsInStateFragment();
transaction.replace(R.id.container, hallsForState);
transaction.addToBackStack(null);
transaction.commit();
where the R.id.container is the FrameLayout in the view.
when need to remove all views from the parent view you need to call removeAllViews() at container in your onCreateView() method of your fragment.
Here is the code:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
container.removeAllViews(); // Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_example, container, false);
}
Instead of R.id.container put id of fragment like this: ((ViewGroup)getView().getParent()).getId(). Actually it is not replacing the fragment but the previous layout i.e FrameLayout. It works for me and i hope it will work in your case also.
Add this to both fragment parent layout
android:background="#android:color/white".
The one which you are replacing and one which you will replace.
The fragment's UI is a part of the activity view hierarchy. So if you created your views in onCreateView() method then you inflate your layout using the ViewGroup container. This container keeps references to your fragment views. Try to override onDestroyView() method of your fragment and remove all the views from the parent:
#Override
public void onDestroyView() {
//mContainer.removeAllViews();
ViewGroup mContainer = (ViewGroup) getActivity().findViewById(R.id.container);
mContainer.removeAllViews();
super.onDestroyView();
}
Your fragments should be loaded in FrameLayout like this
<FrameLayout
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground" />
And your fragments should be added/loaded in this frameLayout by this function
private fun switchFragment(
fragment: Fragment,
addToBackstack: Boolean
) {
//check new fragment is alredy loaded currently, then return
val myFragment =
supportFragmentManager.fragments.lastOrNull()//return current visible fragment or null
if (myFragment != null && fragment::class == myFragment::class) {
return
}
val fragmentManager = supportFragmentManager
val transaction = fragmentManager.beginTransaction()
//transaction.add(R.id.frameLayout, fragment, fragment.javaClass.name)
transaction.replace(
R.id.frameLayout,
fragment,
fragment.javaClass.name
)//using replace will make sure that the previous fragment won't be visible from new fragment
if (addToBackstack) {
transaction.addToBackStack(fragment.javaClass.name)
}
transaction.commit()
}
So initially, your first fragment should be loaded like this,
switchFragment(HomeFragment(), false)
and then other fragments when you select from bottom navigation view or navigation drawer, call this function like this
switchFragment(MyProfileFragment(), true)
In My Case , This was happening because I was using the static fragment as
<?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.android.FooFragment"
android:id="#+id/fooFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
where foofragment is the initial fragment , Then Trying to replace the fragment using with other fragment , so that both fragment overlaps.
Instead , Problem is solved , when I used dynamic Linkage , in place of fragment in the xml , we need to use framelayout as
<?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" >
<FrameLayout
android:id="#+id/your_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
Then dynamically adding the fragment-1 and replacing with the fragment-2 , is working fine for me.
I did not find answer earlier, hence posting this solution.
In the root view add clickable = true and add a background color(both in the xml) of the fragment replacing the current fragment .
Its just a fix for workaround
Best code for it. clearly and not used another ram of device.
on you Activity onCreate or before adding fragments add this code:
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
if (fragment instanceof NavigationDrawerFragment) {
continue;
}
else if (fragment != null) {
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
}
}
Happy coding :)