RecyclerView实现滚动轮

实现原理使用LinearSnalphelper实现元素居中(如果对SnapHelper不了解的话建议百度下),使用ViewType实现偏移。

具体效果:这里写图片描述

实现:

package com.david.mytest.test.wheeltest;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.LinearSnapHelper;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.david.mytest.R;
import com.david.mytest.ui.pulltorefresh.pulltorefreshorigin.progress.Utils;

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

/**
* Created by wb-cuiweixing on 2016/7/5.
*/
public class RecyclerWheelView extends RecyclerView {
public interface OnSelectListener{
void onSelect(int position);
}

private ArrayList<String> mData;
private int mOffset = 2;//默认每页显示五条
private float mItemHeight;
private int mWidth;
private LinearLayoutManager mManager;
private LinearSnapHelper mSnapHelper;

private OnSelectListener mOnSelectListener;

public RecyclerWheelView(Context context) {
    super(context);
    initData();
}

public RecyclerWheelView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    initData();
}

public RecyclerWheelView(Context context, @Nullable AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    initData();
}

private void initData() {
    mData = new ArrayList<>();

    mItemHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45, getResources().getDisplayMetrics());
    mManager = new LinearLayoutManager(getContext());
    mManager.setOrientation(LinearLayoutManager.VERTICAL);

    if (null == paint) {
        paint = new Paint();
        paint.setColor(Color.parseColor("#83cde6"));
        paint.setStrokeWidth(Utils.dp2px(getResources(), 1f));
    }
    post(new Runnable() {
        @Override
        public void run() {//RecyclerView还未初始化完成不能直接调用其方法否则会报空指针,类构造方法中只能进行初始化成员变量
            getLayoutParams().height = (int) (mItemHeight * (mOffset * 2 + 1));
            setLayoutManager(mManager);

            setAdapter(new MySpaceAdapter());

            getAdapter().notifyDataSetChanged();

            mWidth = getWidth();
        }
    });

    mSnapHelper = new LinearSnapHelper();
    mSnapHelper.attachToRecyclerView(this);
}

public ArrayList<String> getData() {
    if (mData.size() < 1) {
        return null;
    }
    ArrayList<String> data = new ArrayList<>();
    for (int i = 1; i < mData.size() - 1; i++) {
        data.add(mData.get(i));
    }
    return data;
}

public void setData(ArrayList<String> data) {
    this.mData.clear();
    this.mData.addAll(data);
    mData.add(0, null);
    mData.add(null);
    if (getAdapter() != null)
        getAdapter().notifyDataSetChanged();
}

private List<TextView> textViews;

/**
 * RecyclerView实现WheelView
 */
class MySpaceAdapter extends RecyclerView.Adapter {


    MySpaceAdapter() {
        textViews = new ArrayList<>();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == 1) {
            return new SpaceViewHolder(new View(getContext()));
        } else {
            View view = LayoutInflater.from(getContext()).inflate(R.layout.item_recycler_wheel, parent, false);
            textViews.add((TextView) view);
            return new NormalViewHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof NormalViewHolder) {
            TextView textView = ((NormalViewHolder) holder).mText;
            textView.setText(mData.get(position));
        }
    }

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

    @Override
    public int getItemViewType(int position) {
        return (position == 0 || position == mData.size() - 1) ? 1 : 0;
    }
}

class NormalViewHolder extends RecyclerView.ViewHolder {
    TextView mText;

    NormalViewHolder(View itemView) {
        super(itemView);
        mText = (TextView) itemView;
        mText.getLayoutParams().height = (int) mItemHeight;
    }
}

class SpaceViewHolder extends RecyclerView.ViewHolder {
    SpaceViewHolder(View itemView) {
        super(itemView);
        //根据每一条高度及偏移量设置高度
        float height = mOffset * mItemHeight;
        itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) height));
    }
}

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    super.onScrollChanged(l, t, oldl, oldt);
    /**
     * 手动滑动或者惯性滑动时触发该方法,不过由于本身没有滑动所以l,t,oldl,oldt都是0
     * 此处只是在滑动时设置相应状态
     */
    View viewContainer = mSnapHelper.findSnapView(mManager);//获取中间位置的view
    TextView textView = ((NormalViewHolder) getChildViewHolder(viewContainer)).mText;

    int centerPosition = mData.indexOf(textView.getText().toString());
    if (mCenterPosition == centerPosition) {
        return;
    }
    mCenterPosition = centerPosition;

    for (TextView view : textViews) {//设置选中颜色
        view.setTextColor(Color.parseColor("#dddddd"));
        if (view == textView) {
            view.setTextColor(Color.parseColor("#0288ce"));
        }
    }

    if (mOnSelectListener != null) {
        //第一条是占位条
        mOnSelectListener.onSelect(mCenterPosition - 1);
    }
}

private int mCenterPosition;//获取选中位置时要减一(有占位条)
private Paint paint;

/**
 * 获取选中区域的边界
 */
private int[] selectedAreaBorder;

private int[] obtainSelectedAreaBorder() {
    if (null == selectedAreaBorder) {
        selectedAreaBorder = new int[2];
        selectedAreaBorder[0] = (int) (mItemHeight * mOffset);
        selectedAreaBorder[1] = (int) (mItemHeight * (mOffset + 1));
    }
    return selectedAreaBorder;
}

@Override
public void onDraw(Canvas c) {
    super.onDraw(c);
    c.drawLine(mWidth * 1.0F / 6, obtainSelectedAreaBorder()[0], mWidth * 5 / 6, obtainSelectedAreaBorder()[0], paint);
    c.drawLine(mWidth * 1.0F / 6, obtainSelectedAreaBorder()[1], mWidth * 5 / 6, obtainSelectedAreaBorder()[1], paint);
}

public void setmOnSelectListener(OnSelectListener mOnSelectListener) {
    this.mOnSelectListener = mOnSelectListener;
}

}

一般是用点击确定后获取选中位置,OnSelectListener是在滑动选中时执行的。

猜你喜欢

转载自blog.csdn.net/divaid/article/details/74940969