关于ScrollView嵌套RecyclerView的建议

博客探讨了ScrollView与RecyclerView嵌套的问题,官方并不推荐这种做法,因两者高度处理方式不同,可能导致绘制复杂和滑动冲突。建议通过重写RecyclerView布局管理器来解决复杂布局问题,同时提供了适配器、Activity使用及包含Header、Item、Footer的布局示例。
摘要由CSDN通过智能技术生成

一直都在纠结ScrollView嵌套RecyclerView这个问题。有人说大多数人不会解决。其实是不用解决!!!理由:官方不推荐这样使用,因为这两个控件的高度是不固定的,而且他们两测量高度的方法也不同。在处理的时候很复杂(你得了解ScrollView的绘制过程和RecyclerView的绘制过程),参照当前流行的网站中给出的例子(一般都是重写RecyclerView的布局管理器),而在实际的开发过程中你会发现,在滑动事件上仍然存在冲突。如果你是大神,那就当我啥都没说。

那么如何解决RecyclerView的复杂布局?

开始代码

1、适配器

package com.hs.recyclerviewadd.adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.support.v7.widget.RecyclerView;

import com.hs.recyclerviewadd.R;

/**
 * Created by zhanghaitao on 2017/6/14.
 */

public class HeaderBottomAdapter extends RecyclerView.Adapter {
    //item类型
    //在这里还是可以添加其他类型的。
    public static final int ITEM_TYPE_HEADER = 0;//头布局
    public static final int ITEM_TYPE_CONTENT = 1;//条目布局
    public static final int ITEM_TYPE_BOTTOM = 2;//脚布局

    //模拟数据(后期可以通过构造函数添加,也可以交给继承HeaderBottomAdapter的子类)
    public String[] texts = {"java", "python", "C++", "Php", ".NET", "js", "Ruby", "Swift", "OC",
            "java", "python", "C++", "Php", ".NET", "js", "Ruby", "Swift"};
    private LayoutInflater mLayoutInflater;
    private Context mContext;
    private int mHeaderCount = 1;//头部View个数
    private int mBottomCount = 1;//底部View个数

    /**
     * 构造函数(不多解释)
     *
     * @param context
     */
    public HeaderBottomAdapter(Context context) {
        mContext = context;
        mLayoutInflater = LayoutInflater.from(context);
    }

    /**
     * 获取内容的长度
     *
     * @return
     */
    public int getContentItemCount() {
        return texts.length;
    }

    /**
     * 判断当前item是否是HeadView
     *
     * @param position
     * @return
     */
    public boolean isHeaderView(int position) {
        return mHeaderCount != 0 && position < mHeaderCount;
    }

    /**
     * 判断当前item是否是FooterView
     *
     * @param position
     * @return
     */
    public boolean isBottomView(int position) {
        return mBottomCount != 0 && position >= (mHeaderCount + getContentItemCount());
    }

    /**
     * 判断当前item类型
     *
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        int dataItemCount = getContentItemCount();
        if (mHeaderCount != 0 && position < mHeaderCount) {
            //头部View
            return ITEM_TYPE_HEADER;
        } else if (mBottomCount != 0 && position >= (mHeaderCount + dataItemCount)) {
            //底部View
            return ITEM_TYPE_BOTTOM;
        } else {
            //内容View
            return ITEM_TYPE_CONTENT;
        }
    }

    /**
     * 内容 ViewHolder类
     */
    public static class ContentViewHolder extends RecyclerView.ViewHolder {
        private TextView textView;

        public ContentViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.tv_item_text);
        }
    }

    /**
     * 头部 ViewHolder
     */
    public static class HeaderViewHolder extends RecyclerView.ViewHolder {
        public HeaderViewHolder(View itemView) {
            super(itemView);

        }
    }

    //底部 ViewHolder
    public static class BottomViewHolder extends RecyclerView.ViewHolder {
        public BottomViewHolder(View itemView) {
            super(itemView);
        }
    }

    //接下来的方法是大家熟悉的方法,不作解释
    /**
     * 这个方法不能反悔为空,需要继承父类或者返回一个视图。
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == ITEM_TYPE_HEADER) {
            return new HeaderViewHolder(mLayoutInflater.inflate(R.layout.rv_header, parent, false));
        } else if (viewType == mHeaderCount) {
            return new ContentViewHolder(mLayoutInflater.inflate(R.layout.rv_item, parent, false));
        } else if (viewType == ITEM_TYPE_BOTTOM) {
            return new BottomViewHolder(mLayoutInflater.inflate(R.layout.rv_footer, parent, false));
        }
        return new ContentViewHolder(mLayoutInflater.inflate(R.layout.rv_item, parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof HeaderViewHolder) {
            ((HeaderViewHolder) holder).itemView.setVisibility(View.GONE);
        } else if (holder instanceof ContentViewHolder) {
            ((ContentViewHolder) holder).textView.setText(texts[position - mHeaderCount]);
        } else if (holder instanceof BottomViewHolder) {
        }
    }

    @Override
    public int getItemCount() {
        return mHeaderCount + getContentItemCount() + mBottomCount;
    }
}

2、在Activity中的使用

package com.hs.recyclerviewadd;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import com.hs.recyclerviewadd.adapter.HeaderBottomAdapter;

/**
 * 给RecyclerView添加头布局和脚布局
 * RecyclerView通过getItemViewType来实现复杂布局
 */
public class RecyclerActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;
    private LinearLayoutManager layoutManager;
    private HeaderBottomAdapter adapter;
    private GridLayoutManager gridLayoutManager;

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

        mRecyclerView = (RecyclerView) findViewById(R.id.rv_list);
        //List布局
        layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(layoutManager);
        mRecyclerView.setAdapter(adapter = new HeaderBottomAdapter(this));


        //Grid布局
        /*gridLayoutManager = new GridLayoutManager(MainActivity.this, 2);
        mRecyclerView.setLayoutManager(gridLayoutManager);//这里用线性宫格显示 类似于grid view
        mRecyclerView.setAdapter(adapter = new HeaderBottomAdapter(this));

        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return (adapter.isHeaderView(position) || adapter.isBottomView(position)) ? gridLayoutManager.getSpanCount() : 1;
            }
        });*/




    }
}

3、布局

header

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:id="@+id/cv_item"
    android:foreground="?android:attr/selectableItemBackground"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp"
    card_view:cardBackgroundColor="#4CAF50"
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="150dp"
        >
        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:text="Header"
            android:textSize="30sp"
            android:textColor="#ffffff"
            android:gravity="center"
            />
    </LinearLayout>
</android.support.v7.widget.CardView>

item

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cv_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:foreground="?android:attr/selectableItemBackground"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_item_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="8dp"
            android:text="test" />
    </LinearLayout>

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

footer

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cv_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:foreground="?android:attr/selectableItemBackground"
    card_view:cardBackgroundColor="#E91E63"
    card_view:cardCornerRadius="4dp"
    card_view:cardElevation="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="150dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="Footer"
            android:textColor="#ffffff"
            android:textSize="30sp" />
    </LinearLayout>
</android.support.v7.widget.CardView>








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值