Android - Back button from FragmentActivity to another Fragment - android

Let's say I have a ListFragment A that is rooted from MainActivity A. User presses a list from List A and go to the FragmentActivity B. FragmentActivity holds 3 tabs of fragments.
So, I want to put an up navigation to the FragmentActivity B, so that it goes back to ListFragment A. How do I go about that?
This is my try, so far no luck:
public class ItemDetailActivity extends FragmentActivity implements ActionBar.TabListener {
...
actionBar.setDisplayHomeAsUpEnabled(true);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
LatestFragment fragment = new LatestFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.pager, fragment).addToBackStack(null)
.commit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
LatestFragment is the ListFragment A I want to go back to.
However, I got an error that says I have to implement OnLatestSelectedListener because in LatestFragment, I already put an interface to pass values.
What else can I go inside onOptionsItemSelected?

Assuming you started ItemDetailActivity with a standard intent, you should just be able to use back action like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
super.onBackPressed();
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

If fragment A is in your main activity then you can also look in to using ActionBar. Back button takes you to the main activity. It is quite easy to implement as well.

I assume your FragmentActivityB has got the back button.
if not you can get it by
getActionBar().setDisplayHomeAsUpEnabled(true);
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value="#######" />
Now you can just identify fragments rooted with MainActivity using some flags like ViewNumber(1,2,3).
Implement the method onMenuItemSelected(....) and pass the viewNumber ie; the Fragment Which you want to show.
#Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
//We are implementing this method to respond to the back button on the action bar.
int itemId = item.getItemId();
switch (itemId) {
case android.R.id.home:
Intent i = new Intent(this,MainActivity.class);
i.putExtra("viewNumber",2);
startActivity(i);
break;
}
return true;
}//onMenuItemSelected
In MainActivity get the viewNumber using Bundles, and you can have some method like this to work out and display the desired Fragment.
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 1:
fragment = new ListFragmentB();
break;
case 2:
fragment = new ListFragmentA();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
}
}
}
I hope it will solve your problem.

Related

How to use interface to call an action from a fragment in an activity

I have an interface like so:
public interface IStartCamera {
void startScanning();
}
I have a fragment that implements this interface and in this fragment I have an override for this like so:
#Override
public void startScanning() {
Intent intent = new Intent(getActivity(), QrScanAcitivity.class);
startActivityForResult(intent, SQ_SCANNING_RESULT);
startActivity(new Intent(getActivity().getApplicationContext(), QrScanAcitivity.class));
}
In my activity I create an instance of this fragment when a navigation button is clicked like so:
private IStartCamera iStartCameraInFragment;
public void setStartCameraInFragment(IStartCamera IStartCameraInFragment) {
this.iStartCameraInFragment = IStartCameraInFragment;
}
fragment = new ExitFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
fragment).commit();
navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
fragment = null;
switch (item.getItemId()){
case R.id.item_manual_scanning:
fragment = new ExitFragment();
setStartCameraInFragment(fragment); // <=== I HAVE THE PROBLEM HERE
break;
case R.id.item_reload:
fragment = new ReloadFragment();
break;
case R.id.item_add_entry_info:
fragment = new AddEntryInfoFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
fragment).commit();
return true;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fabOpenCamera:
iStartCameraInFragment.startScanning();
break;
}
}
when I the setStartCameraInFragment(fragment) when instantiating the fragment, I get a wrong requirement since it is expecting an IStartCamera and not a fragment even though that fragment implements IStartCamera.
First of all, don't instantiate the Fragment by using the constructor. It's a good practice to use a static method, usually named 'newInstance' for instantiating Fragments, because if you'd like to pass any parameter to it later on, you will be able to do it easily.
Regarding your question, you get the error because you are trying to call the 'setStartCameraInFragment' method by using a Fragment object, while the method requires an instance of IStartCamera. What you should do (if you want to stick with this logic) is check if the Fragment is an instance of the IStartCamera interface, and after that you would be able to use it as such. Here's an example:
if (fragment instanceof IStartCamera)
setStartCameraInFragment((IStartCamera)fragment); // --> Here the fragment can be considered as an instance of IStartCamera and this will work

Start an activity from fragment using bottom navigation bar

