Data is not passing to fragment from view pager adapter in android - android

I am passing data to a fragment using View-Pager Adapter.
My data is coming until View-Pager Adapter but is not showing in the fragment.
this is my view pager adapter code.
public class ExensesViewPagerAdapter extends FragmentPagerAdapter {
private Context mContext;
private MonthsTotal monthsTotal;
public ExensesViewPagerAdapter(FragmentManager fm, Context mContext, MonthsTotal monthsTotal) {
super(fm);
this.mContext = mContext;
this.monthsTotal = monthsTotal;
Logger.e("ExensesViewPagerAdapter");
Logger.json(new Gson().toJson(monthsTotal));
}
/*public ExensesViewPagerAdapter(FragmentManager fm) {
super(fm);
}*/
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return AmountFragment.newInstance(monthsTotal);
case 1:
return GraphFragment.newInstance(monthsTotal);
}
return null;
}
This is my fragment code where I am getting the data.
public static AmountFragment newInstance(MonthsTotal monthsTotal) {
Logger.e("AmountFragment");
Logger.json(new Gson().toJson(monthsTotal));
AmountFragment fragment = new AmountFragment();
Bundle args = new Bundle();
args.putParcelable("allExpenseData", monthsTotal);
fragment.setArguments(args);
return fragment;
}
Please help me to solve.Thank you in advance.

Related

Call onCreateView() on fragment that is inside a viewpager

I have viewpager that has 4 fragments.
I have set the offscreenPageLimit to 4 and did not override getItemPosition of the adapter because I don't want them to be re-created every time when I change tabs.
Now, there will be a scenario when I want a particular fragment to be re-created (it means to call onCreateView).
That is before I select or when I select that fragment again.
How to do this?
Please try this adapter. This recover to re-create fragment again.
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Fragment[] fragments;
private String[] titleList;
private int index;
public ViewPagerAdapter(FragmentManager fm, String[] titleList){ // titleList is list of title of fragments
super(fm);
fragments = new Fragment[titleList.length];
this.titleList = titleList;
}
#Override
public Fragment getItem(int position) {
Fragment fragment;
if (fragments[position] == null){
YourFragment yourFragment = new YourFragment();
fragment = yourFragment;
fragments[position] = fragment;
return fragment;
}else{
return fragments[position];
}
}
#Override
public int getCount() {
return titleList.length;
}
#Override
public CharSequence getPageTitle(int position) {
return titleList[position].toUpperCase();
}
}

SectionsPageAdapter with FragmentPageAdapter

First let me try to reproduce my Problem/Question.
My Activity is a TabbedActivity with 3 Tabs, done with a SectionPageAdapter and a FragmentPageAdapter.
On these 3 Tabs the user is input Data. With just swiping the user can change the tab. After the User has filled in all data, he must click on a FloatingActionButton to save the data.
Now there is my Problem i donĀ“t know if i can access these 3 Fragments with the filled in data ?
Can i load all 3 Fragments with the filled in Data, read the data and save it or must i handle the PageChangeListenEvent and saved the Data before i change the Page?
Code:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return TravelInfoActivity.PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
return maxTabs;
}
}
public static class PlaceholderFragment extends Fragment {
private static final String ARG_FRAGMENT_ID = "fragment_id";
private static int REQUEST_CODE_PLACE = 1;
private View currentRootView;
private View currentClickedView;
#SuppressLint("UseSparseArrays")
private HashMap<Integer, View> hMap = new HashMap<>();
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static TravelInfoActivity.PlaceholderFragment newInstance(int sectionNumber) {
TravelInfoActivity.PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
int fragmentLayout;
switch (sectionNumber) {
case 1:
fragmentLayout = R.layout.fragment_accommodation;
break;
case 2:
fragmentLayout = R.layout.fragment_visited_places;
break;
case 3:
fragmentLayout = R.layout.fragment_additional_info;
break;
default:
fragmentLayout = R.layout.fragment_accommodation;
}
args.putInt(ARG_FRAGMENT_ID, fragmentLayout);
fragment.setArguments(args);
return fragment;
}
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View rootView = inflater.inflate(getArguments().getInt(ARG_FRAGMENT_ID), container, false);
currentRootView = rootView;
switch (getArguments().getInt(ARG_FRAGMENT_ID)) {
// switch handling here, not relevant
}
return rootView;
}
Guys i have done it refreshed my brain ;)
Just save the instance from the Fragment to an array and you can use it later.
I made this in the SectionPageAdapter and ovverided the mehtod instantiateItem().
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private SparseArray<Fragment> registeredFragments = new SparseArray<>();
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
Integer fragmentId = fragment.getArguments().getInt("fragment_id");
registeredFragments.put(fragmentToPageMap.get(fragmentId), fragment);
return fragment;
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
public boolean registeredFragmentExists(int position) {
if(registeredFragments.size() >= position) {
if(registeredFragments.get(position) != null) {
return true;
}
}
return false;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return TravelInfoActivity.PlaceholderFragment.newInstance(position);
}
#Override
public int getCount() {
return maxTabs;
}
}
Later you can access the fragments rootView with
mSectionsPagerAdapter.getRegisteredFragment(position);
fragment.getActivity().findViewById(id);

