Open ViewPager views beyond max count set in the Fragment Adapter - android

So I have a viewPager with 4 view, which I can access by swiping left or right. My Adapter -
public class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
#Nullable
#Override
public Fragment getItem(int i) {
switch (i){
case 0:
return new FirstFrag();
case 1:
return new SecondFrag();
case 2:
return new ThridFrag();
case 3:
return new FourthFrag();
default:
return null;
}
}
#Override
public int getCount() {
return 3;
}
}
Since getCount() return 3 hence I can only see only three views which is fine and it works perfectly but I go to the fourth view maybe programatically, beyond the fixed count.
Why I am doing this? I am trying to make a view accessible when user click a button on the third view but can't access it by swiping. I have tried launching an new activity but the problem was my livedata viewmodel data couldn't talk to the new activity because two activities can share viewmodel hence this approach.
My solution was, the approach I have mentioned above.

Your error is that you are indicating that there are only 3 views, ignoring a fourth, remember that in programming the 0 does count.
Your solution is
public class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
#Nullable
#Override
public Fragment getItem(int i) {
switch (i){
case 0:
return new FirstFrag(); //View 1
case 1:
return new SecondFrag(); //View 2
case 2:
return new ThridFrag(); //View 3
//By indicating that getCount () return 3, this is all 3 views
case 3:
return new FourthFrag(); //View 4
default:
return null;
}
}
#Override
public int getCount () {
return 4;
}
}

Related

Re-use fragments of ViewPager & FragmentPagerAdapter

