RecyclerView.Adapter is null in ViewPager Fragment - android

public class MainLibraryFragment extends Fragment implements PlaylistChangedInterface {
AudioItemSelectedListener mCallback;
// Container Activity must implement this interface
public interface AudioItemSelectedListener {
// public void onAudioItemSelected(int position);
public void onAudioItemSelected(Audio audioSelected);
}
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private Context context;
private ArrayList<Audio> listToDisplay;
private String TAG = "MainLibraryFragment";
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
context = getActivity();
MemoryManagement memoryManagement = new MemoryManagement(context);
listToDisplay = memoryManagement.loadAudioList(MemoryManagement.MAIN_LIST_KEY);
try {
//Expression is meaningless but tests if null.
//TODO, should catch this in loadAudioList.
if (listToDisplay.isEmpty()){}
} catch (NullPointerException e){
defaultList();
}
View rootView = inflater.inflate(R.layout.fragment_top_rated, container, false);
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerView.setHasFixedSize(true);
// use a linear layout manager
mLayoutManager = new LinearLayoutManager(getContext());
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), LinearLayoutCompat.VERTICAL));
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.addOnItemTouchListener(new CustomTouchListener(context, new onItemClickListener() {
#Override
public void onClick(View view, int index) {
mCallback.onAudioItemSelected(listToDisplay.get(index));
}
}));
mAdapter = new SongListAdapter2(listToDisplay, context);
mRecyclerView.setAdapter(mAdapter);
return rootView;
}
private void defaultList(){
listToDisplay = new ArrayList<>();
listToDisplay.add(new Audio("You need to add some songs!"));
}
#Override
public void playListChanged(ArrayList<Audio> arrayList) {
Log.d(TAG, "updateTop: in.");
if (!arrayList.isEmpty()) {
listToDisplay = arrayList;
}else {
defaultList();
}
updateListView();
Log.d(TAG, "updateTop: out.");
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = getContext();
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (AudioItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement AudioItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mCallback = null;
}
private void updateListView(){
Log.d(TAG, "updateTop: in.");
((SongListAdapter2) mAdapter).refreshList(listToDisplay);
Log.d(TAG, "updateTop: out.");
}
}
I have added refreshList():
public void refreshList(ArrayList<Audio> list) {
this.list = list;
notifyDataSetChanged();
}
And then the error message:
--------- beginning of crash
06-09 15:14:24.275 9114-9114/com.bteq.audia E/AndroidRuntime: FATAL
EXCEPTION: main
Process: com.bteq.audia, PID: 9114
java.lang.NullPointerException: Attempt to invoke virtual method 'void com.bteq.audia.SongListAdapter2.refreshList(java.util.ArrayList)' on a null object reference
at com.bteq.audia.MainLibraryFragment.updateListView(MainLibraryFragment.java:128)
at com.bteq.audia.MainLibraryFragment.playListChanged(MainLibraryFragment.java:100)
at com.bteq.audia.MainActivity.onDialogPositiveClick(MainActivity.java:195)
at com.bteq.audia.AddSongDialog$2.onClick(AddSongDialog.java:47)
at android.support.v7.app.AlertController$ButtonHandler.handleMessage(AlertController.java:166)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6753)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:482)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
06-09 15:14:24.281 9114-9114/com.bteq.audia W/OPDiagnose:
getService:OPDiagnoseService NULL
The MainActivity that contains the Pager. I tried to remove as much code as I could that wasn't relevant.
public class MainActivity extends AppCompatActivity implements MainLibraryFragment.AudioItemSelectedListener, AddSongDialog.NoticeDialogListener, ShowQueueDialog.ShouldClearAll {
private MemoryManagement memoryManagement;
private ViewPager viewPager;
private com.bteq.audia.PagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
memoryManagement = new MemoryManagement(this);
setContentView(R.layout.activity_main);
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
initialiseViews();
}
public void initialiseViews() {
//Fills the titles of all the tabs.
String[] tabTitles = getTabTitles();
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
for (int i = 0; i < tabTitles.length; i++) {
tabLayout.addTab(tabLayout.newTab().setText(tabTitles[i]));
}
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
//Sets up the ViewPager and creates the functionality to make them changeable.
viewPager = (ViewPager) findViewById(R.id.pager);
adapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
setupBottomView();
}
//method used as main control to the service from this activity.
private void audioActionDo(String audioAction) {
Intent intent = new Intent("audio_control_intent");
intent.putExtra("button_pressed", audioAction);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
/*
Method tells the activity which item in the shown playlist has been selected. This should then cause that item to play if possible.
//TODO, fill in body of method.
*/
#Override
public void onAudioItemSelected(Audio audio) {
songSelected(audio);
Log.d("MainActivity", "onAudioItemSelected: At end");
}
#Override
public void onDialogPositiveClick(String titleString, String artistString, String albumString, String genreString) {
Audio audioToAdd = new Audio(genreString, titleString, albumString, artistString);
memoryManagement.addAudioToList(audioToAdd, MemoryManagement.MAIN_LIST_KEY);
Fragment fragment = adapter.getItem(0);
PlaylistChangedInterface playlistChangedInterface = (PlaylistChangedInterface) fragment;
playlistChangedInterface.playListChanged(memoryManagement.loadAudioList(MemoryManagement.MAIN_LIST_KEY));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_top, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
//TODO, take the user to the app settings page.
// User chose the "Settings" item, show the app settings UI...
return true;
case R.id.action_favorite:
//TODO, make this favourite the current Audio.
// User chose the "Favorite" action, mark the current item
// as a favorite...
memoryManagement.clearPrefsValue(MemoryManagement.MAIN_LIST_KEY);
return true;
case R.id.action_add_new_song:
showAddSongDialog();
return true;
case R.id.action_show_queue:
showQueueDialog();
return true;
case R.id.action_add_from_internal:
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
public void showAddSongDialog() {
DialogFragment newFragment = new AddSongDialog();
newFragment.show(getSupportFragmentManager(), "missiles");
}
public void showQueueDialog() {
DialogFragment newFragment = new ShowQueueDialog();
newFragment.show(getSupportFragmentManager(), "showQueue");
}
//Should immediately play a song then be able to continue with the queued audio.
public void songSelected(Audio audioToAdd) {
}
//clears the entire queue but completes playback of current audio.
private void clearCurrentQueue() {
memoryManagement.clearPrefsValue(MemoryManagement.QUEUE_KEY);
}
// Utility method. Returns the locale titles for the tabs in the viewpager.
private String[] getTabTitles() {
return getResources().getStringArray(R.array.tab_titles);
}
#Override
public void clearAllPressed() {
clearCurrentQueue();
}
private void setupBottomView() {
ImageView playButton = (ImageView) findViewById(R.id.bottom_play);
ImageView replayButton = (ImageView) findViewById(R.id.bottom_replay);
ImageView skipBackButton = (ImageView) findViewById(R.id.bottom_skip_back);
ImageView skipForwardButton = (ImageView) findViewById(R.id.bottom_skip_next);
ImageView shuffleButton = (ImageView) findViewById(R.id.bottom_shuffle);
playButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// playAudio(storageUtility2.loadAudioIndex());
audioActionDo(getResources().getString(R.string.broadcast_action_playpause));
}
});
replayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
audioActionDo(getResources().getString(R.string.broadcast_action_loop));
}
});
skipBackButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
audioActionDo(getResources().getString(R.string.broadcast_action_skip_back));
}
});
skipForwardButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
audioActionDo(getResources().getString(R.string.broadcast_action_skip_forward));
}
});
shuffleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
audioActionDo(getResources().getString(R.string.broadcast_action_shuffle));
}
});
}
}
I get a null pointer exception whenever the method updateListView is called. The fragment initially displays with no problem, but when a new entry is added to the ArrayList and the updateListView is called - it stops. The log shows that mAdapter is null. I don't know enough about android yet to understand why mAdapter becomes null after it is used before.
Sorry for large amount of code but I'm completely stumped. Thanks.

