I make a FragmentPagerAdapter
There is a fragment which has a pager.
And the pager show 3 fragments and it works well.
But, After application cache clearing,
(It means... long time has passed application service backgrounded)
only pager showing up and 3 fragments have empty layout (white space).
As a result checking Log, I caught some problem lines...
After clearing cache, SectionsPagerAdapter() constructure called then
getItem() method never called.
Please Help me
public class ReviewFragment extends SherlockFragment {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.review_fragment, container, false);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState == null) {
mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
mViewPager = (ViewPager) getActivity().findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return new BFragment();
} else {
return new CFragment();
}
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "1";
case 1:
return "2";
}
return null;
}
}
Related
My app have a fragmentActivity with tabBar which control over the view pager and contain 3 fragments ,when i update my class User in fragmentB,i need to display him in fragmentC.
my question is how to refresh fragmentC every time when i add new User.
before i wrote this question i tried all the solution from this questions:
1.Update ViewPager dynamically?
2.refresh fragment at reload
3.Update Fragment from ViewPager
4.ViewPager PagerAdapter not updating the View
5.How to update fragment content from activity (viewpager)?
here is my code
FragmentActivity:
public class MainActivityTab extends FragmentActivity {
public SectionsPagerAdapter mSectionsPagerAdapter;
public ViewPager mViewPager;
public static MainActivityTab instance = null;
public static MainActivityTab getInstance(){
return instance;
}
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_tab);
getWindow().setStatusBarColor(Color.rgb(191,76,12));
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
final TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setIcon(R.drawable.icon_A);
tabLayout.getTabAt(1).setIcon(R.drawable.icon_B);
tabLayout.getTabAt(2).setIcon(R.drawable.icon_C);
mViewPager.setCurrentItem(1,false);
}
FragmentStatePagerAdapter:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return FragmentA.newInstance();
case 1:
return FragmentA.newInstance();
case 2:
return FragmentC.newInstance();
default:
return null;
}
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}
}
FragmentB:
public class FragmentB extends Fragment {
EditText name;
EditText age;
Button btnSave;
public static FragmentB newInstance() {
FragmentB fragment = new FragmentB();
return fragment;
}
public FragmentB() {}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new2, container, false);
name = (EditText) rootView.findViewById(R.id.name);
age = (EditText) rootView.findViewById(R.id.age);
btnSave = (Button) rootView.findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UserManager.getInstance().creteUser(name.getText().toString(),age.getText().toString());
}
});
return rootView;
}
}
FragmentC:
public class FragmentC extends Fragment {
TextView nameTxt;
TextView ageTxt;
public static FragmentC newInstance(){
FragmentC instance = new FragmentC();
return instance;
}
public FragmentC(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_new3, container, false);
nameTxt = (TextView) rootView.findViewById(R.id.nameTxt);
ageTxt = (TextView) rootView.findViewById(R.id.ageTxt);
showUser();
return rootView;
}
public void showUser(){
if(UserManager.getInstance().getUser().getName()!=null){
nameTxt.setText(UserManager.getInstance().getUser().getName().toString());
ageTxt.setText(UserManager.getInstance().getUser().getAge().toString());
}
}
}
You could create a callback like:
public interface UserChangedCallback{
void onUserChanged();
}
and implement this callback on every view/fragment where you want to access the user:
#Override
public void onUserChanged() {
adapter.notifyDataSetChanged();
// or if you don't have an adapter refresh your textfields or whatever you want
}
Register the callback on the usermanager via UserManager.getInstance().registerCallback(this). Internally the usermanager have to add the callback to an internal list.
Create a private function inside your usermanager:
private void notifyCallbacks() {
for(UserChangedCallback callback : registeredCallbacks) {
callback.onUserChanged();
}
}
If you add/modify/delete a user you always have to call this function at the end. For example:
public void addUser(User user) {
users.add(user);
notifiCallbacks();
}
Now every view will be notified and refreshed.
Important!
Don't forget to unregister the callback from the usermanager on onDestroy() to avoid memory leaks.
Found solution:
i used in the method onPageSelected,when position is 2 my fragment detach and afterwards attach the fragment.
working perfectly!
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position==2){
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction().add(R.id.fragmant_new3, FragmentC.newInstance());
fragmentTransaction.detach(FragmentC.newInstance());
fragmentTransaction.attach(FragmentC.newInstance());
fragmentTransaction.commit();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I am a newbie with Fragments. I have 5 different Fragmentsin my TabLayout. In each fragment I am loading data from the server.
My problem is as follows:
When the first fragment loads it calls the function and loads data from the server and displays on the RecyclerView.
Then When I swipe to the second tab the server data loads and so on. But when I swipe again to say fragment one the data is loading again from the server and the RecyclerView needs to be set again.
Is there anyway where I can load the server data only once (without saving it to a local database) and set the recyclerview only once so that no matter how many times I swipe the tab the data does not load again? I have referred here but i really didnt understand how to solve my problem.I am posting a snippet of my code.
TabActivity
public class TabActivity extends AppCompatActivity {
ViewPager viewpager;
Toolbar toolbar;
TabLayout tablayout;
ViewPagerAdapter viewPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_activity);
initialize();
}
private void initialize() {
viewpager = (ViewPager) findViewById(R.id.viewpager);
toolbar = (Toolbar) findViewById(R.id.toolbar);
tablayout = (TabLayout) findViewById(R.id.tablayout);
setSupportActionBar(toolbar);
viewPagerAdapter=new ViewPagerAdapter(getSupportFragmentManager());
viewpager.setAdapter(viewPagerAdapter);
tablayout.setTabsFromPagerAdapter(viewPagerAdapter);
tablayout.setupWithViewPager(viewpager);
}
}
class ViewPagerAdapter extends FragmentStatePagerAdapter implements ViewPager.OnPageChangeListener {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:return LocatedEvents.newInstance();
case 1:return QrCodeScanner.newInstance();
case 2:return NewsFeed.newInstance();
case 3:return CreatePoll.newInstance();
case 4:return MyProfile.newInstance();
}
return NewsFeed.newInstance();
}
#Override
public int getCount() {
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
return "Tab " + (position + 1);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
}
NewsFeed Fragment
public class NewsFeed extends Fragment {
#Nullable
public static NewsFeed newInstance() {
return new NewsFeed();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.newsfeed_fragment, container, false);
load_data();
return view;
}
}
Avoid creating new Fragments every time in
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return LocatedEvents.newInstance();
case 1:
return QrCodeScanner.newInstance();
case 2:
return NewsFeed.newInstance();
case 3:
return CreatePoll.newInstance();
case 4:
return MyProfile.newInstance();
}
return NewsFeed.newInstance();
}
Make an array of fragments and pass it to your Adapter.Something like this
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
initFragments();
}
private void initFragments() {
ArrayList < Fragment > fragmentArrayList = new ArrayList < > ();
fragmentArrayList.add(LocatedEvents.newInstance());
fragmentArrayList.add(QrCodeScanner.newInstance());
fragmentArrayList.add(NewsFeed.newInstance());
fragmentArrayList.add(MyProfile.newInstance();
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager(), fragmentArrayList); viewpager.setAdapter(viewPagerAdapter); tablayout.setTabsFromPagerAdapter(viewPagerAdapter); tablayout.setupWithViewPager(viewpager);
}
And in your adapter change it to
private ArrayList < Fragment > fragments;
public ViewPagerAdapter(FragmentManager fm, ArrayList < Fragment > fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
I am using ViewPager with my fragments. All fragments has animation and it does not work when switching back maybe because ViewPager saves somehow state of near Fragments, do you have some idea how to avoid it?
getItemPosition() doesn't make anything in this case
private class MyFragmentPagerAdapter extends FragmentPagerAdapter {
public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public CharSequence getPageTitle(int position) {
return null;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return GetStartedOneFragment.newInstance();
case 1:
return GetStartedTwoFragment.newInstance();
case 2:
return GetStartedThreeFragment.newInstance();
case 3:
return GetStartedFourFragment.newInstance();
case 4:
return GetStartedFiveFragment.newInstance();
case 5:
return GetStartedSixFragment.newInstance();
default:
return GetStartedOneFragment.newInstance();
}
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
I used a Fragment as a slider content, see the sample code below. Feel free to ask more details if required.
I have 4 flight modes in the example. The ViewPager is used with the associated adapter (ScreenSlidePagerAdapter).
You can see the app in the Play Store to see the slider (search "Flight Recorder 24").
// In the main fragment java code
private View headerView;
private ViewPager mPager;
public ScreenSlidePagerAdapter mPagerAdapter;
// ...
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
View mainView = inflater.inflate(R.layout.monitoring_fragment,container, false);
// The header of the list
View view = inflater.inflate(R.layout.header_monitoring_fragment, mListView, false);
headerView = view;
//...
mPager = (ViewPager) view.findViewById(R.id.pager);
FragmentManager fm = getChildFragmentManager();
mPagerAdapter = new ScreenSlidePagerAdapter(fm);
mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(UserConfiguration.getUserConf().getPositionFromFlightMode());
// Attach the page change listener inside the activity
mPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
// This method will be invoked when a new page becomes selected.
#Override
public void onPageSelected(int position)
{
int flight_mode = UserConfiguration.getFlightModeFromPosition(position);
UserConfiguration.getUserConf().setFlightMode(flight_mode);
}
// This method will be invoked when the current page is scrolled
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
// Code goes here
}
// Called when the scroll state changes:
// SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
#Override
public void onPageScrollStateChanged(int state)
{
// Code goes here
}
});
// ...
}
// ...
// Slider adapter
private class ScreenSlidePagerAdapter extends FragmentPagerAdapter
{
public ScreenSlidePagerAdapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position)
{
// position to flight mode
int flight_mode = UserConfiguration.getFlightModeFromPosition(position);
FlightModeFragment flightModeFragment = FlightModeFragment.newInstance(flight_mode);
return flightModeFragment;
}
public int getItemPosition(Object object)
{
return POSITION_NONE;
}
#Override
public int getCount()
{
return 4;
}
}
Then you have to create a Fragment with your slider content (here the class FlightModeFragment), it will be instanciated with an integer to identify the page embedded into a Bundle savedInstanceState (I have 4 pages).
public class FlightModeFragment extends Fragment
{
LinearLayout mainLayout;
ImageView live15minImageView;
ImageView modeImageView;
ImageView imageViewLeft;
ImageView imageViewRight;
private TextView textViewRecord;
private TextView textViewGps;
int flight_mode = UserConfiguration.AC_LISTENER_TRAVEL_RECORDER_MODE;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// handle fragment arguments
Bundle arguments = getArguments();
if(arguments != null)
{
flight_mode = arguments.getInt("flight_mode");
}
}
// ...
}
here's a portion of my code:
public class MenuExpenses extends Fragment {
private ViewPager viewPager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.expenses,container, false);
viewPager = (ViewPager) root.findViewById(R.id.pager);
viewPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
// Bind the tabs to the ViewPager
PagerSlidingTabStrip tabs = (PagerSlidingTabStrip) root.findViewById(R.id.tabs);
tabs.setViewPager(viewPager);
return root;
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
private final String[] TITLES = { "Daily", "Recurring" };
#Override
public Fragment getItem(int pos) {
switch(pos) {
case 0: return new MenuExpensesDaily();
case 1: return new IncomeList2();
default: return new MenuExpensesDaily();
}
}
}
}
MenuExpensesDaily & IncomeList2 are both fragments. So how can I set the fragment tag for both of them here?
You can override the instantiateItem method, the save the fragment to a SparseArray/HashMap, then create a method to return the fragment with the position. Now you will be able to access your selected your fragment and set the tag to it.
I am using Holoeverywhere and ViewPagerIndicator; using Holoeverywhere1 I implemented the slider and tabs in the Fragment using ViewPagerIndicator. Everything is working fine, Slider working, the menu in it, the tabs; the tabs works fine only the first time, when I move to other Fragment using the slider and come back to the tabs Fragment, the contents are no more available.
Code for the Fragment where tabs are created
public class SeconFrag extends Fragment {
ViewPager mViewPager;
FragmentAdapter mTabsAdapter;
PageIndicator mIndicator;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mTabsAdapter = new FragmentAdapter(getSupportFragmentManager());
View view = inflater.inflate(R.layout.second_frag);
mViewPager = (ViewPager) view.findViewById(R.id.pager);
mViewPager.setAdapter(mTabsAdapter);
TitlePageIndicator indicator = (TitlePageIndicator) view
.findViewById(R.id.indicator);
indicator.setViewPager(mViewPager);
indicator.setFooterIndicatorStyle(IndicatorStyle.Triangle);
mIndicator = indicator;
return view;
}
#Override
public void onResume() {
super.onResume();
getSupportActionBar().setSubtitle("Create");
}
}
FragmentAdapter code
public class FragmentAdapter extends FragmentPagerAdapter{
protected static final String[] CONTENT = new String[] { "Choose", "Customise" };
private int mCount = CONTENT.length;
public FragmentAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
if (position == 0) {
return TabOne.newInstance();
} else if (position == 1) {
return TabTwo.newInstance();
}else if (position == 3 ) {
return TabOne.newInstance();
}else
return null;
}
#Override
public int getCount() {
return mCount;
}
#Override
public CharSequence getPageTitle(int position) {
return FragmentAdapter.CONTENT[position % CONTENT.length];
}
public void setCount(int count) {
if (count > 0 && count <= 10) {
mCount = count;
notifyDataSetChanged();
}
}
}
on of the tab Fragment
public final class TabOne extends Fragment {
public static TabOne newInstance() {
TabOne fragment = new TabOne();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View myFragmentView = inflater.inflate(R.layout.tab_one, container,
false);
return myFragmentView;
}
}
in the SeconFrag OnPause() I removed the Fragment no luck, hide() it in the OnPause() and tried to show() in the OnResume() still not showing content after the Fragment is changed.
EDIT