Skip to content

Instantly share code, notes, and snippets.

@martijn00
Last active March 18, 2021 14:46
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save martijn00/23b00172af9e2c798f3d to your computer and use it in GitHub Desktop.
Save martijn00/23b00172af9e2c798f3d to your computer and use it in GitHub Desktop.
Android v22.2 Tabs and ViewPager in MvvmCross
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
app:tabGravity="center"
app:tabMode="scrollable" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="fill_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
public class SomeFragment : MvxFragment<SomeViewModel>
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
var view = base.OnCreateView(inflater, container, savedInstanceState);
var viewPager = view.FindViewById<Android.Support.V4.View.ViewPager>(Resource.Id.viewpager);
if (viewPager != null)
{
var fragments = new List<MvxViewPagerFragmentAdapter.FragmentInfo>
{
new MvxViewPagerFragmentAdapter.FragmentInfo
{
FragmentType = typeof(SomeFragment1),
Title = "",
ViewModel = ViewModel.ViewModelSomething1
},
new MvxViewPagerFragmentAdapter.FragmentInfo
{
FragmentType = typeof(SomeFragment2),
Title = ViewModel.ViewModelPopular.TextSource.GetText("Title"),
ViewModel = ViewModel.ViewModelSomething2
},
new MvxViewPagerFragmentAdapter.FragmentInfo
{
FragmentType = typeof(SomeFragment3),
Title = ViewModel.ViewModelContributors.TextSource.GetText("Title"),
ViewModel = ViewModel.ViewModelSomething3
}
};
viewPager.Adapter = new MvxViewPagerFragmentAdapter(Activity, ChildFragmentManager, fragments);
}
var tabLayout = view.FindViewById<TabLayout>(Resource.Id.tabs);
tabLayout.SetupWithViewPager(viewPager);
return view;
}
}
public class MvxFragmentStatePagerAdapter
: FragmentStatePagerAdapter
{
private readonly Context _context;
public IEnumerable<FragmentInfo> Fragments { get; private set; }
public override int Count
{
get { return Fragments.Count(); }
}
protected MvxFragmentStatePagerAdapter(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public MvxFragmentStatePagerAdapter(
Context context, FragmentManager fragmentManager, IEnumerable<FragmentInfo> fragments)
: base(fragmentManager)
{
_context = context;
Fragments = fragments;
}
public override Fragment GetItem(int position)
{
var fragmentInfo = Fragments.ElementAt(position);
var fragment = Fragment.Instantiate(_context,
FragmentJavaName(fragmentInfo.FragmentType));
((MvxFragment)fragment).ViewModel = fragmentInfo.ViewModel;
return fragment;
}
protected static string FragmentJavaName(Type fragmentType)
{
var namespaceText = fragmentType.Namespace ?? "";
if (namespaceText.Length > 0)
namespaceText = namespaceText.ToLowerInvariant() + ".";
return namespaceText + fragmentType.Name;
}
public override ICharSequence GetPageTitleFormatted(int position)
{
return new Java.Lang.String(Fragments.ElementAt(position).Title);
}
public class FragmentInfo
{
public string Title { get; set; }
public Type FragmentType { get; set; }
public IMvxViewModel ViewModel { get; set; }
}
}
@zakayothuku
Copy link

Awesome!!!

@bradlak
Copy link

bradlak commented Oct 1, 2017

Thanks

@shahid-pk
Copy link

shahid-pk commented Mar 14, 2018

throwing this exception for me

Android.Support.V4.App.Fragment+InstantiationException: Unable to instantiate fragment shifa4u.android.views.account.LabTestResults: make sure class name exists, is public, and has an empty constructor that is public

though i have an empty constructor on LabTestResults fragment , it is MvxFragment< LabTestResultViewModel >

@gvsharma
Copy link

Binding is not working for ViewPager's fragment....

@aroni79
Copy link

aroni79 commented Aug 9, 2018

I really sorry, i'm new in mvvmcross and i need to use a tablayout with a viewpager, the quantity of tab is depends of the quantity of object in a list, i tried to use this solution but i don't know how to call the SomeFragment class in the main activity to build the tab and viewpager elements, some idea ?

@c-lamont
Copy link

c-lamont commented Sep 5, 2018

@shahid-pk I am also getting the same error

Android.Support.V4.App.Fragment+InstantiationException: Unable to instantiate fragment .....: make sure class name exists, is public, and has an empty constructor that is public

Did you manage to solve the issue?

Edit
solution is to change the FragmentJavaName method to:

protected static string FragmentJavaName(Type fragmentType)
{
    return Java.Lang.Class.FromType(fragmentType).Name;
}

@MaksimFilatov
Copy link

Why isn't MvxFragmentStatePagerAdapter include in MvvmCross library?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment