美文网首页RecyclerViewAndroid 进阶之路Android开发
【 Android 】使用 RecyclerView 实现页面滑

【 Android 】使用 RecyclerView 实现页面滑

作者: Tyhoo_Wu | 来源:发表于2017-09-02 16:37 被阅读268次

示例图片:


1.gif

实现思路:
开发文档要求这个页面,上半部分不动,下半部分当一个页面展示不全,是可以滑动的。
我最初的想法是 ScrollView + RecyclerView 。但是在机器上运行之后,发现控件之间发生了冲突,RecyclerView 显示不全。经过了一段时间的思考,最终选择使用 RecyclerView + RecyclerView 实现页面滑动和多个不同类别的 item 展示。

其实网上关于 RecyclerView 的相关文档有很多,但是我觉得都是打补丁的方法,没有真正意义上的使用 RecyclerView 。

代码实现(核心代码部分):

从示例图中,可以看到,整个页面分为两大部分 A 是不可以滑动的上半部分,B 是可以滑动的下半部分。而 B 又分为三个小部分,B1 是一大堆文字描述,B2 是一个用于展示有多少个演员的 RecyclerView ,B3 是一个用于展示有多少个作品的 RecyclerView 。

那么很显然,我们要在主布局页面创建一个 RecyclerView:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    ...

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

</LinearLayout>

并在主类里面将 B1,B2,B3,按照顺序一次添加:

public class MainActivity extends AppCompatActivity {

    private List<Integer> mTypeList = new ArrayList<>();

    ...

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

        initParam();

        ...
    }

    private void initParam() {
        mTypeList.add(1);   // B1
        mTypeList.add(2);   // B2
        mTypeList.add(3);   // B3
    }

    ...
}

然后就是我们的核心部分 Adapter ,继承 RecyclerView.Adapter<RecyclerView.ViewHolder>
定义 B1,B2,B3 三个常量:

private static final int TYPE_B1 = 1;
private static final int TYPE_B2 = 2;
private static final int TYPE_B3 = 3;

重写 getItemViewType 方法,参数 position 代表 RecyclerView 的位置,而 int 型的返回值代表了布局的类型,即 B1 是 1,B2 是 2,B3 是 3。

@Override
public int getItemViewType(int position) {
    if (mTypeList.get(position) == 1) {         // B1
        return TYPE_B1;
    } else if (mTypeList.get(position) == 2) {  // B2
        return TYPE_B2;
    } else if (mTypeList.get(position) == 3) {  // B3
        return TYPE_B3;
    } else {
        return 0;
    }
}

自定义三个 ViewHolder:

public class B1ViewHolder extends RecyclerView.ViewHolder {

    public MainDetailsViewHolder(View itemView) {
        super(itemView);
    }
}
public class B2ViewHolder extends RecyclerView.ViewHolder {

    public RecyclerView b2RecyclerView;

    public MainActorsViewHolder(View itemView) {
        super(itemView);
        aRecyclerView = itemView.findViewById(R.id.rcv_b2);
    }
}
public class B3ViewHolder extends RecyclerView.ViewHolder {

    public RecyclerView b3RecyclerView;

    public MainActorsViewHolder(View itemView) {
        super(itemView);
        aRecyclerView = itemView.findViewById(R.id.rcv_b3);
    }
}

重写 onCreateViewHolder 方法,返回一个自定义的 ViewHolder (当 RecyclerView 需要一个 ViewHolder 时会回调该方法,如果有可复用的 View 不会回调)。

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_B1) {        // B1
        View viewB1 = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_b1, parent, false);
        B1ViewHolder b1Holder = new B1ViewHolder(viewB1);
        return b1Holder;
    } else if (viewType == TYPE_B2) {  // B2
        View viewB2 = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_b2, parent, false);
        B2ViewHolder b2Holder = new B2ViewHolder(viewB2);
        return b2Holder;
    } else if (viewType == TYPE_B3) {   // B3
        View viewB3 = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_b3, parent, false);
        B3ViewHolder b3Holder = new B3ViewHolder(viewB3);
        return b3Holder;
    }
    return null;
}

重写 onBindViewHolder 方法,填充 onCreateViewHolder 方法返回的 holder 中的控(当一个 View 需要出现在屏幕上时,该方法会被回调,我们需要再该方法中根据数据来更改视图)。

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof B2ViewHolder) {
        setB2Data((B2ViewHolder) holder);
    } else if (holder instanceof B3ViewHolder) {
        setB3Data((B3ViewHolder) holder);
    }
}

重写 getItemCount 方法,获取数据的数量(告诉 RecyclerView 有多少个视图需要显示)。

private final Context mContext;
private final List<Integer> mTypeList;

public MainAdapter(Context context, List<Integer> list) {
    this.mContext = context;
    this.mTypeList = list;
}

@Override
public int getItemCount() {
    return mTypeList.size();
}

上面代码涉及到三个子布局 layout_b1 、layout_b2 、layout_b3 。
layout_b1 从上面的示例图中可以看到就是一堆文字排列。
layout_b2 、layout_b3 是我们今天的重点:RecyclerView 嵌套 RecyclerView 。

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

    ...

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rcv_b2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

既然有 RecyclerView 那么就会有 Adapter ,自定义 B2 和 B3 对应的 Adapter 。
(item 布局就不啰嗦了,很简单)

public class B2Adapter extends RecyclerView.Adapter<B2Adapter.B2Holder> {

    private final Context mContext;

    private OnItemClickListener mListener;

    public B2Adapter(Context context) {
        this.mContext = context;
    }

    @Override
    public B2Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext)
                .inflate(R.layout.item_b2, parent, false);
        B2Holder holder = new B2Holder(view);
        return holder;
    }

    @Override
    public void onBindViewHolder(final B2Holder holder, int position) {
        if (mListener != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListener.onItemClick(holder.getLayoutPosition());
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return 5;
    }

    public class B2Holder extends RecyclerView.ViewHolder {

        public B2Holder(View itemView) {
            super(itemView);
        }
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.mListener = onItemClickListener;
    }
}
public interface OnItemClickListener {
    void onItemClick(int position);
}

B3 和 B2 类似,就不赘述了。

自定义完 子 Adapter ,我们就要回到主 Adapter 里面去调用。

private void setB2Data(B2ViewHolder holder) {
    setB2RecyclerView(holder.b2RecyclerView);
}
private void setB2RecyclerView(RecyclerView b2RecyclerView) {
    B2Adapter b2Adapter = new B2Adapter(mContext);
    LinearLayoutManager layoutManager = new LinearLayoutManager(mContext);
    layoutManager.setOrientation(OrientationHelper.VERTICAL);
    b2RecyclerView.setLayoutManager(layoutManager);
    b2RecyclerView.setHasFixedSize(false);
    b2RecyclerView.setAdapter(b2Adapter);

    b2Adapter.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(int position) {
            // TODO:
        }
    });
}

B3 和 B2 类似,就不赘述了。

注意:
如果我们的界面是嵌套在可以左右滑动的控件里,这时会发生焦点的问题,导致整体界面向上移动一小部分,解决办法是在布局的最外层加入:

android:focusable="true"
android:focusableInTouchMode="true"

综上所述,就完成了 RecyclerView 的使用,避免了 ScrollView + RecyclerView 在一起使用会出现冲突的问题。

相关文章

网友评论

本文标题:【 Android 】使用 RecyclerView 实现页面滑

本文链接:https://www.haomeiwen.com/subject/hsdrjxtx.html