垂直 RecyclerView 内的水平 RecyclerView

Posted

技术标签:

【中文标题】垂直 RecyclerView 内的水平 RecyclerView【英文标题】:Horizontal RecyclerView inside Vertical RecyclerView 【发布时间】:2017-01-18 08:57:11 【问题描述】:

我正在尝试制作这样的东西。

所以我的想法是我有一个带有通道的垂直 recyclerview,在通道的第二个位置我应该有一个带有 relives 的水平 recyclerview。

我不知道我应该怎么做,我试着弄乱了视图,我想我应该在我的 channel_details 布局中只创建一个 recyclerview,另一个作为 item_channel_details 中的项目,但我无法做到工作。

这是我的代码。

ChannelDetailsActivity:

 @Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_channel_details);

    ImageView coverPhoto = (ImageView) findViewById(R.id.image_cover_details);
    final HexagonImageView avatarPhoto = (HexagonImageView) findViewById(R.id.img_hex);
    TextView toolbarText = (TextView) findViewById(R.id.txt_toolbar_title);

    final Bundle b = getIntent().getExtras();
    final MNetworkChannel parcelChannel =
            b.getParcelable(Const.IntentData.H_CHANNEL_LIST);

    final MVideosForChannel parcelVideosForChannel = b.getParcelable(Const.IntentData.D_VIDEOS_LIST);




    setChannelsView();
    setVideosView();




private void setChannelsView() 

    rvRelive = (RecyclerView) findViewById(R.id.rv_relive_details);
    rvRelive.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
    adapterRelives = new ReliveAdapter();
    rvRelive.setAdapter(adapterRelives);

    if (getIntent() != null && getIntent().getParcelableExtra(Const.IntentData.D_RELIVE_LIST) != null) 
        adapterRelives.setData(((ReliveMainPojo) getIntent().getParcelableExtra(Const.IntentData.D_RELIVE_LIST)).relives);
    


private void setVideosView() 

    rvVideos = (RecyclerView) findViewById(R.id.rv_videos);
    rvVideos.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    adapterVideos = new ChannelVideosAdapter();
    rvVideos.setAdapter(adapterVideos);

    if (getIntent() != null && getIntent().getParcelableExtra(Const.IntentData.D_VIDEOS_LIST) != null) 
        adapterVideos.setData(((MVideosForChannel) getIntent().getParcelableExtra(Const.IntentData.D_VIDEOS_LIST)).experience);
    

ChannelDetails 适配器:

public final class ChannelVideosAdapter extends RecyclerView.Adapter<ChannelVideosAdapter.ViewHolder> 

private List<MVideo> data = new ArrayList<>();

public ChannelVideosAdapter() 


public void setData(List<MVideo> newData) 

    if (newData != null && !newData.isEmpty()) 

        data = newData;
        notifyDataSetChanged();
    


public void clearData() 

    data.clear();
    notifyDataSetChanged();


@Override
public final ChannelVideosAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) 
    return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_video_recycle_tile, parent, false));


@Override
public final void onBindViewHolder(final ChannelVideosAdapter.ViewHolder holder, final int position) 

    final MVideo video = data.get(position);

    final String videoBackgroundImageUrl = video.asset.frame;
    final String videoName = video.name;

    ImageLoader.getInstance().displayImage(videoBackgroundImageUrl, holder.coverPhoto, new ImageLoadingListener() 
        @Override
        public void onLoadingStarted(String imageUri, View view) 
            holder.videoLoading.setVisibility(View.VISIBLE);
        

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) 
            holder.videoLoading.setVisibility(View.GONE);
        

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) 
            holder.videoLoading.setVisibility(View.GONE);
        

        @Override
        public void onLoadingCancelled(String imageUri, View view) 
            holder.videoLoading.setVisibility(View.GONE);
        
    );

    holder.videoName.setText(videoName);
    holder.itemView.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            VideoPlayerActivity.StartNewVideoPlayerActivity((ChannelDetailsActivity) holder.itemView.getContext(), video, true);
        
    );


@Override
public final int getItemCount() 
    return data.size();


final class ViewHolder extends RecyclerView.ViewHolder 

    private final ImageView coverPhoto;
    private final TextView videoName;
    private final ProgressBar videoLoading;

    ViewHolder(final View itemView) 
        super(itemView);

        coverPhoto = (ImageView) itemView.findViewById(R.id.img_thumbnail_background_video);
        videoName = (TextView) itemView.findViewById(R.id.txt_video_name);
        videoLoading = (ProgressBar) itemView.findViewById(R.id.pb_video_loading);
    