In my opinion this is because your variable mAdapter is declared as of type RecyclerView.Adapter which is an interface which does not declare your method, refreshList(). Therefore if you intend to use the type RecyclerView.Adapter, only the methods declared in the interface could be called by using the reference variable. If you intend to call methods implemented by yourself other than whats overridden from the interface, the reference type SongListAdapter2 has to be used.
Simple fix is to change the RecyclerView.Adapter to SongListAdapter2 at the declaration of the mAdapter.
Ps. Check android docs to see the methods declared by the RecyclerView.Adapter.

It depends on how you are accessing the adapter in the RecyclerView. If you look at this line Fragment fragment = adapter.getItem(0), you are trying to access the first fragment in your ViewPager's adapter. getItem usually won't get called again after the ViewPager has layout its fragments which means your call to access the RecyclerView's adapter in the first fragment in the ViewPager will be pointing to a null adapter even though the fragment might exist (and you might even be calling a wrong fragment). Use this Fragment fragment = getChildFragmentManager().getFragments().get(0) to access the right fragment which will ensure the RecyclerView adapter won't be null. Change getChildFragmentManager() to getFragmentManager() if your ViewPager is in an Activity.

Related

onSaveInstanceState null in Fragment everytime

I search everywhere and for the solution but not find it, I need some help.
I have an app that has Two activity's, Activity A and Activity B, but B have fragments, the first fragment from B, have an important data that I don't want to lose when the user press back when going to Activity A.
My problem is this every time I'm back to Activity A and go to B, my Data go empty because android clear it, so I made some search and changes on the code and still not find the solution. Now my code :
ACTIVITY A
fbReceive.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, OmniActivity.class));
}
});
I call B from this line and when they go to B this is the code :
ACTIVITY B
public class OmniActivity extends BaseActivity {
private View parent_view;
private TabLayout tab_layout;
FragmentOmni fragmentOmni = new FragmentOmni();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_omni_om);
parent_view = findViewById(R.id.container);
Tools.setSystemBarColor(this, R.color.new_purple_O200);
openFragment(fragmentOmni);
initToolbar();
initComponent();
}
public void openFragment(final Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.containerView, fragment, fragment.getTag());
transaction.addToBackStack(null);
transaction.commit();
}
#Override
public void onBackPressed() {
Intent intent = new Intent(this, MainActivity.class);
startActivityForResult(intent, 1);
}
private void initToolbar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Voltar");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.getNavigationIcon().setColorFilter(getResources().getColor(android.R.color.white), PorterDuff.Mode.SRC_ATOP);
toolbar.setNavigationOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
Intent intent = new Intent(OmniActivity.this, MainActivity.class);
startActivityForResult(intent, 1);
}
});
}
And when the application executes OpenFragment() they go to this code from Fragment :
FRAGMENT A
public class FragmentOmni extends Fragment {
RecyclerView recyclerView;
MDOmniturn controller;
List<HashMap<String, String>> listproduct;
private ArrayList<Product> producttypelist;
Product tpobjproduct;
private ActionMode actionMode;
private ActionModeCallback actionModeCallback;
private ListProductAdapter lpAdapter;
private NestedScrollView nested_scroll_view;
private ImageButton bt_toggle_input;
private Button bt_hide_input;
private View lyt_expand_input;
EditText edOmni, edMani,edEan ;
LinearLayout layoutNoResult;
Handler time;
TextWatcher textexample;
private ProgressBar progressBarProduct;
LinearLayout linearLayout;
public FragmentOmni() {
}
public static FragmentOmni newInstance() {
FragmentOmni fragment = new FragmentOmni();
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if(savedInstanceState != null){
producttypelist = savedInstanceState.getParcelableArrayList("list");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_omni, container, false);
return root;
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("list", producttypelist);
super.onSaveInstanceState(outState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (savedInstanceState != null) {
producttypelist = savedInstanceState.getParcelableArrayList("list");
}
initexpand(view);
linearLayout = (LinearLayout) view.findViewById(R.id.container);
edOmni = (EditText) view.findViewById(R.id.edOmni);
edMani = (EditText) view.findViewById(R.id.edBManifesto);
edEan = (EditText) view.findViewById(R.id.edEan);
progressBarProduct = (ProgressBar) view.findViewById(R.id.progressBarProduct);
layoutNoResult = (LinearLayout) view.findViewById(R.id.layoutNoResult);
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.addItemDecoration(new LineItemDecoration(getActivity(), LinearLayout.VERTICAL));
recyclerView.setHasFixedSize(true);
controller = new MDOmniturn(getActivity());
producttypelist = new ArrayList<>();
listproduct = new ArrayList<>();
addListenerTextChange(edOmni);
//set data and list adapter
lpAdapter = new ListProductAdapter(getActivity(), producttypelist);
recyclerView.setAdapter(lpAdapter);
lpAdapter.setOnClickListener(new ListProductAdapter.OnClickListener() {
#Override
public void onItemClick(View view, Product obj, int pos) {
if (lpAdapter.getSelectedItemCount() > 0) {
enableActionMode(pos);
} else {
// read the inbox which removes bold from the row
Product product = lpAdapter.getItem(pos);
Toast.makeText(getActivity(), "Read: " + product.prd_description, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onItemLongClick(View view, Product obj, int pos) {
enableActionMode(pos);
}
});
actionModeCallback = new ActionModeCallback();
}
The savedInstanceState from FRAGMENT A always go NULL, what i'm doing wrong?
Replace your code to the following order
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("list", producttypelist);
}
It might be possible you are expecting data during the wrong state too.
For example, the savedInstanceState will always be null the first time an Activity is started which also points to your fragment, but may be non-null if an Activity is destroyed during rotation, because onCreate is called each time activity starts or restarts.
This line transaction.addToBackStack(null); is unnecessary. You can save the fragment state on its onStop() and onPause() and restore onResume() and onCreate().
You can remove the onBackPressed() in Activity B now
Alternatively, you can use Shared Preferences. When exiting the application, (onBackPressed, onPause ...) save the item you want. For Example the high score of a game.
activity.getSharedPreferences(getString(R.string.app_name),
Context.MODE_PRIVATE).edit().putInt("score", highScore).apply();
And retrieving the score would be:
int value = activity.getSharedPreferences(getString(R.string.app_name),
Context.MODE_PRIVATE).getInt("score", 0);

How can I implement OnClickListener of an ImageView in a fragment?

Can anyone kindly help me implement the opening of a new activity upon clicking of an ImageView. I have a code snippet displayed below.
public class TabFan extends Fragment {
//Overriden method onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
return inflater.inflate(R.layout.tab_fan, container, false);
// Onclick Listening
ImageView image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(this);
}
public void onClick(View v) {
// Launching new Activity on hitting the image
Intent j = new Intent(getApplicationContext(), Activity2.class);
startActivity(j);
// End intent
}
}
Ok I have a code with three tabs, the following controls my tabs which is working right.
public class Fans extends AppCompatActivity implements TabLayout.OnTabSelectedListener{
//This is our tablayout
private TabLayout tabLayout;
//This is our viewPager
private ViewPager viewPager;
ImageView image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fans);
//Adding toolbar to the activity
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Initializing the tablayout
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
//Adding the tabs using addTab() method
tabLayout.addTab(tabLayout.newTab().setText("Fans"));
tabLayout.addTab(tabLayout.newTab().setText("Jersey"));
tabLayout.addTab(tabLayout.newTab().setText("Team"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
//Initializing viewPager
viewPager = (ViewPager) findViewById(R.id.pager);
//Creating our pager adapter
Pager adapter = new Pager(getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
}
I have another class pager
public class Pager extends FragmentStatePagerAdapter {
//integer to count number of tabs
int tabCount;
//Constructor to the class
public Pager(FragmentManager fm, int tabCount) {
super(fm);
//Initializing tab count
this.tabCount= tabCount;
}
//Overriding method getItem
#Override
public Fragment getItem(int position) {
//Returning the current tabs
switch (position) {
case 0:
TabFan tab1 = new TabFan();
return tab1;
case 1:
TabJersey tab2 = new TabJersey();
return tab2;
case 2:
TabTeam tab3 = new TabTeam();
return tab3;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
}
Finally the interested raw class TabFan, now where exactly should that listener be implemented. I have tried the class Fans but apparently am getting some crush, TabFan seem not to work with the events too. Any help please.
public class TabFan extends Fragment {
//Overriden method onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
return inflater.inflate(R.layout.tab_fan, container, false);
// Onclick Listener
}
}
With the code that you have provided, you will need to do two things to properly link the image object to the onClick() method that you have written.
First, the Fragment class needs to implement the View.OnClickListener interface. This is what makes the onClick(View v)actually activate on a click when using setOnClickListener(this). Replace your class declaration line with:
public class TabFan extends Fragment implements View.OnClickListener {
Second, if you are going to add any more clickable objects to TabFan with setOnClickListener(this), then onClick(View v) needs to verify that it is dealing with the expected View:
#Override
public void onClick(View v) {
if (v.getId() == R.id.image) {
// Launching new Activity on hitting the image
Intent j = new Intent(getActivity().getApplicationContext(), Activity2.class);
startActivity(j);
// End intent
}
}
If you click Ctrl + Space keys, Android Studio will show you suggestion window and generate overriding methods like onClick for you.
image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent j = new Intent(getActivity(), Activity2.class);
startActivity(j);
}
});
Doesn't matter where you are, in Fragment or in Activity. ImageView just needs View.OnClickListener. for detecting click events override onClick method.
And another point when you need any context in fragment use getActivity() or getActivity().getApplicationContext()
What I like to do is setting up the onClick in the XML already like this:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="yourMethod"
android:src="#drawable/yourpicture"/>
Then in your Fragment or Activity just implement yourMethod to open the new Activity:
public void yourMethod(View v) {
Intent intent = new Intent(this, ToOpenAcitivy.class);
startActivity(intent);
}
Also this site helped me a lot when learning about stuff like this.

ViewPager Fragments And CircleIndicator Re-Create Itself

Good day, I'm having a problem regarding with viewPager and CircleIndicator.
Every time I switch to another Activity or press the
TAB hardware keyboard panel (the switching tab between apps), and go back
to WelcomeActivity.java it re-create itself - circleDots and the items in the fragments (re-create fragments).
And also if I press the TAB hardware keyboard in the panel, and re-enter my app, it will not allow me to go back directly, it splash white then disappeared .
And if I click the icon to go back to my app, it re-create the fragments. Can you help me with this?
Here my code: WelcomeActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome_page);
//Function Call
assignWidgetId();
//ViewPager for text AppIntro
mViewPager = (ViewPager) findViewById(R.id.viewpager_welcome_msg);
circlePageIndicator = (CirclePageIndicator) findViewById(R.id.circle_indicator);
setUpViewPager(mViewPager);
circlePageIndicator.setViewPager(mViewPager);
runnable = new Runnable() {
#Override
public void run() {
int currentPage = 0;
if(currentPage == FRAGMENT_PAGE - 1){
currentPage = 0;
}
mViewPager.setCurrentItem(currentPage,true);
handler.postDelayed(runnable,DELAY_TIME_CHANGE_SLIDE);
}
};
swipeTimer = new Timer();
try{
mVideoView = (VideoView) findViewById(R.id.yayong_welcome_video);
mVideoView.setVideoURI(uri);
mediaPlayer.setVolume(0, 0);
mVideoView.start();
} catch (Exception e){
//mImageView.setVisibility(View.VISIBLE);
}
//IF ERROR VIDEO CANNOT BE PLAYED
mVideoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
//wait for 1 seconds
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
//mImageView.setVisibility(View.VISIBLE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
if (videoCompleted) {
mVideoView.start();
mediaPlayer.setVolume(0, 0);
}
return false;
}
});
//IF COMPLETE REPEAT AGAIN - SILENT
mVideoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
videoCompleted = true;
mVideoView.start();
mediaPlayer.setVolume(0, 0);
}
});
}
public void assignWidgetId(){
btnSignIn = (Button) findViewById(R.id.signIn);
btnSignIn.setOnClickListener(this);
btnSignUp = (Button) findViewById(R.id.signUp);
btnSignUp.setOnClickListener(this);
textViewForgotPass = (TextView) findViewById(R.id.textViewForgotPassword);
textViewForgotPass.setOnClickListener(this);
//mImageView = (ImageView) findViewById(R.id.welcome_image_backup);
}
#Override
public void onClick(View v) {
switch (v.getId()){
//GO TO LOGIN ACTIVITY
case R.id.signIn:
Intent intentSignIn = new Intent(WelcomePageActivity.this,LoginActivity.class);
startActivity(intentSignIn);
finish();
break;
//GO TO REGISTER ACTIVITY
case R.id.signUp:
Intent intentSignUp = new Intent(WelcomePageActivity.this,RegisterActivity.class);
startActivity(intentSignUp);
finish();
break;
case R.id.textViewForgotPassword:
forgotPasswordDialog();
break;
}
}
public void setUpViewPager(ViewPager viewPager){
Adapter adapter = new Adapter(getSupportFragmentManager());
adapter.addFragments(new Welcome_First_Fragment());
adapter.addFragments(new Welcome_Fragment_Second());
adapter.addFragments(new Welcome_Fragment_Third());
viewPager.setAdapter(adapter);
}
static class Adapter extends FragmentPagerAdapter{
private static List<Fragment> mFragmentList = new ArrayList<>();
public Adapter(FragmentManager fragmentManager){
super(fragmentManager);
}
public void addFragments(Fragment fragment){
mFragmentList.add(fragment);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
}
WelcomeFragments.java
public class Welcome_First_Fragment extends Fragment {
RelativeLayout relativeLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View viewRoot = inflater.inflate(R.layout.welcome_fragment_first, container,false);
relativeLayout = (RelativeLayout) viewRoot.findViewById(R.id.welcome_about_first);
return viewRoot;
}
I'm using jake wharton viewpager circleIndicator
I solved this by using System.exit(0); every time I go back to this page, so that it will not re-create the items. I know this is not the best way. Is there any alternative way?

How do I add a new tab with fragments

So I want to create 3 tabs, all different from each other. The xml I have that covered. But not how to create the tabs without it crashing my app.
I have implemented the swipe tab with viewpage.
http://developer.android.com/training/implementing-navigation/lateral.html
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
and part of
http://www.java2s.com/Code/Android/UI/Demonstrateshowfragmentscanparticipateintheoptionsmenu.htm
When I try to go to the next tab(swipe does work no problem) I get an error:
07-08 22:07:57.414: E/AndroidRuntime(6865): FATAL EXCEPTION: main
07-08 22:07:57.414: E/AndroidRuntime(6865): Process: com.cyberdog.magiceasydraft, PID: 6865
07-08 22:07:57.414: E/AndroidRuntime(6865): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.view.ViewPager.setCurrentItem(int)' on a null object reference
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.cyberdog.magiceasydraft.addPlayersfragmentTab.doPositiveClick(addPlayersfragmentTab.java:113)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.cyberdog.magiceasydraft.addPlayersfragmentTab$MyAlertDialogFragment$1.onClick(addPlayersfragmentTab.java:165)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:160)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.os.Handler.dispatchMessage(Handler.java:102)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.os.Looper.loop(Looper.java:135)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.app.ActivityThread.main(ActivityThread.java:5274)
07-08 22:07:57.414: E/AndroidRuntime(6865): at java.lang.reflect.Method.invoke(Native Method)
07-08 22:07:57.414: E/AndroidRuntime(6865): at java.lang.reflect.Method.invoke(Method.java:372)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
So.. what am I doing wrong here? I can see that there is a null reference to my create round fragment... but I have no clue how to fix this. This is my first time working with fragments and tabs.
code:
main activity:
public class CreateDraft extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private fragmentPageAdapter mAdapter;
private ActionBar actionBar;
private Fragment addPlayer, createRound,score;
private String[] tabs = { "Add players", "Create round", "Score" };
public static final String CuSToM_FRAGMENT_KEY ="ADD_PLAYER_TAB";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_draft);
viewPager = (ViewPager) findViewById(R.id.activity_viewpager_main);
actionBar = getActionBar();
mAdapter = new fragmentPageAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
if(savedInstanceState == null){
FragmentManager fm = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
addPlayer = fm.findFragmentByTag("Add Players");
if(addPlayer == null){
addPlayer = new addPlayersfragmentTab();
ft.add(addPlayer, "Add players");
}
createRound = fm.findFragmentByTag("Create round");
if(createRound == null){
createRound = new createRoundfragmentTab();
ft.add(createRound, "Create round");
}
score = fm.findFragmentByTag("Score");
if(score == null){
score = new scoreResultfragmentTab();
ft.add(score, "Score");
}
ft.commit();
}
//
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
public void passBundleToFragment(int position){
if(true){
}
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
private void hiddenKeyboard(View v) {
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
One of the fragments(others don't contain much code yet):
public class addPlayersfragmentTab extends Fragment {
private Button addPlayer, createDraft;
private EditText evAddPlayer;
private ViewPager viewPager;
private List<Player> players;
private ListView lvAddedPlayers;
ListAdapter adapter;
private boolean buttonCreateDraftPressed= false;
public boolean isButtonCreateDraftPressed() {
return buttonCreateDraftPressed;
}
public void setButtonCreateDraftPressed(boolean buttonCreateDraftPressed) {
this.buttonCreateDraftPressed = buttonCreateDraftPressed;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.draft_adding_players,
container, false);
initialiseEditAndText(rootView);
players = new ArrayList<Player>();
lvAddedPlayers = (ListView) rootView.findViewById(
R.id.lv_players_adding);
adapter = new ListAdapter(rootView.getContext(), players);
lvAddedPlayers.setAdapter(adapter);
addPlayer = (Button) rootView.findViewById(R.id.button_total_player);
createDraft = (Button) rootView.findViewById(R.id.button_create_draft);
addPlayer.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Player player = new Player(evAddPlayer.getText().toString());
players.add(player);
adapter.notifyDataSetChanged();
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
});
createDraft.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (adapter != null && players != null) {
createdraft(players.size());
} else {
Toast.makeText(getActivity(),
"Add minimal 3 players to start the draft.",
Toast.LENGTH_LONG).show();
}
}
});
return rootView;
}
public void showDialog(){
DialogFragment newFragment = new MyAlertDialogFragment().newInstance(R.string.recreate_draft);
newFragment.show(getFragmentManager(), "dialog");
}
public void doPositiveClick(){
viewPager.setCurrentItem(1);
}
public void doNegativeClick(){
}
public int getTotalPlayers() {
return players.size();
}
public List<Player> getPlayersNames() {
return players;
}
public void initialiseEditAndText(View rootView) {
evAddPlayer = (EditText) rootView.findViewById(R.id.et_player_name);
}
public void createdraft(int totalplayers) {
if (totalplayers >= 3 && totalplayers <= 16) {
showDialog();
} else {
Toast.makeText(getActivity(),
"Minimum of 3 and maximum of 16 players.",
Toast.LENGTH_LONG).show();
}
}
public class MyAlertDialogFragment extends DialogFragment{
public MyAlertDialogFragment newInstance(int title){
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.abc_ic_search)
.setTitle(title)
.setPositiveButton("R.string.alert_dialog_ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addPlayersfragmentTab.this.doPositiveClick();
}
}
)
.setNegativeButton("R.string.alert_dialog_cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addPlayersfragmentTab.this.doNegativeClick();
}
}
)
.create();
}
}
}
EDIT:
pageadpter:
public fragmentPageAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
#Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new addPlayersfragmentTab();
case 1:
// Games fragment activity
return new createRoundfragmentTab();
case 2:
// Movies fragment activity
return new scoreResultfragmentTab();
}
return null;
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return 3;
}
}
edit 2:
I followed the passing of data to the activity, that did work, however if I wanted to pass the data from the activity(that got the data from the addPlayerTab) i am getting a null reference again, this time i think becuase the id is wrong. but my layoutfile dont use . So how will i find the fragment?
code:
the interface implementation of the addPlayerTab:
#Override
public void onButtonClickCreateRound(int position, List<Player> players) {
viewPager.setCurrentItem(position);
this.players = players;
GetPlayer();
}
code in addPlayerTab:
public interface GoToCreateRoundListener{
public void onButtonClickCreateRound(int position, List<Player> players);
}
public void onAttach(Activity activity){
super.onAttach(activity);
try{
goCreateRound = (GoToCreateRoundListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+" must implement GoToRoundListener");
}
}
public void createdraft(int totalplayers) {
if (totalplayers >= 3 && totalplayers <= 16) {
goCreateRound.onButtonClickCreateRound(1, players);
} else {
Toast.makeText(getActivity(),
"Minimum of 3 and maximum of 16 players.",
Toast.LENGTH_LONG).show();
}
}
this is the interface implementation for passing the data to the createroundtab:
#Override
public void GetPlayer() {
createRoundfragmentTab createRoundfragmentTab = (createRoundfragmentTab)getSupportFragmentManager().findFragmentById(R.layout.create_round);
createRoundfragmentTab.makeRandomFirstRound(players);
}
code in the createroundTab:
public interface GetPlayersFromAddPlayersListener{
public void GetPlayer();
}
public void onAttach(Activity activity){
super.onAttach(activity);
try{
getPlayers = (GetPlayersFromAddPlayersListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+" must implement GetPlayersFromAddPlayersListener");
}
}
I've already shared my point on Fragment instantiation above so I'll just quote myself again.
That whole if (savedInstance == null) block is not required because Fragment instantiation is the job of your PagerAdapter. The ViewPager will call PagerAdapter#getItem() when it sees fit to.
Although, it's fairly obvious that the NullPointerException is caused by an uninitialized ViewPager reference inside your addPlayersfragmentTab, the whole approach of either passing the view pager to the fragment at creation or the fragment accessing it through a getter is wrong.
The reason is that a fragment is a self-contained reusable implementation of a part of your UI and hence it should not couple itself with the activity hosting it. Once you couple it with your view pager, you can never host this fragment in any other normal activity again. In short, the fragment does not remain reusable anymore.
So, then how is a fragment supposed to communicate with its host activity? Well, using Callback Interfaces. Here is a short tutorial from the official Android developers site: Communicating with Other Fragments but it works the same for requesting the activity to do anything on behalf of the fragment.
In your case, you would inform the main activity that the user pressed OK at the alert dialog and the activity would respond to that by moving to the next tab using the view pager.
Usually when you want to catch hold of a Fragment again, you either use findFragmentById() or its custom tag with findFragmentByTag(). But, the whole ViewPager and its PagerAdapter doesn't expose these properties to us.
So, to enable the fragment look-ups, you need to hold references to them inside your PagerAdapter. Something along the lines of the following.
Map<String, Fragment> mFragments = new HashMap<>(3);
...
#Override
public Fragment getItem(int index) {
...
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
// super calls getItem() if fragment is not already instantiated
Fragment fragment = (Fragment) super.instantiateItem(container, position);
mFragments.put(fragment.getClass().getSimpleName(), fragment);
return fragment;
}
public Fragment getFragment(String name) {
return mFragments.get(name);
}
#Override
public int getCount() {
return 3;
}
With the above changes, your GetPlayer() implementation would now become
#Override
public void GetPlayer() {
createRoundfragmentTab createRoundfragmentTab = (createRoundfragmentTab)
((fragmentPageAdapter) mAdapter).getFragment("createRoundfragmentTab");
createRoundfragmentTab.makeRandomFirstRound(players);
}
To understand this approach in more details please do read ViewPager and fragments — what's the right way to store fragment's state?.
As an aside, please also take a look at Java naming conventions recommended by Oracle. Long story short, you need to start your class names with an upper case letter and do the opposite with your method names. Following these conventions would make your code easier to read and thus more understandable. Currently, all your class names appear as variable names to seasoned Java developers.
You didn't initialize viewPager field of your fragment (addPlayersfragmentTab.viewPager). That's why you got NullPointerException.
You can do getViewPager() method in activity and after that call it from fragment, i.e. ((CreateDraft) getActivity()).getViewPager().setCurrentItem(1)

