I have done as below :
Implemented Listener in Activity as MyCallBack.MyListener
Initialized it in activity as below :
App.Manager.myCallback?.myListener(this)
Below is the method implemented :
override fun onGettingData(data: MyData) {
var fragment1 = supportFragmentManager.findFragmentById(R.id.container) as Fragment1
if (fragment1 != null && fragment1.isVisible) {
fragment1.onDataReceived(data)
}
var fragment2 = supportFragmentManager.findFragmentById(R.id.container) as Fragment2
if (fragment2 != null && fragment2.isVisible) {
fragment2.onDataReceived(data)
}
}
But this method inside my fragments is not getting called.
Solution :
for (fragment in supportFragmentManager.fragments) {
if (fragment is Fragment1) {
fragment.onDataReceived(data)
} else if (fragment is Fragment2) {
fragment.onDataReceived(data)
}
}
Related
I can not do exactly what I want with the transitions to the initialization of my fragments:
val fragmentTransaction = fragmentManager.beginTransaction()
val fragments = fragmentManager.fragments
if (fragments.isNotEmpty())
for (oldFragment in fragments)
if (oldFragment.isAdded && (!second || oldFragment.tag?.substring(0, userId.length)!!.contains(fragmentTag)))
fragmentTransaction.hide(oldFragment)
//create or show
var fragment = fragmentManager.findFragmentByTag(fragmentTag + userId) as? F_Base
if (fragment == null || mKillFrags.contains(fragmentTag) || killFragment) {
if (fragment != null)
fragmentTransaction.remove(fragment)
fragment = createFragmentByTag(fragmentTag, bundle)
if (fragment == null) {
UIUtils.broadcastMessage(R.string.error)
return false
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
fragment.sharedElementEnterTransition = DetailsTransition()
fragment.sharedElementReturnTransition = null
fragment.enterTransition = Fade()
fragment.exitTransition = null
}
//todo test animation
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && sharedView.isNotEmpty()) {
for (view in sharedView)
fragmentTransaction.addSharedElement(view, view.transitionName.substring(0, view.transitionName.lastIndexOf("_")))
fragmentTransaction.replace(content.id, fragment, fragmentTag)
} else
fragmentTransaction.add(content.id, fragment, fragmentTag + userId)
} else {
fragmentTransaction.show(fragment)
}
fragmentTransaction.commitAllowingStateLoss()
In this case the transitions work because the initialization of the fragments pass by fragmentTransaction.replace() but I do not want to destroy my current fragment, except that if I leave fragmentTransaction.add() my transition is not taken.
Do you have a solution ?
I have a bottom navigation which runs on my Main Activity
private void BottomNavigation_NavigationItemSelected(object sender, BottomNavigationView.NavigationItemSelectedEventArgs e)
{
LoadFragment(e.Item.ItemId);
}
void LoadFragment(int id)
{
Android.Support.V4.App.Fragment fragment = null;
switch (id)
{
case Resource.Id.navigation_1:
fragment = Fragment1.NewInstance();
break;
case Resource.Id.navigation_2:
fragment = Fragment2.NewInstance();
break;
case Resource.Id.navigation_3:
fragment = Fragment3.NewInstance();
break;
}
if (fragment == null)
return;
SupportFragmentManager.BeginTransaction()
.Replace(Resource.Id.content_frame, fragment)
.Commit();
}
In my Fragment1 (which is Resource.Id.navigation_1) I am refreshing data
public async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
RefreshItems(false);
}
The issue is, every time I click on navigation_1 for fragment1, the data gets refreshed.
I don't want to load the fragment/data again once it's already loaded.
Is it possible in Xamarin?
You can check if current fragment also executed Here is a function
public Fragment find(String identifier) {
Fragment fragment = (Fragment) getSupportFragmentManager().findFragmentByTag(identifier);
return fragment;
}
and in BottomNavigationView you must check like this
if (find(fragment.getIdentifier()) != null) {
return;
}
I'd this problem sometime ago, however I was developing on native kotlin code, here goes the code I've used to handle this:
class Navigation(val supportFragmentManager: FragmentManager,
val filterIcon: ImageView ): BottomNavigationView.OnNavigationItemSelectedListener {
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when(item.itemId){
R.id.menu_bottom_home ->{
changeFragment(HomeFragment(), Constants.FRAG_HOME_FRAGMENT)
filterIcon.visibility = View.VISIBLE
}
R.id.menu_bottom_favorites ->{
changeFragment(FavoritesFragment(), Constants.FRAG_FAVORITES_FRAGMENT)
filterIcon.visibility = View.INVISIBLE
}
R.id.menu_bottom_reservations ->{
changeFragment(ReservationFragment(), Constants.FRAG_RESERVATION_FRAGMENT)
filterIcon.visibility = View.INVISIBLE
}
R.id.menu_bottom_profile ->{
changeFragment(ProfileFragment(), Constants.FRAG_PROFILE_FRAGMENT)
filterIcon.visibility = View.INVISIBLE
}
}
return true
}
fun changeFragment(fragment: Fragment, tag : String){
var contains: Fragment? = null
var current: Fragment? = null
if(supportFragmentManager.fragments != null && supportFragmentManager.fragments.isNotEmpty()) {
contains = supportFragmentManager.fragments.firstOrNull { x -> x.tag == tag }
current = supportFragmentManager.fragments.first { x -> x.isVisible }
}
if(current != null){
supportFragmentManager.beginTransaction()
.hide(current).commit()
}
if(contains != null){
supportFragmentManager.beginTransaction()
.show(contains).commit()
}
else{
supportFragmentManager.beginTransaction()
.add(R.id.fl_fragment_container, fragment, tag)
.addToBackStack(tag)
.commit()
}
}
}
Then you just have to set setOnNavigationItemSelectedListener with your Navigation class like this:
bnv_navigation.setOnNavigationItemSelectedListener(Navigation(supportFragmentManager, iv_filter_bar))
I have fatal exception in the method onBackPressed(): on a null object reference.
How to handle the exception correctly?
My code:
#Override
public void onBackPressed() {
List fragments = getSupportFragmentManager().getFragments();
BaseExampleFragment currentFragment = (BaseExampleFragment) fragments.get(fragments.size() - 1);
if (fragments != null && !currentFragment.onActivityBackPress()) {
super.onBackPressed();
}
}
it would be much easier if you also gave the stack trace.
However it is possible you are checking the wrong thing for null, change fragments to currentFragment
#Override
public void onBackPressed() {
List fragments = getSupportFragmentManager().getFragments();
BaseExampleFragment currentFragment = (BaseExampleFragment) fragments.get(fragments.size() - 1);
if (currentFragment != null && !currentFragment.onActivityBackPress()) {
super.onBackPressed();
}
}
I have a viewpager. The viewpager has five fragments. And these fragments have child fragments. When I start my app, it crashes. If I comment out resetMenu() function it works. What is the problem?
HomeActivity.java
#Override
public void onPageSelected(int position) {
listeners[beforePagerPosition].onViewPaused();
tabLayout.getTabAt(beforePagerPosition).getIcon().setAlpha(getResources().getInteger(R.integer.tab_unselected_alpha));
beforePagerPosition = position;
tabLayout.getTabAt(position).getIcon().setAlpha(getResources().getInteger(R.integer.tab_selected_alpha));
listeners[position].onViewResumed();
resetMenu();
hideKeyboard();
}
#Override
public void onPageScrollStateChanged(int state) {
}
private void resetMenu() {
if (getSupportFragmentManager() != null) {
ParentFragment parentFragment = (ParentFragment) listeners[viewPager.getCurrentItem()];
FragmentManager fm = parentFragment.getChildFragmentManager();
if (fm != null && fm.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry backStackEntry = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1);
String str = backStackEntry.getName();
BaseMenuFragment fragment = (BaseMenuFragment) fm.findFragmentByTag(str);
fragment.setHasOptionsMenu(true);
}
}
}
OK. I found answer. I added control for ParentFragment isAdded().
ParentFragment parentFragment = (ParentFragment) listeners[viewPager.getCurrentItem()];
if(parentFragment.isAdded()){
....
}
How to load animation when backstack fragment or removing fragment in stack?
I am using below code for remove fragment but i don't know how to add setCustomAnimation method to Load animation.
//Remove fragment in stack
private boolean returnBackStackImmediate(FragmentManager fm) {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size() > 0) {
for (Fragment fragment : fragments) {
if (fragment.getChildFragmentManager().getBackStackEntryCount() > 0) {
if (fragment.getChildFragmentManager()
.popBackStackImmediate()) {
Log.d("tag", "CalledInside");
return true;
} else {
return returnBackStackImmediate(fragment
.getChildFragmentManager());
}
}
}
}
return false;
}