Open DialogFragment from Presentation in Android - android

I'm trying to open a DialogFragment in a Presentation view.
But the DialogFragment keeps showing up in the Activity where the Presentation is projected from.
Can we have the DialogFragment in the Presentation itself or is this impossible since Presentation is extended from Dialog?
private void showMobileNumberEntryDialog() {
mobileNumberViewModel.setMobileNumberDialogVisibility(true);
FragmentTransaction ft = ((AppCompatActivity) referenceActivity).getSupportFragmentManager()
.beginTransaction();
if (customerNumberInputDialogVisible) {
Fragment oldFragment = ((AppCompatActivity) referenceActivity).getSupportFragmentManager()
.findFragmentByTag("fragment_mobile_number_input");
if (oldFragment != null) {
ft.remove(oldFragment);
}
MobileNumberInputFragment mobileNumberInputFragment = MobileNumberInputFragment.newInstance(customerNumberInputViewMode);
mobileNumberInputFragment.show(ft, "fragment_mobile_number_input");
} else {
Fragment oldFragment = ((AppCompatActivity) referenceActivity).
getSupportFragmentManager().findFragmentByTag("fragment_mobile_number_input");
if (oldFragment != null) {
ft.remove(oldFragment);
ft.commit();
}
}
}
The referenceActivity here is from the source activity where the Presentation is being projected from.

Related

Previous fragment visible behind current one after screen rotation

In my main activity I am displaying several fragments depending on option chosen by the user. When screen is rotated and then fragment changed, the previous fragment, one that was visible while rotating screen, is transparent and still visible behind or over new one. I am adding fragments using add() method and then removing old ones with remove(). I am aware that simply using replace() would fix my problem but my main fragment contains many network and database calls on create and I would like to remember its state rather than make many unnecessary calls.
Why does my problem even occur when I am removing fragments other than the main one? How can I fix it?
Here is how I am setting my fragments:
public void setFragment(FragmentEnum fragmentEnum, #Nullable Bundle bundle) {
Fragment oldFragment = getCurrentFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
currentFragment = fragmentEnum;
mMapFragment = (MainMapFragment) fragmentManager.findFragmentByTag(MainMapFragment.TAG);
if (mMapFragment == null) {
mMapFragment = MainMapFragment.newInstance(bundle);
}
if (fragmentEnum == FragmentEnum.MAP) {
if (!mMapFragment.isAdded()) {
ft.add(R.id.container_contents, mMapFragment, MainMapFragment.TAG);
}
if (oldFragment != null && !(oldFragment instanceof MainMapFragment)) {
ft.remove(oldFragment);
}
ft.show(mMapFragment);
if (mNavigationDrawerFragment != null) mNavigationDrawerFragment.unselectItems();
} else {
ft.hide(mMapFragment);
Fragment newFragment = null;
String tag = null;
switch (fragmentEnum) {
case LIST:
newFragment = MainListFragment.newInstance();
tag = MainListFragment.TAG;
break;
case FAVORITE:
newFragment = MainFavoriteFragment.newInstance();
tag = MainFavoriteFragment.TAG;
break;
case ADD:
newFragment = MainAddFragment.newInstance();
tag = MainAddFragment.TAG;
break;
case USER:
newFragment = MainUserFragment.newInstance();
tag = MainUserFragment.TAG;
break;
}
ft.add(R.id.container_contents, newFragment, tag);
if (oldFragment != null && !(oldFragment instanceof MainMapFragment)) {
ft.remove(oldFragment);
}
ft.show(newFragment);
}
ft.commit();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable(SAVE_STATE_CURR_FRG, currentFragment);
}
onCreate(){
...
if (savedInstanceState != null) {
FragmentEnum savedFragmentEnum = (FragmentEnum) savedInstanceState.getSerializable(SAVE_STATE_CURR_FRG);
setFragment(savedFragmentEnum, null);
}
...
}

Find a proper way to remove search onbackpress fragment

I'm developing an application that involves fragments. There are three fragments
Item List fragment
Item details fragment
Search/Loading fragment
Everything works well until the user press onbackbutton. I would like to show the user the previous fragment before the search fragment was shown.
I tried few solutions but none of them seems to work for me. I tried to remove the search fragment manually from back stuck but I got weird situation that the previous and the current fragment were shown at the same time.
This is the function that replaces the fragments from the main activity
public void replaceFragment(Class<?> fragClass, Bundle b)
{
Fragment bf = null;
try
{
bf = (Fragment) fragClass.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
if (b != null)
{
bf.setArguments(b);
}
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String backStateName = bf.getClass().getSimpleName();
if (f != null && backStateName.equals(f.getClass().getSimpleName()))
{
return;
}
FragmentManager manager = getSupportFragmentManager();
_currentFragment = bf;
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_left, R.anim.exit_to_right);
if(backStateName.equals(LoadingFragment.class.getSimpleName()))
{
ft.replace(R.id.fragment_container, bf).addToBackStack(null).commit();
}
else
{
ft.replace(R.id.fragment_container, bf).addToBackStack(backStateName).commit();
}
}
onbackpress function
#Override
public void onBackPressed()
{
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START))
{
drawer.closeDrawer(GravityCompat.START);
}
else
{
super.onBackPressed();
}
}
After many hours of figuring this out. I came across a simple solution, basically each time when I'm loading a new fragment I'm checking if the current fragment is the search fragment if so I will remove it manually by using popBackStackImmediate(). Not the most elegant solution but it worked for me.
This is my new function.
public void replaceFragment(Class<?> fragClass, Bundle b)
{
BaseFragment bf = null;
try
{
bf = (BaseFragment) fragClass.newInstance();
}
catch (Exception e)
{
e.printStackTrace();
}
if (b != null)
{
bf.setArguments(b);
}
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
String backStateName = bf.getClass().getSimpleName();
if (f != null && backStateName.equals(f.getClass().getSimpleName()))
{
return;
}
FragmentManager manager = getSupportFragmentManager();
_currentFragment = bf;
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (f != null && f.getClass().getSimpleName().equals(LoadingFragment.class.getSimpleName()))
{
manager.popBackStackImmediate();
}
ft.replace(R.id.fragment_container, bf, backStateName);
ft.addToBackStack(backStateName);
ft.commitAllowingStateLoss();
}