How to reuse the fragments inside view pager ???
I have view pager and inside that Having 3 fragments.
I'm creating new instance of fragment to all time. So It's take more space in memory.
In this 3 fragments having perform same functionality. While Im creating new instance every time. It's having more problems like.
1) It take times to keyboard open and close.
2) Scrollview take times to scroll.
3) Edit text take time to focus on and off.
https://prnt.sc/or86ec
Here screen that I have implemented viewpager with 3 fragment. In swipe it's look like same.
I have created Pager adapter:
public class ProposalDetailPagerAdapter : FragmentStatePagerAdapter, CardAdapter
{
private static int NUM_ITEMS = 3;
private float mBaseElevation;
public ProposalDetailPagerAdapter(Android.Support.V4.App.FragmentManager fm, float baseElevation) : base(fm)
{
mBaseElevation = baseElevation;
}
public override int Count => NUM_ITEMS;
public override int GetItemPosition(Java.Lang.Object #object)
{
if (#object is ProposalDetailFragment)
{
ProposalDetailFragment fragment = (ProposalDetailFragment)#object;
if (fragment != null)
{
fragment.UpdateFragmentAfterCreate();
}
}
return base.GetItemPosition(#object);
}
public int getCount()
{
return NUM_ITEMS;
}
public override Android.Support.V4.App.Fragment GetItem(int position)
{
switch (position)
{
case 0:
return OpenFragment(0);
case 1:
return OpenFragment(1);
case 2:
return OpenFragment(2);
default:
return null;
}
}
private Android.Support.V4.App.Fragment OpenFragment(int position)
{
ProposalDetailFragment createdFragment = new ProposalDetailFragment();
Bundle bundle = new Bundle();
bundle.PutInt("position", position);
createdFragment.Arguments = bundle;
return createdFragment;
}
public override Android.Support.V4.App.Fragment GetItem(int position)
{
switch (position)
{
case 0:
return OpenFragment(0);
case 1:
return OpenFragment(1);
case 2:
return OpenFragment(2);
default:
return null;
}
}
}
In this adapter, created 3 fragments. But It's having lot's of memory problem. Because lot's of condition having in fragments. and created 3 instance of memory. So How to resolve this issue ???
Here is a solution :
In ProposalDetailPagerAdapter , can override DestroyItem method.And comment out the method of calling the parent class to avoid repeated creation of the fragment.
As follow:
public class ProposalDetailPagerAdapter : FragmentStatePagerAdapter, CardAdapter
{
...
public override void DestroyItem(ViewGroup container, int position, Java.Lang.Object #object)
{
//base.DestroyItem(container, position, #object);
// Comment out the calling parent class
}
...
}

How do I set the number of tabs and their respective labels in a ViewPager programatically?

Okay, so. I've got a Spinner that has a set of values retrieved from a database. This spinner is inside a Fragment that is a part of a Tabbed Activity that makes use of a ViewPager. This is what I'm trying to acheive:
Spinner has a certain value
Based on this value, the ViewPager's number of tabs changes (and their respective labels), from information passed from an onChanged() (or simlar) method from the Spinner
Where would I begin in doing this? I am completely clueless on where to start with this.
I use the following code in onResume to change the number of tabs and pages based on a user selected configuration (specified in my case in another activity). You could call something like this when the user selects a configuration from the spinner.
ConfigurationEnum ct = getSelectedConfiguration(); // or pass in from spinner
if( ct != mPagerAdapter.getConfiguration() ) {
// remove all tabs
int cnp = mPagerAdapter.getCount();
while( cnp > 0 ) {
mPagerAdapter.destroyItem(mViewPager, cnp - 1, mPagerAdapter.getItem(cnp - 1));
mTabLayout.removeTabAt(cnp-1);
--cnp;
}
// now add back tabs we need
ArrayList<String> tabList = ct.getTabsToShow();
for(int i = 0; i < meas.size(); ++i) {
mTabLayout.addTab(mTabLayout.newTab().setText(tabList.get(i)),i);
}
mTabLayout.invalidate();
mPagerAdapter.setConfiguration(ct);
mPagerAdapter.notifyDataSetChanged();
}
My custom pager adapter is set to know which fragments to show based on the configuration that gets set here.
static class MyPagerAdapter extends FragmentPagerAdapter {
private ConfigurationEnum myConfiguration = ConfigurationEnum.DEFAULT;
private int numPages = 3;
void setConfiguration(ConfigurationEnum ct) {
myConfiguration = ct;
numPages = ct.getTabsToShow().size();
}
ConfigurationEnum getConfiguration() {
return myConfiguration;
}
MyPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch(myConfiguration) {
case CONFIG_A:
switch(position) {
case 0:
return FragmentA1.getInstance();
case 1:
return FragmentA2.getInstance();
}
break;
case CONFIG_B:
switch(position) {
case 0:
return FragmentB1.getInstance();
case 1:
return FragmentB2.getInstance();
case 2:
return FragmentB3.getInstance();
case 3:
return FragmentB4.getInstance();
}
break;
case CONFIG_C:
switch(position) {
case 0:
return FragmentC1.getInstance();
case 1:
return FragmentC2.getInstance();
case 2:
return FragmentC3.getInstance();
}
break;
}
}
#Override
public int getCount() {
return numPages;
}
#Override
public int getItemPosition(#NonNull Object obj) {
return POSITION_NONE;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
mCurrentFragment = ((Fragment) object);
super.setPrimaryItem(container, position, object);
}
}
And an example implementation of the ConfigurationEnum
public enum ConfigurationEnum {
CONFIG_A,
CONFIG_B,
CONFIG_C;
ArrayList<String> getTabsToShow() {
ArrayList<String> tabs = new ArrayList<>();
switch(this) {
case CONFIG_A:
tabs.add("Tab A1");
tabs.add("Tab A2");
break;
case CONFIG_B:
tabs.add("Tab B1");
tabs.add("Tab B2");
tabs.add("Tab B3");
tabs.add("Tab B4");
break;
case CONFIG_C:
tabs.add("Tab C1");
tabs.add("Tab C2");
tabs.add("Tab C3");
break;
}
return tabs;
}
}

How I can have different controls in different tabs and one Fragment using TabLayout in Android

I am trying to understand how tabs are working but I am confused. I created a sample app with Android Studio wizard where there is one fragment.
How I can have in this one fragment but in different tabs different elements I only need to do something in onCreateView or in FragmentPagerAdapter?
The part of the adapter is:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#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 PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "CONTACTS";
case 1:
return "DETAILS";
case 2:
return "GENERAL";
}
return null;
}
}
An example on how to achieve the task.
//sending different arguments from the view pager adapter
public Fragment getItem(int position){
Fragment fragment=new PlaceHolderFragment();
//a bundle is used to wrap the data you send to the fragment
Bundle bundle=new Bundle();
//change whats inside the bundle based on your page
switch(position){
case 0:{
bundle.putInt("dataForThisPosition",12);
break;
}case 1:{
bundle.putInt("dataForThisPosition",13);
break;
}
//this can continue
}
//attach the bundle to the fragment
fragment.setArguments(bundle);
return fragment;
}
//then in your fragment class
//receiving the data sent from pager adapter
public View onCreateView(/*parameters*/){
Bundle receivedBundle=getArguments();
int datForThisPosition=recievedBundle.getInt("dataForThisPosition",12/*default value*/);
//create your view based on the info received.
}

ViewPager creates duplicate views

This is the PagingAdapter I am using:
public class PagingAdapter extends FragmentStatePagerAdapter {
Context context;
public PagingAdapter(FragmentManager fm, Context con) {
super(fm);
context = con;
}
#Override
public Fragment getItem(int index) {
try {
switch (index) {
case 0:
return Fragment.instantiate(context, ActivityFragment.class.getName());
case 1:
return Fragment.instantiate(context, GroupFragment.class.getName());
case 2:
return Fragment.instantiate(context, MessageFragment.class.getName());
case 3:
return Fragment.instantiate(context, NotificationFragment.class.getName());
}
return null;
}
catch (Exception ex)
{
ex.printStackTrace();
return null;
}
}
#Override
public int getCount() {
// get item count - equal to number of tabs
return 4;
}
}
This creates same view for first two tabs. I want separate content for all tabs.
I am placing WebView in all 4 tabs.
In Activity, I am doing this :
mViewPager.setOffscreenPageLimit(3);
Use SparseArray<Fragment> in your adapter, and in your getItem use new instantiate your fragments like
return new ActivityFragment();
If you want to add bundle info than first create your fragment than add bundle in your
fragment.setArgument(bundle);
And use these line in your deateyItem before calling super
if(0<=sparseArray.indexOfKey(position))
sparseArray.remove(position);
First of all your method instantiate is returning a Fragment right?
Does it add the param implicitly in that method using setArguements if not you may want to change to it. On the other hand FragmentManager will call default constructor of each fragment when needed. So you have to keep them (do not overload constructor) and in destroyItem try removing the fragment for real.
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
getFragmentManager().beginTransaction().remove((Fragment)(object)).commit();
}
What do you mean by separate view? are you sure that you are not inflating the wrong layout in.
GroupClassFragment.java class
Do check int the method.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View myCorrectView = inflater.inflate(R.layout.my_correct_view,container,false);
return myCorrectView;
}

Update gridview in viewpager

I have been searching for a while for a way to refresh a gridview within a viewpager and I am yet to find an answer. More specificaly my problem is that I have a view pager with three gridviews. Each gridview is populated by an arraylist and if the arraylist is changed the gridview stays the same. How can I make it update? I have tried calling notifydatasetchange on the adapter and that doesnt help.
here is my code for the view pager adapter
public class FavoritesViewPager extends FragmentStatePagerAdapter {
public FavoritesViewPager(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
UserDatabaseHandler UDH = new UserDatabaseHandler(getActivity());
switch (i) {
case 0:
ArrayList<Exercise> strengthList = UDH.getFavoriteExercises("strengthexercises");
UDH.close();
return FavoriteExercises.newInstance(strengthList);
case 1:
ArrayList<Exercise> stretchList = UDH.getFavoriteExercises("stretchingexercises");
UDH.close();
return FavoriteExercises.newInstance(stretchList);
case 2:
ArrayList<Exercise> warmupList = UDH.getFavoriteExercises("warmupexercises");
UDH.close();
return FavoriteExercises.newInstance(warmupList);
default:
ArrayList<Exercise> temp = UDH
.getFavoriteExercises("warmupexercises");
UDH.close();
return FavoriteExercises.newInstance(temp);
}
}
#Override
public int getCount() {
return 3;
}
}
If your pager has only two pages, you should use FragmentPagerAdapter. You can get the fragment by findFragmentByTag then call update method of this fragment.
String fragmentName = makeFragmentName(_viewPager.getId(), i);
Fragment frag = _fragmentManager.findFragmentByTag(fragmentName);
private static String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}

Categories

Resources