Lock page fragment in ViewPager android

How can I lock paging in fragment activity of viewpager for fragment swipe.I'm performing some operations using progressbar in one fragment.While progressing progressbar fragment gets changes because of swipe action.so while progessing progressbar I want to stop swiping.How to do this?is there any solution??
activity.xml file-
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainFragmentActivity" >
<android.support.v4.view.PagerTitleStrip
android:id="#+id/pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#drawable/title"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
fragment activity-
public class MainFragmentActivity extends FragmentActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
private Context mContext;
private PagerTitleStrip pt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager(),mContext);
mContext=this;
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
pt=(PagerTitleStrip) findViewById(R.id.pager_title_strip);
}
SectionsPagerAdapter-
public class SectionsPagerAdapter extends FragmentPagerAdapter {
Context mContext;
Fragment fragment;
public SectionsPagerAdapter(FragmentManager fm, Context context) {
super(fm);
mContext=context;
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a DummySectionFragment (defined as a static inner class
// below) with the page number as its lone argument.
if(position==0){
fragment = new SelectItem();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
}
if(position==1){
fragment = new culation();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
}
if(position==2){
fragment = new GraphDisplay();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, position + 1);
fragment.setArguments(args);
}
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0 :
return "Select item";
case 1:
return "Calculation";
case 2:
return "Graph";
}
return null;
}
}
Try setting clickable to false:
mViewPager.setClickable(false);
If that works what you can do is create a function in activity to disable swipe event on view pager and call that function in fragment in event of progress bar show and a function to enable it.
Subclass ViewPager and override onTouch event for example:
EDIT
public class NonSwipeableViewPager extends ViewPager {
private boolean lock;
public void lock(){
lock=true;
}
public void unlock(){
lock=false;
}
public NonSwipeableViewPager(Context context) {
super(context);
}
public NonSwipeableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(lock)
return false;else{
return super.onTouchEvent(event);
}
}
}
reference:
How do disable paging by swiping with finger in ViewPager but still be able to swipe programmatically?
I found a simple way to do this, with its adapter.
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
/**
* Created by paul.boldijar on 2/24/2015.
*/
public class SimpleFragmentAdapter extends FragmentPagerAdapter {
private Fragment[] fragments;
private boolean locked = false;
private int lockedIndex;
public void setLocked(boolean locked, int page) {
this.locked = locked;
lockedIndex = page;
notifyDataSetChanged();
}
public SimpleFragmentAdapter(FragmentManager fm, Fragment[] fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
if (locked) return fragments[lockedIndex];
return fragments[position];
}
#Override
public int getCount() {
if (locked) return 1;
return fragments.length;
}
}
If you want to lock your fragment to a page, just call fragment.setLocked(true,page);
Where page is the index of the page you want to lock.
Based on the solution by Paul, I modified it to support displaying titles as well
public static class MainPagerAdapter extends FragmentStatePagerAdapter {
private Fragment[] fragments;
private String[] titles;
private boolean locked = false;
private int lockedIndex;
public MainPagerAdapter(FragmentManager fm, Fragment[] fragments, String[] titles) {
super(fm);
this.fragments = fragments;
this.titles = titles;
}
public void setLocked(boolean locked, int page) {
this.locked = locked;
lockedIndex = page;
notifyDataSetChanged();
}
#Override
public Fragment getItem(int position) {
if (locked) return fragments[lockedIndex];
return fragments[position];
}
#Override
public int getCount() {
if (locked) return 1;
return fragments.length;
}
#Override
public CharSequence getPageTitle(int position) {
if (locked) return titles[lockedIndex];
return titles[position];
}
}
The way I use it is to say
Fragment[] fragments = {//Create fragment objects here...};
String[] titles = getResources().getStringArray(R.array.tabs);
MainPagerAdapter adapter = new MainPagerAdapter(getSupportFragmentManager(), fragments, titles);
adapter.setLocked(true, 0);
mPager.setAdapter(adapter);
You can use this View:
https://github.com/mr-sarsarabi/lockableViewPager
It lets you lock the swipe gesture with a method: viewPager.setSwipeLocked(true);

How to prevent a FragmentPagerAdapter from loading the next Fragment in advance?

I am using a FragmentPagerAdapter to swipe three Fragments. It's not giving me any errors, but it always loads the next Fragment in advance. How can I stop this behavior?
Here is my FragmentPagerAdapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Context _context;
public ViewPagerAdapter(Context context, FragmentManager fm) {
super(fm);
_context = context;
}
#Override
public Fragment getItem(int position) {
Fragment f = new Fragment();
switch (position) {
case 0:
f = ReservationTab.newInstance(_context);
break;
case 1:
f = GalleryTab.newInstance(_context);
break;
case 2:
f = VideoTab.newInstance(_context);
break;
}
return f;
}
#Override
public int getCount() {
return 3;
}
}
try to use this
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(2 /*count of your fragments in viwePager*/);
Try using setOffscreenPageLimit(0) on your ViewPager

Android FragmentStatePagerAdapter

I'm working with a FragmentStatePagerAdapter using this example.
The MyAdapter class is implemented as follows:
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return NUM_ITEMS;
}
#Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
}
The ListFragment class includes the following method to create a new instance:
/**
* Create a new instance of CountingFragment, providing "num"
* as an argument.
*/
static ArrayListFragment newInstance(int num) {
ArrayListFragment f = new ArrayListFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
When I create a new fragment state pager adapter in my activity, getItem is called, which in turn calls the newInstance method in the ListFragment class. This is great when I want to create a new fragment.
But it's not clear to me how to modify getItem (if even needed) to get the fragment object when it already exists and the user pages from, for example, page 2 to page 1. I'd like my Activity to retrieve that existing, previously created fragment so that it can run an inner class AsyncMethod, which resides in the fragment class.
I think the solution is much simpler than the answers provided.
If you take a look at the source of FragmentStatePagerAdapter.instantiateItem(), you'll notice that instantiateItem() handles this logic for you, and thus your implementation of getItem() should always return a new instance.
So in order to return an existing Fragment, simply do (assuming you're calling from ViewPager):
Fragment f = (Fragment) getAdapter().instantiateItem(this, getCurrentItem());
While #imiric's solution is very concise, it still bothers me that it requires knowledge of the implementation of the class. My solution involves adding the following to your adapter, which should behave nicely with a FragmentStatePagerAdapter possibly destroying fragments:
private SparseArray<WeakReference<Fragment>> mFragments = new SparseArray<>();
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment f = (Fragment) super.instantiateItem(container, position);
mFragments.put(position, new WeakReference<>(f)); // Remember what fragment was in position
return f;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mFragments.remove(position);
}
public Fragment getFragment(int position) {
WeakReference<Fragment> ref = mFragments.get(position);
Fragment f = ref != null ? ref.get() : null;
if (f == null) {
Log.d(TAG, "fragment for " + position + " is null!");
}
return f;
}
I have implemented something similar to what you have. I extended the FragmentPagerAdapter class like so:
public class ContactsFragmentPagerAdapter extends FragmentPagerAdapter {
ActionBar mActionBar;
private List<Fragment> mFragments;
public ContactsFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
#Override
public int getCount() {
return mFragments.size();
}
#Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
public void setActionBar(ActionBar bar) {
mActionBar = bar;
}
}
Notice I have added an argument to the constructor to pass in the List of Fragment objects. This way the getItem() method of this class can return any class that extends Fragment or any of its subclasses and not just one specific class ArrayListFragment like you have done.
In the Activity where I instantiate my subclass of FragmentPagerAdapter I have passed in the list of Fragment objects:
Class the instantiates the FragmentPagerAdapter
public final class ContactManager extends Activity {
private ContactsFragmentPagerAdapter mAdapter;
private ViewPager mPager;
public ActionBar mActionBar;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contact_manager);
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, ContactsListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, GroupsListFragment.class.getName()));
mAdapter = new ContactsFragmentPagerAdapter(this.getFragmentManager(), fragments);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
#Override
public void onPageSelected(int arg0) {
mActionBar.getTabAt(arg0).select();
}
});
}
}
By accessing the variable "fragments", you can access a previously created Fragment so that you can run methods of that Fragment.
public class MyPagerAdapter extends FragmentStatePagerAdapter {
final Context m_context;
final WeakReference<Fragment>[] m_fragments;
public DetailPagerAdapter(FragmentManager fm) {
super(fm);
m_context = ...
m_fragments = new WeakReference[enter size here];
}
#Override
public Fragment getItem(int position) {
final Fragment fragment = instantiate your fragment;
m_fragments[position] = new WeakReference<Fragment>(fragment);
return fragment;
}
#Override
public int getCount() {
return ...
}
public Fragment getFragment(final int position) {
return m_fragments[position] == null ? null :
m_fragments[position].get();
}
}
Do not need modify the FragmentPagerAdapter, because fragments are cached by the FragmentManager. So you must need find inside it. Use this function to find the fragment by pager adapter position.
public Fragment findFragmentByPosition(int position) {
FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
return getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + getViewPager().getId() + ":"
+ fragmentPagerAdapter.getItemId(position));
}
Sample code for v4 support api.
I think this could help:
class HomePagerAdapter(fragmentManager: FragmentManager) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
private val fragmentConstructors: List<() -> Fragment> by lazy {
listOf(
::AuctionLotsFragment,
::ChatListFragment,
::MarketHomeFragment,
::WalletSectionsFragment,
::SettingsFragment
)
}
private val fragments: HashMap<Int, WeakReference<Fragment>> by lazy {
HashMap()
}
override fun getCount(): Int = fragmentConstructors.size
override fun getItem(position: Int): Fragment {
return fragments[position]?.get() ?: this.createFragmentForPosition(position)
}
private fun createFragmentForPosition(position: Int): Fragment {
val fragment = fragmentConstructors[position].invoke()
fragments[position] = WeakReference(fragment)
return fragment
}
}

Categories

Resources