What is difference between FragmentTransaction.add().commit() and DialogFragment.show()?

To show DialogFragment, I can use below two ways:
ProgressDialogFragment fragment = (ProgressDialogFragment) getFragmentManager().findFragmentByTag("progress_dialog");
if (fragment == null) {
fragment = ProgressDialogFragment.newInstance();
fragment.setCancelable(false);
getFragmentManager().beginTransaction()
.add(fragment, "progress_dialog")
.commitAllowingStateLoss();
}
or
ProgressDialogFragment fragment = (ProgressDialogFragment) getFragmentManager().findFragmentByTag("progress_dialog");
if (fragment == null) {
fragment.show(getFragmentManager().beginTransaction(), "progress_dialog");
}
When and which I should use? Or both are same?
there are pretty much the same. show retrieve a transaction, from the FragmentManager you provide as parameter, and call add/commit as you can see from the snippet
public void show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commit();
}
the only difference is they reset some flags upon multiple calls of show()

Unable to remove fragment from transaction

In my app, I need to remove a set of fragments from transaction when the OS recreate my app due to configuration change. I'm trying to do it as following;
#Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
FragmentManager fm = getSupportFragmentManager();
List<android.support.v4.app.Fragment> fragments = fm.getFragments();
for (Fragment fragment : fragments) {
if (fragment != null) {
if (!((fragment instanceof FragmentType1) ||
(fragment instanceof FragmentType2) ||
(fragment instanceof FragmentType3))) {
FragmentTransaction trans = fm.beginTransaction();
trans.remove(fragment).commit();
}
}
}
}
}
Though trans.remove(fragment).commit() is executed successfully, but debugging shows that these fragments are still there in FragmentManager. Can anybody tell what I'm doing wrong here.

How to make a fragment be in the exact same way I left it when I return to it from another fragment?

I have a few fragments in my app, but my code opens a new fragment every time I click the button.
I want to know how can I change this, and make the fragment return to the exact same state I left it in.
The code im using right now:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragments);
MainActivity fragment = new MainActivity();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.add(R.id.fragment_place, fragment);
transaction.commit();
turnGPSOn();
}
public void onSelectFragment(View view) {
if (view == findViewById(R.id.add))
{
newFragment = new Add();
}
else if (view == findViewById(R.id.map))
{
newFragment = new MainActivity();
}
else
{
newFragment = new Add();
}
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment_place, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
Thanks!
You are getting a new fragment each time because you are calling to new XXX() each time.
I think you could use findFragmentByTag in order to solve this problem. As you can see here the replace function can accept a third parameter that is a String, this String can be used as an id to identify different fragments you have used previously.
So to sum up you can:
Call Fragment f = getSupportFragmentManager().findFragmentByTag("FragAdd"); for example in order to retrieve the first fragment.
If f is null, that means that you haven't used that fragment yet, so you have to call to new Add() if not, use that fragment to replace the old one. For example like this:
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment_place, newFragment, "FragAdd"); //or whatever other string you want to use
transaction.addToBackStack(null);
transaction.commit();
Hope it helps :)
I faced this issue a time ago, and managed to solve it for applications with one visible fragment at a time; for activities with several visible fragments, you'll need to make some adjustments. This is what I did.-
Create a custom ParentActivity, so that all my activities extend it. ParentActivity knows about which is the current Fragment that is showed, and how to show a new one.
public String currentFragmentTag;
public ParentFragment getCurrentFragment(int fragmentWrapperResId) {
ParentFragment res = null;
FragmentManager fragmentManager = getSupportFragmentManager();
res = (ParentFragment) fragmentManager.findFragmentById(fragmentWrapperResId);
if (res != null && res.isHidden()) {
if (currentFragmentTag != null) {
res = (ParentFragment) fragmentManager.findFragmentByTag(currentFragmentTag);
}
}
return res;
}
public void openFragment(ParentFragment fragment, int fragmentWrapperResId, int enterAnim, int exitAnim, int popEnterAnim, int popExitAnim, boolean addToBackStack) {
FragmentManager fragmentManager = getSupportFragmentManager();
ParentFragment currentFragment = getCurrentFragment(fragmentWrapperResId);
if (currentFragment != null && currentFragment.getTagName().equals(fragment.getTagName())) {
return;
}
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(enterAnim, exitAnim, popEnterAnim, popExitAnim);
if (currentFragment != null) {
transaction.hide(currentFragment);
}
if (fragment.isAdded()) {
transaction.show(fragment);
} else {
transaction.add(fragmentWrapperResId, fragment, fragment.getTagName()).setBreadCrumbShortTitle(fragment.getTagName());
}
if (addToBackStack) {
transaction.addToBackStack(fragment.getTagName());
} else {
currentFragmentTag = fragment.getTagName();
}
transaction.commit();
}
Create a ParentFragment, to be extended by the rest of Fragments, with a tag getter
public String getTagName() {
return getClass().getSimpleName() + System.identityHashCode(this);
}
As you can see, the main idea is not replacing visible fragments, but just adding them and show/hide whenever it's needed. This way, the fragments will keep their states, as they're not destroyed until you remove them from the bakstack.

Categories

Resources