重温适配器:

public final class ReliveAdapter extends RecyclerView.Adapter<ReliveAdapter.ViewHolder> 

private List<Relive> data = new ArrayList<>();

public ReliveAdapter() 


public void setData(List<Relive> newData) 

    if (newData != null && !newData.isEmpty()) 

        data = newData;
        notifyDataSetChanged();
    


public void clearData() 

    data.clear();
    notifyDataSetChanged();


@Override
public final ReliveAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, final int viewType) 
    return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_relive_recycle_tile, parent, false));


@Override
public void onBindViewHolder(final ReliveAdapter.ViewHolder holder, final int position) 

    final Relive relive = data.get(position);

    final String reliveOwnerIconUrl = relive.owner.asset.large;
    final String reliveCoverPhotoUrl = relive.asset.stream.thumbnail;
    final String reliveDescription = relive.owner.name;

    ImageLoader.getInstance().displayImage(reliveCoverPhotoUrl, holder.backgroundImage, new ImageLoadingListener() 
        @Override
        public void onLoadingStarted(String imageUri, View view) 
            holder.imageLoading.setVisibility(View.VISIBLE);
        

        @Override
        public void onLoadingFailed(String imageUri, View view, FailReason failReason) 
            holder.imageLoading.setVisibility(View.GONE);
        

        @Override
        public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) 
            holder.imageLoading.setVisibility(View.GONE);

            ImageLoader.getInstance().displayImage(reliveOwnerIconUrl, holder.profilePicture, new ImageLoadingListener() 
                @Override
                public void onLoadingStarted(String imageUri, View view) 
                    holder.imageLoading.setVisibility(View.VISIBLE);
                

                @Override
                public void onLoadingFailed(String imageUri, View view, FailReason failReason) 
                    holder.imageLoading.setVisibility(View.GONE);
                

                @Override
                public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) 
                    holder.imageLoading.setVisibility(View.GONE);
                

                @Override
                public void onLoadingCancelled(String imageUri, View view) 
                    holder.imageLoading.setVisibility(View.GONE);
                
            );

            holder.eyeIcon.setImageResource(R.drawable.relive);
        

        @Override
        public void onLoadingCancelled(String imageUri, View view) 
            holder.imageLoading.setVisibility(View.GONE);
        
    );

    holder.reliveDescription.setText(reliveDescription);

    holder.itemView.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 
            RelivePlayerActivity.StartReliveReviewActivity((ChannelDetailsActivity) holder.itemView.getContext(), relive.asset.stream.url, relive.experienceGuid, relive.guid, holder.getAdapterPosition());
        
    );


@Override
public final int getItemCount() 
    return data.size();


final class ViewHolder extends RecyclerView.ViewHolder 

    private final CircleImageView profilePicture;
    private final ImageView eyeIcon;
    private final ImageView backgroundImage;
    private final TextView reliveDescription;
    private final ProgressBar imageLoading;

    ViewHolder(View itemView) 
        super(itemView);

        profilePicture = (CircleImageView) itemView.findViewById(R.id.profile_circle_image);
        eyeIcon = (ImageView) itemView.findViewById(R.id.icon_circle_image);
        backgroundImage = (ImageView) itemView.findViewById(R.id.thumbnail_image);
        reliveDescription = (TextView) itemView.findViewById(R.id.description_textview);
        imageLoading = (ProgressBar) itemView.findViewById(R.id.image_loading);
    

这是我的布局:

activity_channel_details

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout      xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical">

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar_details"
    android:layout_
    android:layout_
    android:background="#017789"
    android:textAlignment="center">

    <TextView
        android:id="@+id/txt_toolbar_title"
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:textColor="@android:color/white"
        android:textStyle="bold" />

    <ImageView
        android:layout_
        android:layout_
        android:layout_gravity="end"
        android:layout_marginEnd="10dp"
        android:background="@color/white_trans"
        android:src="@drawable/zeality" />

</android.support.v7.widget.Toolbar>

