MainActivity to Fragment and from that Fragment back to MainActivity - java

Solve by using getActivity()
I have this MainActivity.java and RepeatEntry.java
inside my MainActivity i have this code to have RepeatEntry ui
//i did hide two linear layout here with buttons and edittext inside it ,using the following method
hideTwoLinearLayout();
showCategoryContainerLayout();
Fragment fragment = new RepeatEntry();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//category_cont is a linear layout container for my fragment
ft.replace(R.id.category_cont, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
inside my RepeatEntry.java sample code
Button k = (Button) v.findViewById(R.id.button);
k.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Intent intent = new Intent(getActivity(),MainActivity.class);
// startActivity(intent);
// if i use popBackStack and also remove the code for intent , i cannot show what i hide
//note i have a method inside mainactivity to showTwoLinearLayout()
getFragmentManager().popBackStack();
}
});
Now my question is, do i have other option other than using intent to go back to MainActivity view
Note:Edited

You can add the transaction to backstack and then reverse with poping the backstack the code is here
Fragment fragment = new RepeatEntry();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
//category_cont is a linear layout container for my fragment
ft.replace(R.id.category_cont, fragment).addToBackStack("tag");
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
And for going back to the activity view call this to pop backstack
FragmentManager fm = getFragmentManager();
fm.popBackStack();
Also you can use the tag to poping back the specific transaction with
fm.popBackStack("tag");

There is a method called onAttach in your fragment. You can write an interface and assign your fragment's activity like:
private MyFragmentListener mListener;
#Override public void onAttach(Activity activity) {
super.onAttach(activity);
mListener = ((MainActivity) activity);
}
public interface MyFragmentListener{
void onClicked(int value);
}
//Call your listener when button clicked or other events
... mListener.onClicked(position);
Or another solution is to use Otto or Eventbus to get rid unnecessary code

You can also go back in Fragment like
getActivity().getSupportFragmentManager().popBackStack();

any way i solve my problem just in case if anyone might see this.I came up with two solution which i think the first one is best for me.Thanks to Adnan Basar who give me idea.
First solution is so simple by just adding this code inside my onClick event
((MainActivity) getActivity()).showTwoLinearLayout();
((MainActivity) getActivity()).hideCategoryContainerLayout();
Second Solution I created Activity after extends Fragment{
Activity mainActivity;
And use override methods
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mainActivity= activity;
}
#Override
public void onDestroy() {
super.onDestroy();
// this is where i call the method for showing the twolinearlayout again
((MainActivity) mainActivity).showTwoLinearLayout();
((MainActivity) mainActivity).hideCategoryContainerLayout();
}

Related

How to reload all the fragments at the same time

