双recyclerview实现持仓横滑持仓列表

先上效果图:

 

如图所示,左侧一列固定不动,右侧横滑列表。

实现方案:左侧固定列使用recyclerview,右侧HorizontalScrollView嵌套recyclerview;

布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    >
    <data>
        <variable
            name="presenter"
            type="com.zj.holdlist.MainActivity"/>
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >
        <LinearLayout
            android:layout_width="120dp"
            android:layout_height="match_parent"
            android:background="#FAFAFA"
            android:orientation="vertical"
            android:focusable="true"
            >
            <TextView
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:text="币对名称"
                android:gravity="center"
                android:textColor="@color/colorPrimaryDark"
                android:textSize="14sp"
                android:background="#f0f0f0"
                />
            <android.support.v7.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/recycle_coin_name"
                android:overScrollMode="never"
                ></android.support.v7.widget.RecyclerView>
        </LinearLayout>

        <HorizontalScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:ignore="NewApi"
            android:overScrollMode="never"
            android:scrollbars="none"
            >
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >
                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="40dp"
                    android:orientation="horizontal"
                    android:background="#FAFAFA"
                    >
                    <TextView
                        android:layout_width="120dp"
                        android:layout_height="40dp"
                        android:text="title1"
                        android:gravity="center"
                        android:textColor="@color/colorPrimaryDark"
                        android:textSize="14sp"
                        android:background="#f0f0f0"
                        />
                    <TextView
                        android:layout_width="120dp"
                        android:layout_height="40dp"
                        android:text="title2"
                        android:gravity="center"
                        android:textColor="@color/colorPrimaryDark"
                        android:textSize="14sp"
                        android:background="#f0f0f0"
                        />
                    <TextView
                        android:layout_width="120dp"
                        android:layout_height="40dp"
                        android:text="title3"
                        android:gravity="center"
                        android:textColor="@color/colorPrimaryDark"
                        android:textSize="14sp"
                        android:background="#f0f0f0"
                        />
                    <TextView
                        android:layout_width="120dp"
                        android:layout_height="40dp"
                        android:text="title4"
                        android:gravity="center"
                        android:textColor="@color/colorPrimaryDark"
                        android:textSize="14sp"
                        android:background="#f0f0f0"
                        />
                    <TextView
                        android:layout_width="120dp"
                        android:layout_height="40dp"
                        android:text="title5"
                        android:gravity="center"
                        android:textColor="@color/colorPrimaryDark"
                        android:textSize="14sp"
                        android:background="#f0f0f0"
                        />
                    <TextView
                        android:layout_width="120dp"
                        android:layout_height="40dp"
                        android:text="title6"
                        android:gravity="center"
                        android:textColor="@color/colorPrimaryDark"
                        android:textSize="14sp"
                        android:background="#f0f0f0"
                        />
                </LinearLayout>
                <android.support.v7.widget.RecyclerView
                    android:layout_width="720dp"
                    android:layout_height="match_parent"
                    android:id="@+id/recycle_coin_data"
                    android:overScrollMode="never"
                    ></android.support.v7.widget.RecyclerView>
            </LinearLayout>
        </HorizontalScrollView>
    </LinearLayout>
</layout>
布局文件有了,开始写adapter,填充数据。
public class CoinAdapter extends AbsRVAdapter<CoinBean,AbsRVAdapter.BindingViewHolder> {
    private final static int TYPE_NAME=0;
    private final static int TYPE_DATA=1;
    public CoinAdapter(Context context) {
        super(context);
    }

    @NonNull
    @Override
    public BindingViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
        ViewDataBinding binding;
        if (i==TYPE_NAME){
            binding=ItemCoinValueBinding.inflate(mInflater,parent,false);
        }else {
            binding= ItemDataValueBinding.inflate(mInflater,parent,false);
        }
        return new BindingViewHolder(binding);
    }

    @Override
    public void onBindViewHolder(@NonNull BindingViewHolder holder, int position) {
        CoinBean bean= (CoinBean) getItem(position);
        if (holder.mBinding instanceof ItemCoinValueBinding){
            ItemCoinValueBinding binding= (ItemCoinValueBinding) holder.mBinding;
            binding.setData(bean);
            binding.setPos(position);
        }else if (holder.mBinding instanceof ItemDataValueBinding){
            ItemDataValueBinding binding= (ItemDataValueBinding) holder.mBinding;
            binding.setData(bean);
            binding.setPos(position);
        }

    }

    @Override
    public int getItemViewType(int position) {
        List<CoinBean> list=getDataList();
        if (list!=null){
            return list.get(position).viewType==0?TYPE_NAME:TYPE_DATA;
        }else{
            return super.getItemViewType(position);
        }
    }
}

主要两个布局,一个是左侧item,一个是右侧。差点忘了AbsRVAdapter是我封装的一个基类,代码奉上.


import android.content.Context;
import android.databinding.ViewDataBinding;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;

import java.util.ArrayList;
import java.util.List;

/**
 * {@link RecyclerView}适配器基类
 *
 * @author Created by zh on 2018/12/09.
 */

public abstract class AbsRVAdapter<E, T extends AbsRVAdapter.BindingViewHolder> extends RecyclerView.Adapter<T> {
    private List<E> mDataList;
    protected Context mContext;
    protected LayoutInflater mInflater;