Using backstack and back button in viewpager

I'm using a viewpager to swipe between fragments and would like the back button to navigate to the previously viewed fragment rather than ending the activity. Sorry if this is a duplicate of this question however I didn't find the answer very helpful. Obviously onBackPressed needs to be overridden, but I don't know how to get and display the correct fragment. I assume that I should use the fragmentmanager's backstack, but getSupportFragmentManager().getBackStackEntryCount() always returns 0. Do I need to manually add fragments to the backstack using FragmentTransaction.addToBackStack()? If so, where would I add this in my adapter?
Here is the code for my activity,
public class PagerActivity extends FragmentActivity {
ArrayList<Sale> sales;
MyAdapter mAdapter;
ViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent it = getIntent();
this.sales = (ArrayList<Sale>) it.getExtras().get("sales");
int position = it.getExtras().getInt("position");
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.fragment_pager);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setCurrentItem(position);
}
public class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public int getCount() {
return sales.size();
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
#Override
public Fragment getItem(int position) {
SalesThumbFragment frag = new SalesThumbFragment();
return frag.newInstance(sales.get(position));
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.sales_controller, menu);
return true;
}
#Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount() != 0) {
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
In new design support library, i use this
I have same issue and i follow this step
In the main activity where there are 3 fragment in viewpager i create stack
and push and pop data.
//private Stack<Integer> stackkk; ==> As i get edit suggestion
private Stack<Integer> stackkk = new Stack<>(); // Edited
private ViewPager mPager;
private int tabPosition = 0;
mTabLayout.setupWithViewPager(mPager);
mPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
mTabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
tabPosition = tab.getPosition();
mPager.setCurrentItem(tab.getPosition());
if (stackkk.empty())
stackkk.push(0);
if (stackkk.contains(tabPosition)) {
stackkk.remove(stackkk.indexOf(tabPosition));
stackkk.push(tabPosition);
} else {
stackkk.push(tabPosition);
}
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
tabPositionUnselected = tab.getPosition();
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
and in the onBackPressed in activity,
#Override
public void onBackPressed() {
if (stackkk.size() > 1) {
stackkk.pop();
mPager.setCurrentItem(stackkk.lastElement());
} else {
}
}
Use this code in Fragment Activity class. Don't forget to add return true;
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
mViewPager.setCurrentItem(viewPageSelected - 1);
return true;
}
return super.onKeyDown(keyCode, event);
}
I had a similar problem, this is how I solved it. I think you can adapt the code to your problem, if I understood what you problem is. I had a ViewPager with 6 fragments and wanted to keep track of the page history and to be able to use the back button to navigate backwards in the history. I create a java.util.Stack<Integer> object, add fragment numbers to it (except when you use the back button, see below), and override onBackPressed() to make it pop the last viewed fragment instead of using the back stack, when my history stack is not empty.
You want to avoid pushing elements on the Stack when you press the back button, otherwise you will get stuck between two fragments if you keep using the back button, instead of eventually exiting.
My code:
MyAdapter mAdapter;
ViewPager mPager;
Stack<Integer> pageHistory;
int currentPage;
boolean saveToHistory;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.container);
mPager.setAdapter(mAdapter);
mPager.setOffscreenPageLimit(5);
pageHistory = new Stack<Integer>();
mPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageSelected(int arg0) {
if(saveToHistory)
pageHistory.push(Integer.valueOf(currentPage));
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
saveToHistory = true;
}
#Override
public void onBackPressed() {
if(pageHistory.empty())
super.onBackPressed();
else {
saveToHistory = false;
mPager.setCurrentItem(pageHistory.pop().intValue());
saveToHistory = true;
}
};
If you use a field to keep track of the index of the previous page using mPager.getCurrentItem() after each time the user navigates to a new fragment, then in the onBackPressed() method, you should be able to call mPager.setCurrentItem(previousPage)
Or, if the user can only page in order, then you don't need a field at all, and you could just do mPager.setCurrentItem(mPager.getCurrentItem()-1)
I've made custom ViewPager and implement stack functionality in it.
public class CustomViewPager extends ViewPager {
private Stack<Integer> stack = new Stack<>();
#Override
public void setCurrentItem(int item, boolean smoothScroll) {
stack.push(getCurrentItem());
super.setCurrentItem(item, smoothScroll);
}
public int popFromBackStack(boolean smoothScroll) {
if (stack.size()>0) {
super.setCurrentItem(stack.pop(), smoothScroll);
return getCurrentItem();
} else return -1;
}

Categories

Resources