I have an activity with 2 fragments. Let's call the activity "MainActivity", the first fragment "FragmentA" and the second fragment "FragmentB".
When I delete an element in FragmentA, I use this method inside the FragmentA to realod it:
public void reload_fragment() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();
}
But I also need to reload the FragmentB at the same time.
I try to add in the above method that:
public void reload_fragment() {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(this).attach(this).commit();
MainActivity mainActivity = new MainActivity();
mainActivity.reload_fragments();
And then, in my mainActivity, i have this method:
public void reload_fragments(){
viewPager = findViewById(R.id.Viewpager_ID);
adapter = new SimpleFragmentPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
TabLayout tabLayout = findViewById(R.id.tablayout);
tabLayout.setupWithViewPager(viewPager);
}
But it doesn't work.
I tried to add the same method which is inside the FragmentA into the FragmentB, and then call it by the FragmentA, but again, it says "virtual method on NullObjectReference". How can I refresh all the fragments at the same time?
Form a ViewModel with a MutableLiveData boolean field called say "refresh".
Add a method to the ViewModel called "toggleRefresh()" which flips the state of refresh.
In each fragment, in the onAttatch, observe the refresh field and do the "reload there"?

How to change fragment from another fragment an apply it on the main_content layout?

I'm struggling with the changing of a fragment from another fragment. In my main_activity i have a layout-file with a bottomnavigationview and a framelayout for the content on the page. The changing from fragment to fragment on the navigationview workes fine, but if i access a new "subfragment" from a fragment, the new fragment is transparent.
Any suggestions? code below from my fragment and my mainactivity.
MainActivity parentActivity = (MainActivity) getActivity();
parentActivity.switchContent(new VisArrangementInfo(), data, true);
switchContent inside MainActivity:
public void switchContent(final Fragment fragment, Bundle data, final Boolean addToBackStackOption){
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();
}
The id content_frame is the id for the layoutfile for my MainActivity. the bottomnavigationview and the framelayout is in this file. the ID for the framelayout is "main_frame".
After my understanding i would want to change the "main_frame" and not the "content_fram" since it's here the main-content is supposed to be. When i do that i can't find the layout for the fragment i try to open at all. Is it because i'm trying to replace the framelayout instead of the whole layout?
In your Fragment A define an interface.
public interface FragmentEventListener {
void onFragmentChangeEvent(Fragment newFragment);
}
private FragmentEventListener listener;
public void setEventListener(FragmentEventListener listener) {
this.listener = listener;
}
In your fragment, when you want to change the fragment, call the method.
if (listener != null) {
listener.onFragmentChangeEvent(FragmentB);
}
In your main activity, implement FragmentEventListener, so you can switch to Fragment B from MainActivity.
public class MainActivity implements FragmentA.FragmentEventListener {
...
...
fragmentB.setEventListener(this); // here identify the listener.
....
#Override
public void onFragmentChangeEvent(Fragment newFragment) {
switchContent // Switch to Fragment B here
}
In the first time use add instead of replace:
public void switchContent(final Fragment fragment, Bundle data, final Boolean addToBackStackOption){
getSupportFragmentManager()
.beginTransaction()
.add(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();
}

Implementing back stacks with fragments

I'm attempting to implement a back stack while using fragments, but when using the Back button, I keep getting taken out of the app to the home screen.
Activity opens fragment A; Fragment A has a clickable TextView that opens fragment B (this works). Hitting BACK should return me to fragment A, but it takes me to the home screen instead.
Here is the activity's call to the opening of fragment A in onCreate:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_layout_container, new FragmentLogin(), "fragment_login")
.addToBackStack("login_screen")
.commit();
Log.d("Back", getFragmentManager().getBackStackEntryCount() +" <- Entry Count at LoginActivity.onCreate" );
At this point, the Log prints 0 <- Entry Count at LoginActivity.onCreate. Something I've done wrong keeps this from printing 1.
Then, the Fragment A has this listener:
forgottenPassword.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_layout_container, new FragmentForgottenPassword(), "fragment_password")
.addToBackStack("forgotten_password")
.commit();
Log.d("Back", getFragmentManager().getBackStackEntryCount() + " <- Entry Count at FragmentLogin.onCreateView.Listener");
}
});
The Log here prints 1 <- Entry Count at FragmentLogin.onCreateView.Listener. Here, the listener works and opens fragment B - but the back button returns me to the home screen.
Use this in your Activity it should pop out the fragments already added to backstack
#Override
public void onBackPressed()
{
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Try Like This,
public void replaceFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
} else {
getFragmentManager().popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
transaction.replace(R.id.fragment_layout_container, fragment);
transaction.commitAllowingStateLoss();
getFragmentManager().executePendingTransactions();
}
and Used it like this,
replaceFragment(new FragmentForgottenPassword(), true);
There is a GitHub library that will do this work for you!https://github.com/rathodchintan/Fragment-Back-StackWhenever you are displaying any new fragment, just push that fragment into stack using following code.
//here this fragment is our first fragment
homeListFragment = new HomeListFragment();
fragmentStack.push(homeListFragment);It has many other stack options too.

Removing a fragment not working

I want to remove a fragment and show a toast when I click a textView. My code shows the toast, but doesn't remove the fragment.
My method:
public void hide(View view) {
My_frag myFrag= new My_frag();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.remove(myFrag);
transaction.commit();
Toast.makeText(getApplicationContext(), "Hello", Toast.LENGTH_LONG)
.show();
}
My_frag class:
public class My_frag extends android.support.v4.app.Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.my_frag_layout, container, false);
}
}
At some point you must create and add the Fragment correct? You are re-creating the fragment in your hide(...) method so you are trying to remove something that has never been added. Sure you may have added an instance, but not the instance you are trying to remove.
Instead, create a global variable Fragment fragToRemove in your Activity. When you create the fragment (that is where ever you do transaction.add(fragToRemove = new My_Frag);) you will hold an instance. then change your transaction.remove(myFrag) to transaction.remove(fragToRemove) and it should work just fine.
Take the instance of Fragment Transaction other than that was taken while adding fragment to activity and call remove method on that and pass the same instance of Fragment which was used at the time.
Example:
public class MainActivity extends AppCompatActivity {
FragmentTransaction fragmentTransaction;
BlankFragment blankFragment;
Button b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
b = (Button) findViewById(R.id.activity_button);
fragmentTransaction = getSupportFragmentManager().beginTransaction();
blankFragment=new BlankFragment(); //Fragment instance
fragmentTransaction.add(R.id.main_layout,blankFragment).commit();
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.remove(blankFragment).commit(); //created different
}
});
}
In the same way you can do in fragments also and can also remove fragment X on the click of component of fragment X.

Replacing a fragment with another fragment inside activity group