<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:background="#fff"
    android:orientation="vertical">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_
        android:layout_
        android:background="#ffff"
        android:orientation="vertical">


        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_
            android:layout_
            android:background="#ffff"
            android:orientation="vertical">

            <RelativeLayout
                android:layout_
                android:layout_>

                <ImageView
                    android:id="@+id/image_cover_details"
                    android:layout_
                    android:layout_
                    android:adjustViewBounds="true"
                    android:scaleType="fitXY" />

                <FrameLayout
                    android:id="@+id/frame"
                    android:layout_
                    android:layout_
                    android:layout_centerInParent="true">

                    <co.zeality.vrplayer.views.HexagonImageView
                        android:id="@+id/img_hex"
                        android:layout_
                        android:layout_
                        android:layout_alignParentTop="true"
                        android:layout_centerHorizontal="true"
                        android:scaleType="fitXY" />

                </FrameLayout>

            </RelativeLayout>

            <RelativeLayout
                android:layout_
                android:layout_
                android:layout_marginTop="5dp">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/rv_videos"
                    android:layout_
                    android:layout_
                    android:nestedScrollingEnabled="false" />
            </RelativeLayout>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/rv_relive_details"
                android:layout_
                android:layout_ />

        </LinearLayout>
    </LinearLayout>

</android.support.v4.widget.NestedScrollView>

item_video_recycle_tile

 <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout   xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
android:orientation="vertical">

<ImageView
    android:id="@+id/img_thumbnail_background_video"
    android:layout_
    android:layout_
    android:adjustViewBounds="true" />

<FrameLayout
    android:id="@+id/frame_image"
    android:layout_
    android:layout_
    android:layout_centerInParent="true">

    <ProgressBar
        android:id="@+id/pb_video_loading"
        android:layout_
        android:layout_
        android:layout_gravity="center"
        android:foregroundGravity="center"
        android:visibility="gone" />

    <ImageView
        android:layout_
        android:layout_
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="40dp"
        android:src="@drawable/glasses" />
</FrameLayout>

<FrameLayout
    android:layout_
    android:layout_
    android:layout_alignParentBottom="true"
    android:layout_alignParentStart="true">

    <RelativeLayout
        android:layout_
        android:layout_>

        <ImageView
            android:id="@+id/img_play_button"
            android:layout_
            android:layout_
            android:layout_marginBottom="5dp"
            android:layout_marginStart="10dp"
            android:src="@drawable/play_no_circle" />

        <TextView
            android:id="@+id/txt_video_name"
            android:layout_
            android:layout_marginBottom="5dp"
            android:layout_
            android:layout_below="@id/img_play_button"
            android:layout_marginStart="5dp"
            android:textColor="#FFF" />
    </RelativeLayout>
</FrameLayout>

<View
    android:layout_
    android:layout_
    android:layout_alignParentBottom="true"
    android:background="#660c7582"></View>

【问题讨论】:

将一个recyclerview与linearlayout manager一起使用,它的item作为另一个recyclerview与gridlayout manager一起使用。 您需要在适配器中处理此问题。您将确定您希望在哪个位置拥有一个水平 RecyclerView,并且您将为那里的特定适配器位置创建不同的视图。在那个位置,您将创建自己的视图以成为 Recycler 【参考方案1】:

您应该使用一个 recyclerView(垂直)作为父级,并且在位置 1 的适配器中绑定视图时,您返回一个包含 recyclerView(水平)的视图并为该 recyclerView 加载其他适配器。请参考图表以获得正确的理解。

Main RecyclerView (vertical):   
    ---------------------------
    +   Item 1
    ---------------------------
    +   Second RecyclerView (Horizontal)
    ---------------------------
    +   Item 2
    ---------------------------

父 RecyclerView 适配器代码:

    @Override
        public int getItemViewType(int position) 

            if (position == 1)
                return 0;
            else 
                return 1;
        
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 

        if (viewType == 0) 
            View v = LayoutInflater.from(context).inflate(R.layout.your_second_recylerView_layout, parent, false);
            return new ViewHolder1(v);
        
        else
            View v = LayoutInflater.from(context).inflate(R.layout.your_item_layout, parent, false);
            return new ViewHolder2(v);
        

    

现在您需要为水平 recycleView 实现第二个适配器。

【讨论】:

感谢您的回答。我试着弄乱它,但它仍然太复杂了。您是否有某种参考或样本?

以上是关于垂直 RecyclerView 内的水平 RecyclerView的主要内容,如果未能解决你的问题,请参考以下文章

Android 布局:具有滚动行为的 Viewpager 内的垂直 Recyclerview 内的水平 Recyclerview

如何修复垂直 RecyclerView 内的水平 ViewPager2 和 RecyclerView 的滚动问题?

NestedScrollView 内的 RecyclerView :使水平滚动更容易

在垂直 recyclerView 中带有 wrap_content 的水平 recyclerView

在垂直 RecyclerView 中显示水平 RecyclerView 时获得闪烁效果

创建具有水平和垂直滚动的 RecyclerView