    public AbsRVAdapter(Context context) {
        this.mContext = context;
        this.mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getItemCount() {
        return mDataList == null ? getHeaderItemCount() : getHeaderItemCount() + mDataList.size();
    }

    public int getHeaderItemCount() {
        // 在列表顶部不包含在数据列表中的Item数量,并非ListView的Header数
        // 头部Item数量+dataList数量等于总的Item数量,子类必须返回正确的头部Item数量来保证映射数据列表正确
        return 0;
    }

    public Object getItem(int position) {
        if (position < getHeaderItemCount()) {
            return getHeaderItem(position);
        } else {
            return mDataList == null ? null : mDataList.get(position - getHeaderItemCount());
        }
    }

    public Object getHeaderItem(int position) {
        return null;
    }

    /**
     * 列表Item的位置获取对应数据列表的索引,如果找不到将返回-1
     *
     * @param position item位置
     * @return item对应的数据项位置
     */
    public int getDataIndex(int position) {
        if (position < getHeaderItemCount()) {
            return -1;
        }
        return position - getHeaderItemCount();
    }

    public int getDataCount() {
        return mDataList == null ? 0 : mDataList.size();
    }

    public boolean isEmpty() {
        return getItemCount() == 0;
    }

    public void addData(List<E> data) {
        if (data == null || data.isEmpty()) {
            return;
        }
        int addCount = data.size();
        if (mDataList == null) {
            mDataList = new ArrayList<>(addCount);
        }
        int startPos = getItemCount();
        mDataList.addAll(data);
        notifyItemRangeInserted(startPos, addCount);
    }

    public void addDataToStart(E data) {
        if (data == null) {
            return;
        }
        if (mDataList == null) {
            mDataList = new ArrayList<>();
        }
        mDataList.add(0, data);
        notifyItemInserted(0);
    }

    public void addDataToTail(E data) {
        if (data == null) {
            return;
        }
        if (mDataList == null) {
            mDataList = new ArrayList<>();
        }
        int pos = getItemCount();
        mDataList.add(data);
        notifyItemInserted(pos);
    }

    public void clearData() {
        if (mDataList != null && mDataList.size() > 0) {
            mDataList.clear();
            notifyDataSetChanged();
        }
    }

    public void setData(List<E> data) {
        mDataList = data;
        notifyDataSetChanged();
    }

    public List<E> getDataList() {
        return mDataList;
    }

    public void addData(int index, E data) {
        if (data == null) {
            return;
        }
        if (mDataList == null) {
            mDataList = new ArrayList<>();
        }
        mDataList.add(index, data);
        notifyItemInserted(getHeaderItemCount() + index);
    }

    public void setDataIndex(int index,E data){
        if (data==null){
            return;
        }
        if (mDataList==null){
            mDataList = new ArrayList<>();
        }
        mDataList.set(index,data);
        notifyItemChanged(getHeaderItemCount() + index);
    }

    public void removeData(int index) {
        if (mDataList == null) {
            return;
        }
        mDataList.remove(index);
        notifyItemRemoved(getHeaderItemCount() + index);
    }

    public static class BindingViewHolder extends RecyclerView.ViewHolder {
        public ViewDataBinding mBinding;

        public BindingViewHolder(ViewDataBinding binding) {
            super(binding.getRoot());
            this.mBinding = binding;
        }
    }
}

adapter有了开始填充数据:

简单for循环,o(╥﹏╥)o

 public void initData(){
        List<CoinBean> nameList=new ArrayList<>();
        for (int i=0;i<20;i++){
            CoinBean bean=new CoinBean();
            bean.coinName="BTC"+i;
            bean.pairName="pairName"+i;
            bean.pairUnit="pairUnit"+i;
            bean.current="current"+i;
            bean.currentCny="currentCny"+i;
            bean.change="change"+i;
            bean.changeRate="changeRate"+i;
            bean.viewType=0;
            nameList.add(bean);
        }
        nameAdapter.setData(nameList);

        List<CoinBean> dataList=new ArrayList<>();
        for (int i=0;i<20;i++){
            CoinBean bean=new CoinBean();
            bean.coinName="BTC"+i;
            bean.pairName="pairName"+i;
            bean.pairUnit="pairUnit"+i;
            bean.current="current"+i;
            bean.currentCny="currentCny"+i;
            bean.change="change"+i;
            bean.changeRate="changeRate"+i;
            bean.viewType=1;
            dataList.add(bean);
        }
        dataAdapter.setData(dataList);
    }

这时最基本的完成了,看下效果:

大家都能看到问题,没错左右两边不同步;

简单的思路,监听两个recyclerview的滚动事件,让另一个滚动相同的距离。

走起:

binding.recycleCoinName.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                
                binding.recycleCoinData.scrollBy(0,dy);
               
            }
        });

        binding.recycleCoinData.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                
                binding.recycleCoinName.scrollBy(0,dy);
               

            }
        });

然后我们发现这么搞不行,哈哈

添加判断条件如果是左侧recyclerview在滑动时,右侧跟着移动,否则不移动;

如何判断呢,setOnTouchListener!!!

//左侧name
binding.recycleCoinName.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                //手势在左侧时,右侧跟随滚动
                if (isNameScroll){
                    binding.recycleCoinData.scrollBy(0,dy);
                }
            }
        });

//右侧数据源
        binding.recycleCoinData.setOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                //手势在右侧时,左侧跟随滚动
                if (!isNameScroll){
                    binding.recycleCoinName.scrollBy(0,dy);
                }

            }
        });
//
        binding.recycleCoinData.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        isNameScroll=false;
                        break;
                }
                return false;
            }
        });


        binding.recycleCoinName.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        isNameScroll=true;
                        break;
                }
                return false;
            }
        });

到这里这个简单的demo完成。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值