I have a fragment inside a group activity and I want to replace it with another fragment:
FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
SectionDescriptionFragment bdf = new SectionDescriptionFragment();
ft.replace(R.id.book_description_fragment, bdf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
It works fine when it is done as a seperate project without using activity group, every thing works fine in log cat as control goes inside getview(), but no view is visible, not even any exception arises, I want the book detail fragment to be replaced by section detail fragment.
Xml of book detail fragment has id book_description_fragment and xml for section description fragment has id section_description_fragment.
The above code is in onClick method of an item, I want that when user taps on an item in horizontal scroll view, then the fragment changes.
Fragments that are hard coded in XML, cannot be replaced. If you need to replace a fragment with another, you should have added them dynamically, first of all.
Note: R.id.fragment_container is a layout or container of your choice in the activity you are bringing the fragment to.
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Please see this Question
You can only replace a "dynamically added fragment".
So, if you want to add a dynamic fragment, see this example.
I've made a gist with THE perfect method to manage fragment replacement and lifecycle.
It only replace the current fragment by a new one, if it's not the same and if it's not in backstack (in this case it will pop it).
It contain several option as if you want the fragment to be saved in backstack.
=> See Gist here
Using this and a single Activity, you may want to add this to your activity:
#Override
public void onBackPressed() {
int fragments = getSupportFragmentManager().getBackStackEntryCount();
if (fragments == 1) {
finish();
return;
}
super.onBackPressed();
}
Use the below code in android.support.v4
FragmentTransaction ft1 = getFragmentManager().beginTransaction();
WebViewFragment w1 = new WebViewFragment();
w1.init(linkData.getLink());
ft1.addToBackStack(linkData.getName());
ft1.replace(R.id.listFragment, w1);
ft1.commit();
Use ViewPager. It's work for me.
final ViewPager viewPager = (ViewPager) getActivity().findViewById(R.id.vp_pager);
button = (Button)result.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewPager.setCurrentItem(1);
}
});
hope you are doing well.when I started work with Android Fragments then I was also having the same problem then I read about
1- How to switch fragment with other.
2- How to add fragment if Fragment container does not have any fragment.
then after some R&D, I created a function which helps me in many Projects till now and I am still using this simple function.
public void switchFragment(BaseFragment baseFragment) {
try {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
if (getSupportFragmentManager().findFragmentById(R.id.home_frame) == null) {
ft.add(R.id.home_frame, baseFragment);
} else {
ft.replace(R.id.home_frame, baseFragment);
}
ft.addToBackStack(null);
ft.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
enjoy your code time :)
you can use simple code its work for transaction
Fragment newFragment = new MainCategoryFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame_NavButtom, newFragment);
ft.commit();
You Can Use This code
((AppCompatActivity) getActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.YourFrameLayout, new YourFragment()).commit();
or You Can This Use Code
YourFragment fragments=(YourFragment) getSupportFragmentManager().findFragmentById(R.id.FrameLayout);
if (fragments==null) {
getSupportFragmentManager().beginTransaction().replace(R.id.FrameLayout, new Fragment_News()).commit();
}
I change fragment dynamically in single line code
It is work in any SDK version and androidx
I use navigation as BottomNavigationView
BottomNavigationView btn_nav;
FragmentFirst fragmentFirst;
FragmentSecond fragmentSecond;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
fragmentFirst = new FragmentFirst();
fragmentSecond = new FragmentSecond ();
changeFragment(fragmentFirst); // at first time load the fragmentFirst
btn_nav = findViewById(R.id.bottomNav);
btn_nav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch(menuItem.getItemId()){
case R.id.menu_first_frag:
changeFragment(fragmentFirst); // change fragmentFirst
break;
case R.id.menu_second_frag:
changeFragment(fragmentSecond); // change fragmentSecond
break;
default:
Toast.makeText(SearchActivity.this, "Click on wrong bottom SORRY!", Toast.LENGTH_SHORT).show();
}
return true;
}
});
}
public void changeFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_layout_changer, fragment).commit();
}
In kotlin you can do:
// instantiate the new fragment
val fragment: Fragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.book_description_fragment, fragment)
transaction.addToBackStack("transaction_name")
// Commit the transaction
transaction.commit()
This will work if you're trying to change the fragment from another fragment.
Objects.requireNonNull(getActivity()).getSupportFragmentManager()
.beginTransaction()
.replace(R.id.home_fragment_container,new NewFragment())
NOTE As stated in the above answers, You need to have dynamic fragments.
You can use fragment-ktx
// If you are in fragmet
childFragmentManager.beginTransaction()
// or if you are in activiry
supportFragmentManager.beginTransaction()
// Create and commit a new transaction
supportFragmentManager.commit {
setReorderingAllowed(true)
// Replace whatever is in the fragment_container view with this fragment
replace<ExampleFragment>(R.id.fragment_container)
}
To replace a fragment with another one do this, Note that R.id.fragment comes from the id that you give to the first tag of the fragment in the XML.
barAudioPlaying.setOnClickListener(view -> {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment,new HomeFragment())
.commit();

Categories