I have 3 Fragments
inside a ViewPager
. I have different back button functionalities which I want to implement for each Fragment
. At the moment, I have created methods in each fragment which correspond to what I want the back button to do. I implemented an interface in my activity with the following methiod:
@Override
public void onCameraBack(int i) {
currFrag = i;
}
The idea here is that there are three fragments, each fragment calls this method in its onStart()
method. Fragment 0 passes 0, fragment 1 passes 1 and fragment 2 passes 2. So in this way the holding activity knows which fragment is visible. Now I am trying to get a reference to that fragment to be able to call the backbutton method I have implemented in it. I tried using this :
@Override
public void onBackPressed() {
if (currFrag == 0) {
}
else if (currFrag == 1) {
FragmentBTesting fragmentBTesting= new FragmentBTesting();
fragmentBTesting.FragmentBBack();
}
}`
but this doesn't work. I can't use the findFragmentbyId
method since my fragments do not have fragment tags in their XML, they fill the whole screen and their views are defined using linearLayouts
. My question is how can I get an instance of the fragment so I can call its FragmentBack()
method.
Here is my full activity
public class FragmentActivityTesting extends FragmentActivity implements FragmentATesting.logoutListener,FragmentBTesting.onCameraBack {
ViewPager viewPager = null;
SessionManager session = new SessionManager(MyApp.getContext());
int currFrag;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_activity_testing);
viewPager = (ViewPager) findViewById(R.id.pic_pager);
setStatusBarColor();
FragmentManager fragmentManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmentManager));
viewPager.setCurrentItem(1);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("CLOSE_ALL");
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
registerReceiver(broadcastReceiver, intentFilter);
}
@TargetApi(21)
public void setStatusBarColor() {
Window window = this.getWindow();
// clear FLAG_TRANSLUCENT_STATUS flag:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
// add FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS flag to the window
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
if (Integer.valueOf(android.os.Build.VERSION.SDK) >= 21) {
window.setStatusBarColor(this.getResources().getColor(R.color.green));
}
}
@Override
public void logout() {
session.logOut();
Intent a = new Intent(this,MainActivity.class);
startActivity(a);
Intent intent = new Intent("CLOSE_ALL");
this.sendBroadcast(intent);
finish();
}
@Override
public void onBackPressed() {
if (currFrag == 0) {
}
else if (currFrag == 1) {
FragmentBTesting fragmentBTesting= new FragmentBTesting();
fragmentBTesting.FragmentBBack();
}
}
@Override
public void onCameraBack(int i) {
currFrag = i;
}
}
class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
Fragment fragment = null;
if (position ==0) {
fragment = new FragmentATesting();
}
else if (position == 1) {
fragment = new FragmentBTesting();
}
else if (position == 2) {
fragment = new FragmentCTesting();
}
return fragment;
}
@Override
public int getCount() {
return 3;
}
}
Instead of telling your activity what fragment you are currently on, why not tell it what to execute when back is pressed?
In your activity you can have a field to hold the callback field (as a Runnable
, I know so much hate. You can make your own interface if you want), the setter, and then the onBackPressed
implementation. Here is a snippet from my code that works. Im using Guava's Optional
class, but you can null
it instead if you're into that kinda thing.
This is the Activity which should implement ActivityWithHomeButton
private Optional<? extends Runnable> backButtonListener = Optional.absent();
@Override
public void onBackPressed() {
// Check if there is a custom back button
if (backButtonListener.isPresent()) {
backButtonListener.get().run();
backButtonListener = Optional.absent();
} else {
super.onBackPressed();
}
}
@Override
public void setBackButtonListener(Optional<? extends Runnable> backButtonListener) {
this.backButtonListener = backButtonListener;
}
Here is the interface I implement in the activity
public interface ActivityWithHomeButton {
void setBackButtonListener(Optional<? extends Runnable> runnable);
}
and of course the usage from a fragment
parent.setBackButtonListener(Optional.of(new Runnable() {
@Override
public void run() {
// do back button stuff
}
}));
You can put this wherever you want in the fragment. You are also going to want to clear the back button listener whenever you no longer need it (onPause
). You can do this as such
parent.setBackButtonListener(Optional.<Runnable>absent());
Where parent
can be attained using the standard activity-fragment communication pattern detailed here (http://developer.android.com/training/basics/fragments/communicating.html). This code goes in your fragment
private ActivityWithHomeButton parent;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
parent = (ActivityWithHomeButton) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement ActivityWithHomeButton");
}
}
Hope it helps!