In my app I have 5 fragments. In order to switch between them i use bottom navigation bar.
Also, i need to open activities from my fragments, but when I open new activity it opens in each of the fragments. (I mean over the fragments, in each case)
How to make the activity open in one case?
My code:
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment fragment = null;
switch (item.getItemId()) {
case R.id.nav_home:
fragmentManager.beginTransaction().hide(active).show(fragment1).commit();
active = fragment1;
return true;
case R.id.nav_bookmark:
fragmentManager.beginTransaction().hide(active).show(fragment2).commit();
active = fragment2;
return true;
case R.id.nav_blog:
fragmentManager.beginTransaction().hide(active).show(fragment3).commit();
active = fragment3;
return true;
case R.id.nav_notification:
fragmentManager.beginTransaction().hide(active).show(fragment4).commit();
active = fragment4;
return true;
case R.id.nav_account:
fragmentManager.beginTransaction().hide(active).show(fragment5).commit();
active = fragment5;
return true;
}
return false;
}
};
Thanks!
This is clearly a FragmentManager issue - and not an Activity issue.
Instead .hide().show() use .replace().
For reference, see the documentation.
According to the Android documentation, an activity is always placed on top of the current activity stack.
So if you have the MainActivity with the BottomNavigationView and the fragments, starting a new Activity will open the activity above the MainActivity with the BottomNavigationView. So it is not possible to open an Activity only in one of the BottomNavigationView Fragments.
To achieve the desired behaviour, consider using another Fragment instead.

prevent same fragment multiple times in backstack

Hi guys here is my code
navigationView.setNavigationItemSelectedListener(new NavigationView
.OnNavigationItemSelectedListener() {
#Override public boolean onNavigationItemSelected(#NonNull MenuItem item) {
if (item.isChecked()) {
//item already selected. Do nothing
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
switch (item.getItemId()) {
case R.id.home:
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
transaction.replace(R.id.fragment, new HomeFragment())
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).commit();
break;
case R.id.other:
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, new OtherFragment())
.addToBackStack(null).setTransition(FragmentTransaction
.TRANSIT_FRAGMENT_FADE).commit();
break;
default:
break;
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
I basically only have 2 fragments and merely the HomeFragment should be added to the backstack. After switching between HomeFragment and OtherFragment for a while and clicking on the back button while on the HomeFragment, I end up with the HomeFragment getting displayed several times.
Within the HomeFragment lies a recyclerview. When I scroll up and down I can really see that the rows are displayed multiple times.
How can I make sure that the HomeFragment is added to the backstack only once.
Thanks
You could easily check your fragment with
YourFragment.isAdded
And if you have a multiple fragment you could create a new class to manage all the fragment and create state to check if fragment have been added or not.
When you click on the Home menu item try to find out whether there is any fragment in the backstack or not. If yes, call popBackStack() or replace a fragment as you do now otherwise. Use this code: if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
}

onOptionsItemSelected of fragment inside ViewPager not called

I have a problem with developing an app for both tablets and smartphones with fragments.
When app is executed on smartphone, I show a fragment with a list (categories). When clicking on an item, I start a new activity that holds a ViewPager that inflates Fragments with another list (detail).
When app is executed on tablet I have a layout with two fragments inside. The left one is the categories list and the right one is the detail list.
Up to here there's no problem, but when setting onOptionsItemSelected I have problems.
When executing app on smartphone, everything is working well. This works:
Activity containing ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icShare:
sharePortal();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
Fragment inflated by ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icFavourite:
Utils.setFavouritePortal(mContext, mPortal);
getActivity().invalidateOptionsMenu();
return true;
case R.id.icShowFavourites:
showFavouriteArticles();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
But when executing the app in tablet, onOptionsItemSelected is not called. This is the code:
Fragment containing ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icShowFavourites:
Log.e("asdf", "asdfasdf - test tablet");
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
Fragment inflated by ViewPager
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.icFavourite:
Utils.setFavouritePortal(mContext, mPortal);
getActivity().invalidateOptionsMenu();
return true;
case R.id.icShowFavourites:
showFavouriteArticles();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
The only difference is that when executing on smartphone, the first onOptionsItemSelected is hold by an Activity and in tabled is hold by a fragment. I also tried to execute the onOptionsItemSelected from the Activity containing the fragment that contains the ViewPager inflating other fragments with no luck.
How can I get it working?
Thank you in advance!
Try to put setHasOptionsMenu(true); inside the fragment where you want onOptionsItemSelected() to be called.
Documentation
The fragment should call setHasOptionsMenu(true), and should implement onCreateOptionsMenu() and onOptionsItemSelected().

Home up navigation between fragments

I have an activity(say activity X) which contains a search box. On searching, I move on to another activity.( say Activity Y) I have used SherlockFragmentActivity to extend this Activity class and inside this activity I am loading a single fragment(say fragment A).
This fragment has many rows and on click of each row I am loading another fragment(say fragment B).
The problem is on clicking home button on my navigation bar from fragment B, Activity X is getting loaded and not fragment A.
I want fragment A to be loaded. How can I accomplish this?
What I have tried was: In my Activity Y,
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
#Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home :
this.getSupportFragmentManager().popBackStack();
return true;
}
return super.onOptionsItemSelected(item);
}
you can try like this.
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
newFragment=new FragementA();
FragmentTransaction transaction=getFragmentManager().beginTransaction();
transaction.replace(R.id.myFragement,newFragment);
transaction.addToBackStack(null);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.commit();
return true;
}

Categories

Resources