ViewPager内置CardView内置RecyclerView Android

ViewPager内置CardView内置RecyclerView Android,android,android-fragments,xamarin,android-recyclerview,android-cardview,Android,Android Fragments,Xamarin,Android Recyclerview,Android Cardview,我正试图设计一些与这个设计非常相似的东西 所以基本上,我有一个CardView列表,每个都有多个视图,用户可以在它们之间滑动。(图像上的第一张卡片) 我首先实现了一个简单的包含CardView的recyclerview,对于每个CardView,我都实现了一个FragmentStatePagerAdapter,它包含多个用户可以滑动的片段,并且可以正常工作(有点)。 我面临的问题与这个问题非常相似,片段要么无法加载,要么在上下滚动时消失。我已经尝试了人们建议的每一种可能的修复方法,但我仍然无法

我正试图设计一些与这个设计非常相似的东西

所以基本上,我有一个CardView列表,每个都有多个视图,用户可以在它们之间滑动。(图像上的第一张卡片)

我首先实现了一个简单的包含CardView的recyclerview,对于每个CardView,我都实现了一个FragmentStatePagerAdapter,它包含多个用户可以滑动的片段,并且可以正常工作(有点)。 我面临的问题与这个问题非常相似,片段要么无法加载,要么在上下滚动时消失。我已经尝试了人们建议的每一种可能的修复方法,但我仍然无法让它起作用

我想知道是否有更好的方法

