ViewPager dentro do CardView dentro do RecyclerView Android
Estou tentando projetar algo muito semelhante a este design doSite de design de materiais.
Então, basicamente, eu tenho uma lista de CardViews que cada um deles tem várias visualizações que o usuário pode deslizar entre eles. (Primeiro cartão na imagem)
Comecei implementando uma reciclagem simples que contém CardView e, para cada cardview, implementei um FragmentStatePagerAdapter que contém vários fragmentos pelos quais o usuário pode passar e funciona (mais ou menos). O problema que estou enfrentando é muito semelhante a esse problemaO fragmento no ViewPager usando FragmentPagerAdapter fica em branco na segunda vez em que é exibido onde os fragmentos não carregam ou desaparecem quando você rola para cima e para baixo. Eu tentei todas as correções possíveis que as pessoas estavam sugerindo e ainda não consigo fazer isso funcionar.
Eu queria saber se existe uma maneira melhor de fazê-lo.
Aqui está o meu código (C # - Xamarin)
using System;
using Android.Support.V7.Widget;
using System.Collections.Generic;
using Android.Views;
using Android.Widget;
using System.Security.Cryptography;
using Android.Support.V4.View;
using Android.Support.V4.App;
using Android.Runtime;
using Android.OS;
using Android.Content;
using Android.App;
using Android.Support.V7.App;
using JavaString = Java.Lang.String;
using Android.Util;
using Android.Animation;
using System.ComponentModel.Design.Serialization;
namespace Answers.PortalAppXamarin.Droid
{
public enum MyTestAdapterItemType {
Type1,
Type2,
Type3
};
public class MyTestDataObj
{
public MyTestAdapterItemType type { get; set; }
public string data { get; set; }
}
public class PagerFragmentAdapter : Android.Support.V4.App.FragmentStatePagerAdapter {
public List<MyTestPageFragmentContainer> Tabs { get; set; }
public PagerFragmentAdapter(Android.Support.V4.App.FragmentManager fm) : base(fm) {
}
public override Android.Support.V4.App.Fragment GetItem(int position) {
return Tabs [position].Fragment;
}
public override Java.Lang.ICharSequence GetPageTitleFormatted(int position)
{
return new JavaString(Tabs [position].Title);
}
public override int GetItemPosition (Java.Lang.Object objectValue) {
for (int i = 0; i < Tabs.Count; i++) {
if (Tabs[i].Fragment.Equals (objectValue) ) {
return i;
}
}
return PositionNone;
}
public override int Count {
get {
return Tabs.Count;
}
}
}
public class MyTestPageFragmentContainer {
public string Title { get; set; }
public Android.Support.V4.App.Fragment Fragment { get; set; }
public MyTestPageFragmentContainer(string title, Android.Support.V4.App.Fragment fragment)
{
this.Title = title;
this.Fragment = fragment;
}
}
public class BaseFragment : Android.Support.V4.App.Fragment
{
public static Android.Support.V4.App.Fragment newInstance(int position) {
BaseFragment f = new BaseFragment ();
// Supply num input as an argument.
Bundle args = new Bundle ();
args.PutInt ("num", position);
f.Arguments = (args);
return f;
}
}
public class PageFragment1 : BaseFragment {
View RootView;
public override void OnCreate (Bundle savedInstanceState)
{
base.OnCreate (savedInstanceState);
}
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
RootView = inflater.Inflate (Resource.Layout.LoadingIndicatorOverlay, container, false);
return RootView;
}
public override void OnResume ()
{
base.OnResume ();
ValueAnimator _animator = ValueAnimator.OfFloat(0, 1);
_animator.SetDuration(2000);
_animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs e) => {
if (RootView != null) {
RootView.Alpha = (float)e.Animation.AnimatedValue;
}
};
}
}
public class PageFragment2 : BaseFragment {
View RootView;
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
RootView = inflater.Inflate(Resource.Layout.MeasureListItem, container, false);
return RootView;
}
public override void OnResume ()
{
base.OnResume ();
ValueAnimator _animator = ValueAnimator.OfFloat(0, 1);
_animator.SetDuration(2000);
_animator.Update += (object sender, ValueAnimator.AnimatorUpdateEventArgs e) => {
if (RootView != null) {
RootView.Alpha = (float)e.Animation.AnimatedValue;
}
};
}
}
public abstract class BaseCardViewHolder : RecyclerView.ViewHolder
{
public ViewGroup Header;
public ViewGroup Footer;
public TextView TitleTextView;
public Button MoreInfoBtn;
public ViewPager ContentViewPager;
public PagerFragmentAdapter Adapter;
public List<MyTestPageFragmentContainer> Tabs;
public Android.Support.V4.App.FragmentManager fm;
public BaseCardViewHolder(View rootView, Android.Support.V4.App.FragmentManager fm) : base(rootView)
{
Header = rootView.FindViewById<ViewGroup> (Resource.Id.card_view_header);
Footer = rootView.FindViewById<ViewGroup> (Resource.Id.card_view_footer);
ContentViewPager = rootView.FindViewById<ViewPager> (Resource.Id.card_view_content_viewPager);
TitleTextView = Header.FindViewById<TextView> (Resource.Id.card_view_title);
MoreInfoBtn = Footer.FindViewById<Button> (Resource.Id.card_view_moreInfoBtn);
this.fm = fm;
Tabs = setupTabs ();
if (Tabs != null && fm != null) {
Adapter = new PagerFragmentAdapter (fm);
Adapter.Tabs = Tabs;
ContentViewPager.Adapter = Adapter;
}
}
public void RefreshViewPager()
{
ContentViewPager.Adapter.NotifyDataSetChanged ();
}
public abstract List<MyTestPageFragmentContainer> setupTabs ();
}
public class Type1ViewHolder : BaseCardViewHolder
{
public Type1ViewHolder(View v, Android.Support.V4.App.FragmentManager fm) : base(v, fm)
{
}
public override List<MyTestPageFragmentContainer> setupTabs()
{
return new List<MyTestPageFragmentContainer> {
new MyTestPageFragmentContainer ("Tab1", new PageFragment1 ()),
new MyTestPageFragmentContainer ("Tab2", new PageFragment1 ())
};
}
}
public class Type2ViewHolder : BaseCardViewHolder
{
public Type2ViewHolder(View v, Android.Support.V4.App.FragmentManager fm) : base(v, fm)
{
}
public override List<MyTestPageFragmentContainer> setupTabs()
{
return new List<MyTestPageFragmentContainer> {
new MyTestPageFragmentContainer ("Tab1", new PageFragment2 ()),
new MyTestPageFragmentContainer ("Tab2", new PageFragment2 ()),
new MyTestPageFragmentContainer ("Tab1", new PageFragment1 ()),
new MyTestPageFragmentContainer ("Tab2", new PageFragment1 ()),
};
}
}
public class Type3ViewHolder : BaseCardViewHolder
{
public Type3ViewHolder(View v, Android.Support.V4.App.FragmentManager fm) : base(v, fm)
{
}
public override List<MyTestPageFragmentContainer> setupTabs()
{
return new List<MyTestPageFragmentContainer> {
new MyTestPageFragmentContainer ("Tab1", new PageFragment2 ()),
new MyTestPageFragmentContainer ("Tab2", new PageFragment1 ()),
new MyTestPageFragmentContainer ("Tab3", new PageFragment2 ()),
new MyTestPageFragmentContainer ("Tab4", new PageFragment1 ())
};
}
}
public class MyTestRecyclerAdapter : RecyclerView.Adapter
{
public Android.Support.V4.App.FragmentManager FM;
readonly List<MyTestDataObj> myTestDataList = new List<MyTestDataObj>{
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 1"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 2"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 3"},
new MyTestDataObj {type = MyTestAdapterItemType.Type3, data = "Item 4"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 5"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 6"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 7"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 8"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 9"},
new MyTestDataObj {type = MyTestAdapterItemType.Type3, data = "Item 10"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 11"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 12"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 13"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 14"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 15"},
new MyTestDataObj {type = MyTestAdapterItemType.Type3, data = "Item 16"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 17"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 18"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 19"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 20"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 21"},
new MyTestDataObj {type = MyTestAdapterItemType.Type3, data = "Item 22"},
new MyTestDataObj {type = MyTestAdapterItemType.Type1, data = "Item 23"},
new MyTestDataObj {type = MyTestAdapterItemType.Type2, data = "Item 24"},
};
#region implemented abstract members of Adapter
public override void OnBindViewHolder (RecyclerView.ViewHolder holder, int position)
{
MyTestDataObj item = myTestDataList [position];
switch (GetItemViewType (position)) {
case (int) MyTestAdapterItemType.Type1:
{
((Type1ViewHolder)holder).TitleTextView.Text = item.data;
((Type1ViewHolder)holder).RefreshViewPager ();
break;
}
case (int) MyTestAdapterItemType.Type2:
{
((Type2ViewHolder)holder).TitleTextView.Text = item.data;
((Type2ViewHolder)holder).RefreshViewPager ();
break;
}
case (int) MyTestAdapterItemType.Type3:
{
((Type3ViewHolder)holder).TitleTextView.Text = item.data;
((Type3ViewHolder)holder).RefreshViewPager ();
break;
}
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder (Android.Views.ViewGroup parent, int viewType)
{
LayoutInflater layoutInflater = LayoutInflater.From (parent.Context);
switch (viewType) {
case (int) MyTestAdapterItemType.Type1:
{
return new Type1ViewHolder (layoutInflater.Inflate (Resource.Layout.MyTestCardViewLayout, parent, false), FM);
}
case (int) MyTestAdapterItemType.Type2:
{
return new Type2ViewHolder (layoutInflater.Inflate (Resource.Layout.MyTestCardViewLayout, parent, false), FM);
}
case (int) MyTestAdapterItemType.Type3:
{
return new Type3ViewHolder (layoutInflater.Inflate (Resource.Layout.MyTestCardViewLayout, parent, false), FM);
}
}
return null;
}
public override int ItemCount {
get {
return myTestDataList.Count;
}
}
public override int GetItemViewType (int position)
{
return (int)myTestDataList [position].type;
}
#endregion
}
}
Aqui está a demonstração:
Nota: Tenho certeza de que é possível, pois oAplicativo do Google Analytics para iOS e Android, está exatamente com o mesmo design que estou procurando.
Gostaria muito de receber ajuda, obrigado