I have two activities which I want to combine with a FragmentPagerAdapter.
I followed a tutorial and everything works great with the test classes. However, as mentioned I want to use two previously made Activities in that horizontal slider.
At the moment it looks like this:
public class CheatPagerFragmentActivity extends FragmentActivity {
...
/**
* Initialise the fragments to be paged
*/
private void initialisePaging() {
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, CheatView.class.getName()));
fragments.add(Fragment.instantiate(this, CheatMetaView.class.getName()));
this.mPagerAdapter = new MyPagerAdapter(super.getSupportFragmentManager(), fragments);
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
pager.setAdapter(this.mPagerAdapter);
}
}
CheatView and CheatMetaView used to be Activities but now are Fragments ("extends Fragment"). I don't need to know how I can still pass information to those (new) Fragments as I can not use "intent" anymore how I used to pass information between Activities.
Also creating new elements in the code of these classes is being marked as an error now. Like this line of code:
TableRow trTh = new TableRow(this);
How can I pass information to those classes and how do I have to change the code to create a new TableRow in the code of the former Activity class?
Thanks for any help.
Re your first question: Instead of using Fragment.instantiate, create a newInstance method for each fragment that can take the information you wish to pass as a parameter. See the page below for an example (search for newInstance):
http://developer.android.com/reference/android/app/Fragment.html
Related
I want to show a few tabs sharing the same viewmodel with viewpager in an activity. I am using MvvmCross 5.6.2.
When I do that in a fragment, the viewpager is shown properly. Using the same method, I add tab fragments to the viewpager in an activity with code like this:
var viewPagerFragmentList = new List<MvxViewPagerFragmentInfo>
{
new MvxViewPagerFragmentInfo("Personal", typeof (SettingPersonalFragment), ViewModel),
new MvxViewPagerFragmentInfo("Preference", typeof (SettingPreferenceFragment), ViewModel)
};
viewPager.Adapter = new MvxCachingFragmentStatePagerAdapter(this, SupportFragmentManager, viewPagerFragmentList);
var tabLayout = FindViewById<TabLayout>(Resource.Id.tabs_fragment_setting_viewpager);
tabLayout.SetupWithViewPager(viewPager);
The tab fragments are not shown on screen, though the tab fragment's OnCreate and OnCreateView are executed.
I found the latest sample Playground is showing tabs in activity too. Following the sample, I register the fragment:
[MvxTabLayoutPresentation(TabLayoutResourceId = Resource.Id.tabs_fragment_setting_viewpager, ViewPagerResourceId = Resource.Id.viewpager_fragment_setting_viewpager, Title = "Personal", ActivityHostViewModelType = typeof(SettingViewModel))]
No luck with that. The last thing I found in Playground to show a tab is to navigate to the fragment viewmodel:
_navigationService.Navigate<Tab2ViewModel>();
_navigationService.Navigate<Tab3ViewModel>();
However, in my case, I do not have a viewmodel for each fragment. The workaround on my hand is to move the viewpager to a fragment in the activity.
How could I show the viewpager fragments without their own viewmodels in an activity?
Thanks,
Nick
The above code that works in fragment also work in activity. There is an issue in the xml causing the viewpager not showing. Sorry.
Thanks everyone who helped.
It is taking me forever to learn the Android SDK. I am currently trying to implement swipe views with tabs by following this tutorial.
I understand that we are supposed to use fragments as "mini activities", and that one fragment makes up of the many tabs attached to the ViewPager.
There is this code segment in the tutorial that I fail to grasp, however:
public class CollectionDemoActivity extends FragmentActivity {
// When requested, this adapter returns a DemoObjectFragment,
// representing an object in the collection.
DemoCollectionPagerAdapter mDemoCollectionPagerAdapter;
ViewPager mViewPager;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collection_demo);
// ViewPager and its adapters use support library
// fragments, so use getSupportFragmentManager.
mDemoCollectionPagerAdapter =
new DemoCollectionPagerAdapter(
getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mDemoCollectionPagerAdapter);
}
}
Does the FragmentActivity class come into play when attaching a Fragment to the ViewPager? In separate documentations of fragments and viewpagers, I cannot find mention of FragmentActivity.
I would really appreciate it if you could shed some light on this matter.
Thank you in advance.
The Adapter takes this as an argument: getSupportFragmentManager()
That is only available to a FragmentActivity. (specifically, of the Support library variety).
I'm Android programmer making first steps. In my app I decided to use ViewPager (support.v4).
I create all fragments in very typical way:
#Override
public void onCreate(Bundle savedInstanceState) {
(...)
//let's initialize view pager
List<Fragment> fragments = new ArrayList<Fragment>();
fragments.add(new MainActivitySelectDatabase());
fragments.add(new MainActivityDetails());
mainActivityPageAdapter = new MainActivityPageAdapter(getSupportFragmentManager(), fragments);
mainActivityViewPager = (ViewPager) findViewById(R.id.main_activity_view_pager);
mainActivityViewPager.setAdapter(mainActivityPageAdapter);
(...)
}
Next I would like to inform all fragments about one event in the following way:
protected void informAllFragmentsWhenDatabaseStatusChanged () {
for (int i=0; i<mainActivityPageAdapter.getCount(); i++) {
((InterfaceMainDatabaseStatusChanged) mainActivityPageAdapter.getItem(i)).onMainDatabaseStatusChanged();
}
}
And everything seems to work ok if I don't change screen orientation. When I change it everything becomes crazy. Methods like getActivity or getApplication in Fragment returns null. I'm guessing that for unknown reasons the method is executed for old version of my fragments, not for the new ones. How should it be solved? How to list current versions of all Fragments from main Activity?
Thanks in advance for help.
I'm guessing that for unknown reasons the method is executed for old
version of my fragments, not for the new ones.
Those unknown reasons are that the ViewPager only calls the getItem() method only when it doesn't have a valid instance for that page's fragment(and after a configuration change, the ViewPager will have references to those fragments through the FragmentManager). Your options are to get rid of the list of fragments and simply instantiate the proper fragment directly in the getItem() method(and also use a different method to access the fragments ) or to further extend the adapter so your list will always have the proper references to the fragments of the ViewPager.
For option one have a look at this question. You can also implement the communication by interfaces, registering each of the fragments of the ViewPager in their onAttach methods with the activity in some sort of WeakReference structure(and using this when needing to access the fragments).
To further extend the adapter have a look at the instantiateItem() method.
I am trying to create some Picture Album app. But When creating new Fragment , old one stays and Bitmaps it contains are quickly filling my memory resulting in out of memory error.
Here is what I am trying to do:
Let say I have 3 categories. Wedding pictures , Summer holidays and other. After clicking on each category I want to display photos in a fragment next to it.
For main view I am using FragmentActivity from MasterDetailFlow template (When you create new Android project in Eclipse). So basically it have one fragment with listView (here are mine categories) and framelayout to put my other fragment.
Because I wanted to have ViewPager for pictures I created Fragment that puts
android.support.v4.view.ViewPager
inside the framelayout (in Activity onItemSelected :) :
fragment = new PagerFragment();
fragment.setArguments(arguments);
getSupportFragmentManager().beginTransaction()
.replace(R.id.item_detail_container, fragment).commit();
This fragment is basically just used to set up :
onCreateView ....
rootView = inflater.inflate(R.layout.pager, container, false);
myFragmentStatePagerAdapter = new MyFragmentStatePagerAdapter(
getActivity().getSupportFragmentManager(), pictures);
mViewPager = (ViewPager) rootView.findViewById(R.id.pager);
mViewPager.setAdapter(myFragmentStatePagerAdapter);
return rootView;
Adapter on the other hand creates new PictureFragment in getItem method.
PictureFragment uses BitmapFactory and LruCache to fetch pictures. I store WeakReference to bitmap in PictureFragment and in onDestroyView() I call:
if (bitmapReference !=null){
bitmapReference.get().recycle();
bitmapReference = null;
}
Now to the problem. Within one PagerFragment it all looks ok. PicturesFragments are created and destroyed. Memory seems to be under control. But the problem starts when I click in the activity on other list element. I can see in logs that two new fragments are being created for pager View , I can see that onDestroyView() method was called on the PagerFragment but not on the PictureFragment which I assume result in Bitmaps not being recycled. Hence out of memory error. So what do I do wrong? How to remove PicturesFragment and bitmaps inside?
Thanks for help
W
Not sure if it is the same problem, but some time ago I had a problem with viewpager where the fragment lifecycle methods were never called and the problem was with the fragment manager.
So, when you create the adapter in:
myFragmentStatePagerAdapter = new MyFragmentStatePagerAdapter(
getActivity().getSupportFragmentManager(), pictures);
try using childFragmentManager instead of supportFragmentManager and see if it fixes your issue.
I initially create my fragments inside the Activity onCreate(). Than I go about creating the ViewPager and setting up the adapter. I keep a global reference to the fragments so I can update them as needed. Also, these fragments are accessed by the adapter.
My issue is that I notice once the screen is rotated the Fragments are recreated but the ViewPager still contains the original fragments created...??
How am I supposed to handle the life-cycle of my fragment? I need to be able to call directly to the fragment from the activity. Is a singleton for a fragment a good idea? Or just a memory leaker?
protected void onCreate (Bundle savedInstanceState)
{
...
...
// set up cards
mFrag1 = new Frag1();
mFrag1.setOnActionEventListener(mOnActionEvents);
mFrag2 = new Frag2();
mFrag3 = new Frag3();
mFragPager = (ViewPager) findViewById(R.id.vpPager);
mFragAdapter = new FragAdapter(getSupportFragmentManager());
mFragPager.setAdapter(mCardAdapter);
mFragPager.setOnPageChangeListener(mOnCardChange);
}
Global instances and static fragments are definitely a bad idea. Unless you call setRetainInstance() on a fragment, it will be serialized to a Bundle and recreated when an the parent activity is re-created (on screen rotate, etc.). That will, of course, produce new fragment instances, and your old references will be invalid. You should get references to fragments via FragmentManager.findFragmentById/Tag() as needed and definitely not store those in static variables.
You may need to show more of our code, but as long as you create the fragments in onCreate() the references should be valid for the lifetime of the activity. Check the compatibility library sample code for more on using fragments with ViewPager.