这是我的代码(C#-Xamarin)

使用系统;
使用Android.Support.V7.Widget;
使用System.Collections.Generic;
使用Android.Views;
使用Android.Widget;
使用System.Security.Cryptography;
使用Android.Support.V4.View;
使用Android.Support.V4.App;
使用Android.Runtime;
使用Android.OS;
使用Android.Content;
使用Android.App;
使用Android.Support.V7.App;
使用JavaString=Java.Lang.String;
使用Android.Util;
使用Android.Animation;
使用System.ComponentModel.Design.Serialization;
命名空间Answers.PortalAppXamarin.Droid
{
公共枚举MyTestAdapterItemType{
类型1,
类型2,
类型3
};
公共类MyTestDataObj
{
公共MyTestAdapterItemType类型{get;set;}
公共字符串数据{get;set;}
}
公共类PagerFragmentAdapter:Android.Support.V4.App.FragmentStatePagerAdapter{
公共列表选项卡{get;set;}
公共页面FragmentAdapter(Android.Support.V4.App.FragmentManager fm):基本(fm){
}
public override Android.Support.V4.App.Fragment GetItem(int位置){
返回制表符[位置].片段;
}
public override Java.Lang.ICharSequence GetPageTitleFormatted(int位置)
{
返回新的JavaString(制表符[位置].Title);
}
公共覆盖int GetItemPosition(Java.Lang.Object objectValue){
对于(int i=0;i{
if(RootView!=null){
RootView.Alpha=(float)e.Animation.AnimatedValue;
}
};
}
}
公共类PageFragment2:BaseFragment{
视图根视图;
创建视图上的公共覆盖视图(布局、充气机、视图组容器、捆绑包保存状态){
RootView=充气机.充气(Resource.Layout.MeasureListItem,container,false);
返回RootView;
}
恢复时公共覆盖无效()
{
base.OnResume();
ValueAnimator\u animator=ValueAnimator.offload(0,1);
_动画师:设定持续时间(2000年);
_animator.Update+=(对象发送者,ValueAnimator.AnimatorUpdateEventArgs e)=>{
if(RootView!=null){
RootView.Alpha=(float)e.Animation.AnimatedValue;
}
};
}
}
公共抽象类BaseCardViewHolder:RecyclerView.ViewHolder
{
公共视图组标题;
公共视图组页脚;
公共文本视图TitleTextView;
公共按钮MoreInfoBtn;
公共ViewPager内容ViewPager;
公共页片段适配器;
公共列表选项卡;
公共Android.Support.V4.App.FragmentManager fm;
public BaseCardViewHolder(查看rootView,Android.Support.V4.App.FragmentManager fm):基本(rootView)
{
Header=rootView.findviewbyd(Resource.Id.card\u view\u Header);
Footer=rootView.findviewbyd(Resource.Id.card\u view\u Footer);
ContentViewPager=rootView.findviewbyd(Resource.Id.card\u view\u content\u viewPager);
TitleTextView=Header.findviewbyd(Resource.Id.card\u view\u title);
MoreInfoBtn=Footer.findviewbyd(Resource.Id.card\u view\u MoreInfoBtn);
this.fm=fm;
Tabs=setupTabs();
如果(制表符!=null&&fm!=null){
适配器=新页面碎片适配器(fm);
Adapter.Tabs=Tabs;
ContentViewPager.Adapter=适配器;
}
}
public void RefreshViewPager()
{
ContentViewPager.Adapter.NotifyDataSetChanged();
}
公共摘要列表设置选项卡();
}
公共类Type1ViewHolder:BaseCardViewHolder
{
public Type1ViewHolder(View v,Android.Support.V4.App.FragmentManager-fm):基本(v,fm)
{
}
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
}
}
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DecodeFormat;
import com.peoplepost.android.R;
import com.peoplepost.android.common.listener.ItemClickSupport;
import com.peoplepost.android.network.merv.model.Product;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * Custom pager adapter which will manually create the pages needed for showing an slide pages gallery.
 * </p>
 * Created by Ionut Negru on 13/06/16.
 */
public class GalleryAdapter extends PagerAdapter {

    private static final String TAG = "GalleryAdapter";

    private final List<Item> mItems;
    private final LayoutInflater mLayoutInflater;
    /**
     * The click event listener which will propagate click events to the parent or any other listener set
     */
    private ItemClickSupport.SimpleOnItemClickListener mOnItemClickListener;

    /**
     * Constructor for gallery adapter which will create and screen slide of images.
     *
     * @param context
     *         The context which will be used to inflate the layout for each page.
     * @param mediaGallery
     *         The list of items which need to be displayed as screen slide.
     */
    public GalleryAdapter(@NonNull Context context,
                                            @NonNull ArrayList<Item> mediaGallery) {
        super();

        // Inflater which will be used for creating all the necessary pages
        mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // The items which will be displayed.
        mItems = mediaGallery;
    }

    @Override
    public int getCount() {
        // Just to be safe, check also if we have an valid list of items - never return invalid size.
        return null == mItems ? 0 : mItems.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        // The object returned by instantiateItem() is a key/identifier. This method checks whether
        // the View passed to it (representing the page) is associated with that key or not.
        // It is required by a PagerAdapter to function properly.
        return view == object;
    }

    @Override
    public Object instantiateItem(ViewGroup container, final int position) {
        // This method should create the page for the given position passed to it as an argument.
        // In our case, we inflate() our layout resource to create the hierarchy of view objects and then
        // set resource for the ImageView in it.
        // Finally, the inflated view is added to the container (which should be the ViewPager) and return it as well.

        // inflate our layout resource
        View itemView = mLayoutInflater.inflate(R.layout.fragment_gallery_item, container, false);

        // Display the resource on the view
        displayGalleryItem((ImageView) itemView.findViewById(R.id.gallery_item), mItems.get(position));

        // Add our inflated view to the container
        container.addView(itemView);

        // Detect the click events and pass them to any listeners
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (null != mOnItemClickListener) {
                    mOnItemClickListener.onItemClicked(position);
                }
            }
        });

        // Return our view
        return itemView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        // Removes the page from the container for the given position. We simply removed object using removeView()
        // but could’ve also used removeViewAt() by passing it the position.
        try {
            // Remove the view from the container
            container.removeView((View) object);

            // Try to clear resources used for displaying this view
            Glide.clear(((View) object).findViewById(R.id.gallery_item));
            // Remove any resources used by this view
            unbindDrawables((View) object);
            // Invalidate the object
            object = null;
        } catch (Exception e) {
            Log.w(TAG, "destroyItem: failed to destroy item and clear it's used resources", e);
        }
    }

    /**
     * Recursively unbind any resources from the provided view. This method will clear the resources of all the
     * children of the view before invalidating the provided view itself.
     *
     * @param view
     *         The view for which to unbind resource.
     */
    protected void unbindDrawables(View view) {
        if (view.getBackground() != null) {
            view.getBackground().setCallback(null);
        }
        if (view instanceof ViewGroup) {
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                unbindDrawables(((ViewGroup) view).getChildAt(i));
            }
            ((ViewGroup) view).removeAllViews();
        }
    }

    /**
     * Set an listener which will notify of any click events that are detected on the pages of the view pager.
     *
     * @param onItemClickListener
     *         The listener. If {@code null} it will disable any events from being sent.
     */
    public void setOnItemClickListener(ItemClickSupport.SimpleOnItemClickListener onItemClickListener) {
        mOnItemClickListener = onItemClickListener;
    }

    /**
     * Display the gallery image into the image view provided.
     *
     * @param galleryView
     *         The view which will display the image.
     * @param galleryItem
     *         The item from which to get the image.
     */
    private void displayGalleryItem(ImageView galleryView, Item galleryItem) {
        if (null != galleryItem) {
            Glide.with(galleryView.getContext()) // Bind it with the context of the actual view used
                 .load(galleryItem.getImageUrl()) // Load the image
                 .asBitmap() // All our images are static, we want to display them as bitmaps
                 .format(DecodeFormat.PREFER_RGB_565) // the decode format - this will not use alpha at all
                 .centerCrop() // scale type
                 .placeholder(R.drawable.default_product_400_land) // temporary holder displayed while the image loads
                 .animate(R.anim.fade_in) // need to manually set the animation as bitmap cannot use cross fade
                 .thumbnail(0.2f) // make use of the thumbnail which can display a down-sized version of the image
                 .into(galleryView); // Voilla - the target view
        }
    }
}
@Override
public void onBindViewHolder(MyHolder holder, int position) {
    super.onBindViewHolder(holder, position);

    Item listItem = get(position);

    ...

    GalleryAdapter adapter =
                    new GalleryAdapter(getActivity(), product.mediaGallery);
    // Set the custom click listener on the adapter directly
    adapter.setOnItemClickListener(new ItemClickSupport.SimpleOnItemClickListener() {
        @Override
        public void onItemClicked(int position) {
            // inner view pager page was clicked
        }
    });
    // Set the adapter on the view pager
    holder.imageGallery.setAdapter(adapter);

    ...
}