Android 仿拼多多可水平滚动RecyclerView,自定义滚动条滚动距离

2020年,希望大家一切平安如意,毕竟这是个出人意料的多事之秋。

一.效果图:

 

二.快速实现:

1.主函数代码:

import android.content.Context;import android.graphics.Color;import android.os.Bundle;import android.os.Handler;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.util.DisplayMetrics;import android.view.View;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.TextView;import java.util.ArrayList;import java.util.List;import me.samlss.broccoli.Broccoli;import me.samlss.broccoli.PlaceholderParameter;import me.samlss.utils.ScreenUtils;import me.samlss.utils.WheelView;/** * 可参考 * https://blog.csdn.net/shenggaofei/article/details/78186177#comments_12759724 *  https://blog.csdn.net/Blog_Sun/article/details/95338124 * *  https://blog.csdn.net/hhw332704304/article/details/88971381 *  https://blog.csdn.net/u010731746/article/details/83303190 *  https://blog.csdn.net/qq_36347817/article/details/103529540?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase */public class WheelActivity extends AppCompatActivity {    private Broccoli mBroccoli;    private Handler mHandler = new Handler();    private WheelView mWheelView;    private TextView tvAge;    private PersonAgeAdapter mAgeAdapter;    private MyAdapter mAdapter;    private RecyclerView mRvAgeList,RvScroll;    private int age_num= 0;    private int mLastValue= 0;    private int START_NUM= 12;    private int END_NUM= 99;//    private int [] endX;    float endX = 0;    private View view_slip_front,view_slip_front2,view_slip_front3,view_slip_front4;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_wheel);        view_slip_front = findViewById(R.id.view_slip_front);        view_slip_front2 = findViewById(R.id.view_slip_front02);        view_slip_front3 = findViewById(R.id.view_slip_front03);        view_slip_front4 = findViewById(R.id.view_slip_front04);        mRvAgeList = findViewById(R.id.RvAgeList);        RvScroll = findViewById(R.id.RvScroll);        mWheelView = findViewById(R.id.rsv_ruler);        tvAge = findViewById(R.id.tv_age);        confitAgeWheelView();        initAgeList();//        initDatas();        initView();    }    /**     * 仿拼多多可水平滚动RecyclerView,自定义滚动条滚动距离     */    private void initView() {        LinearLayoutManager manager=new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);        mRvAgeList.setLayoutManager(manager);        mAdapter=new MyAdapter(this,START_NUM,22);        mRvAgeList.setAdapter(mAdapter);        // 这里的mRvHx是需要绑定滚动条的RecyclerView        mRvAgeList.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);            }            @Override            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);//                float endX;                // 整体的总宽度,注意是整体,包括在显示区域之外的。//                int range = mRvAgeList.computeHorizontalScrollRange();//                float density = getScreenDensity();//                // 计算出溢出部分的宽度,即屏幕外剩下的宽度//                float maxEndX = range - ScreenUtils.getScreenWidth(WheelActivity.this) + (25 * density) + 5;//                // 滑动的距离////                endX[0] = endX[0] + dx;////                // 计算比例////                float proportion = endX[0] / maxEndX;////                //滑动的距离//                endX += dx;//                //计算比例//                float proportion = endX / maxEndX;////                // 计算滚动条宽度//                int transMaxRange = ((ViewGroup) view_slip_front.getParent()).getWidth() - view_slip_front.getWidth();//                // 设置滚动条移动//                view_slip_front.setTranslationX(transMaxRange * proportion);                //整体的总宽度,注意是整体,包括在显示区域之外的。                int range = mRvAgeList.computeHorizontalScrollRange();                float density = getScreenDensity();                //计算出溢出部分的宽度,即屏幕外剩下的宽度                float maxEndX = range + (10 * density) + 5 - ScreenUtils.getScreenWidth(WheelActivity.this);                //滑动的距离                endX += dx;                //计算比例                float proportion = endX / maxEndX;                //计算滚动条宽度                int transMaxRange = ((ViewGroup) view_slip_front.getParent()).getWidth() - view_slip_front.getWidth();                //设置滚动条移动                view_slip_front.setTranslationX(transMaxRange * proportion);                //02                //计算滚动条宽度                int transMaxRange2 = ((ViewGroup) view_slip_front2.getParent()).getWidth() - view_slip_front2.getWidth();                //设置滚动条移动                view_slip_front2.setTranslationX(transMaxRange2 * proportion);                //03                //计算滚动条宽度                int transMaxRange3 = ((ViewGroup) view_slip_front3.getParent()).getWidth() - view_slip_front3.getWidth();                //设置滚动条移动                view_slip_front3.setTranslationX(transMaxRange3 * proportion);                //04                //计算滚动条宽度                int transMaxRange4 = ((ViewGroup) view_slip_front4.getParent()).getWidth() - view_slip_front4.getWidth();                //设置滚动条移动                view_slip_front4.setTranslationX(transMaxRange4 * proportion);            }        });    }    public float getScreenDensity() {        WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics dm = new DisplayMetrics();        if (wm != null) {            wm.getDefaultDisplay().getMetrics(dm);        }        int width = dm.widthPixels;// 屏幕宽度(像素)        int height = dm.heightPixels; // 屏幕高度(像素)        float density = dm.density;//屏幕密度(0.75 / 1.0 / 1.5)        int densityDpi = dm.densityDpi;//屏幕密度dpi(120 / 160 / 240)        return density;    }    /**     * Android WheelView横向选择器     */    private void confitAgeWheelView() {        ArrayList localArrayList = new ArrayList();        int i = 18;        while (i <= 60) {            StringBuilder localStringBuilder = new StringBuilder();            localStringBuilder.append(String.valueOf(i));            localStringBuilder.append("岁");            localArrayList.add(localStringBuilder.toString());            i += 1;        }        mWheelView.setItems(localArrayList);        mWheelView.selectIndex(0);//设置默认选择的年龄        tvAge.setText(mWheelView.getItems().get(0));//设置默认显示年龄//        mWheelView.selectIndex(6);        //监听        mWheelView.setOnWheelItemSelectedListener(new WheelView.OnWheelItemSelectedListener() {            @Override            public void onWheelItemChanged(WheelView wheelView, int position) {                List items = wheelView.getItems();                String num = items.get(position);                tvAge.setText(num+"");//根据改变的位置设置年龄            }            @Override            public void onWheelItemSelected(WheelView wheelView, int position) {                age_num = position + 18;//选中数字因为position是从0开始的,所以要加上你初始化起始的数字大小//                List items = wheelView.getItems();//                String num = items.get(position);//                String nums = items.get(position);//                tvAge.setText(num+"");            }        });    }    /**     * 初始化年龄滑动条     */    private void initAgeList() {        LinearLayoutManager mLayoutManager =                new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);        RvScroll.setLayoutManager(mLayoutManager);        mAgeAdapter = new PersonAgeAdapter(START_NUM, END_NUM,WheelActivity.this);        RvScroll.setAdapter(mAgeAdapter);        RvScroll.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);//                mBDownStep.setEnabled(false);                // 效果在暂停时显示, 否则会导致重绘异常                if (newState == RecyclerView.SCROLL_STATE_IDLE) {                    mAgeAdapter.highlightItem(getMiddlePosition());                    RvScroll.scrollToPosition(getScrollPosition());                    mLastValue = getMiddlePosition();//                    UserInfoManager.setAge(getMiddlePosition() + START_NUM);//                    mBDownStep.setEnabled(true); // 滑动时不可用, 停止时才可以                }            }            @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                // 值是实时增加                tvAge.setText(String.valueOf(getMiddlePosition() + START_NUM));            }        });        mAgeAdapter.highlightItem(getMiddlePosition());    }    /**     * 获取中间位置     *     * @return 当前值     */    private int getMiddlePosition() {        return getScrollPosition() + (PersonAgeAdapter.ITEM_NUM / 2);    }    /**     * 获取滑动值, 滑动偏移 / 每个格子宽度     *     * @return 当前值     */    private int getScrollPosition() {        return (int) ((double) RvScroll.computeHorizontalScrollOffset()                / (double) PersonAgeAdapter.getItemStdWidth());    }    /**     * 初始化数据     */    private void initDatas() {        LinearLayoutManager manager=new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false);        mRvAgeList.setLayoutManager(manager);        mAdapter=new MyAdapter(this,START_NUM,END_NUM);        mRvAgeList.setAdapter(mAdapter);        mRvAgeList.addOnScrollListener(new RecyclerView.OnScrollListener() {            @Override            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                if(newState==RecyclerView.SCROLL_STATE_IDLE){                    mAdapter.highlightItem(getMiddlePositions());                    //将位置移动到中间位置                    ((LinearLayoutManager)recyclerView.getLayoutManager()).scrollToPositionWithOffset(getScrollPositions(),0);                    System.out.println(getScrollPositions()+"");                }            }            @Override            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                tvAge.setText(String.valueOf(getMiddlePositions() + START_NUM));            }        });        mAdapter.highlightItem(getMiddlePositions());    }    /**     * 获取中间位置的position     * @return     */    private int getMiddlePositions() {        return getScrollPositions()+(mAdapter.ITEM_NUM/2);    }    /**     * 获取滑动值, 滑动偏移 / 每个格子宽度     *     * @return 当前值     */    private int getScrollPositions() {        return (int) (((double) mRvAgeList.computeHorizontalScrollOffset()                / (double) mAdapter.getItemWidth())+0.5f);    }}

2.布局:

<?xml version="1.0" encoding="utf-8"?>                                                                                                                       

3.shape绘制圆角背景、渐变色背景

 shape_bg_slip_behind.xml:

<?xml version="1.0" encoding="utf-8"?>        

shape_bg_slip_front.xml:

<?xml version="1.0" encoding="utf-8"?>        

shape_bg_slip_behind2.xml:

<?xml version="1.0" encoding="utf-8"?>        

 shape_bg_slip_front2.xml:

<?xml version="1.0" encoding="utf-8"?>        

 shape_bg_slip_front3.xml:

<?xml version="1.0" encoding="utf-8"?>            

shape_bg_slip_front4.xml: 

<?xml version="1.0" encoding="utf-8"?>            

 4.ScreenUtils获得屏幕相关的辅助类

package me.samlss.utils;import android.app.Activity;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Rect;import android.util.DisplayMetrics;import android.view.View;import android.view.WindowManager;//获得屏幕相关的辅助类public class ScreenUtils{    private ScreenUtils()    {        /* cannot be instantiated */        throw new UnsupportedOperationException("cannot be instantiated");    }    /**     * 获得屏幕高度     *     * @param context     * @return     */    public static int getScreenWidth(Context context)    {        WindowManager wm = (WindowManager) context                .getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        return outMetrics.widthPixels;    }    /**     * 获得屏幕宽度     *     * @param context     * @return     */    public static int getScreenHeight(Context context)    {        WindowManager wm = (WindowManager) context                .getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics outMetrics = new DisplayMetrics();        wm.getDefaultDisplay().getMetrics(outMetrics);        return outMetrics.heightPixels;    }    /**     * 获得状态栏的高度     *     * @param context     * @return     */    public static int getStatusHeight(Context context)    {        int statusHeight = -1;        try        {            Class<?> clazz = Class.forName("com.android.internal.R$dimen");            Object object = clazz.newInstance();            int height = Integer.parseInt(clazz.getField("status_bar_height")                    .get(object).toString());            statusHeight = context.getResources().getDimensionPixelSize(height);        } catch (Exception e)        {            e.printStackTrace();        }        return statusHeight;    }    /**     * 获取当前屏幕截图,包含状态栏     *     * @param activity     * @return     */    public static Bitmap snapShotWithStatusBar(Activity activity)    {        View view = activity.getWindow().getDecorView();        view.setDrawingCacheEnabled(true);        view.buildDrawingCache();        Bitmap bmp = view.getDrawingCache();        int width = getScreenWidth(activity);        int height = getScreenHeight(activity);        Bitmap bp = null;        bp = Bitmap.createBitmap(bmp, 0, 0, width, height);        view.destroyDrawingCache();        return bp;    }    /**     * 获取当前屏幕截图,不包含状态栏     *     * @param activity     * @return     */    public static Bitmap snapShotWithoutStatusBar(Activity activity)    {        View view = activity.getWindow().getDecorView();        view.setDrawingCacheEnabled(true);        view.buildDrawingCache();        Bitmap bmp = view.getDrawingCache();        Rect frame = new Rect();        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);        int statusBarHeight = frame.top;        int width = getScreenWidth(activity);        int height = getScreenHeight(activity);        Bitmap bp = null;        bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height                - statusBarHeight);        view.destroyDrawingCache();        return bp;    }}

5.自定义类:(以下是Android RecyclerView 实现横向滚动效果) 

Android RecyclerView 实现横向滚动效果

package me.samlss.utils;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Path;import android.graphics.Rect;import android.graphics.RectF;import android.os.Parcel;import android.os.Parcelable;import android.support.v4.view.GestureDetectorCompat;import android.support.v4.view.ViewCompat;import android.text.TextPaint;import android.text.TextUtils;import android.util.AttributeSet;import android.view.GestureDetector;import android.view.MotionEvent;import android.view.SoundEffectConstants;import android.view.View;import android.widget.OverScroller;import java.util.ArrayList;import java.util.List;import me.samlss.broccoli_demo.R;/** *  */public class WheelView extends View implements GestureDetector.OnGestureListener {    public static final float DEFAULT_INTERVAL_FACTOR = 1.2f;    public static final float DEFAULT_MARK_RATIO = 0.7f;    private Paint mMarkPaint;    private TextPaint mMarkTextPaint;    private int mCenterIndex = -1;    private int mHighlightColor, mMarkTextColor;    private int mMarkColor, mFadeMarkColor;    private int mHeight;    private List mItems;    private String mAdditionCenterMark;    private OnWheelItemSelectedListener mOnWheelItemSelectedListener;    private float mIntervalFactor = DEFAULT_INTERVAL_FACTOR;    private float mMarkRatio = DEFAULT_MARK_RATIO;    private int mMarkCount;    private float mAdditionCenterMarkWidth;    private Path mCenterIndicatorPath = new Path();    private float mCursorSize;    private int mViewScopeSize;    // scroll control args ---- start    private OverScroller mScroller;    private float mMaxOverScrollDistance;    private RectF mContentRectF;    private boolean mFling = false;    private float mCenterTextSize, mNormalTextSize;    private float mTopSpace, mBottomSpace;    private float mIntervalDis;    private float mCenterMarkWidth, mMarkWidth;    private GestureDetectorCompat mGestureDetectorCompat;    // scroll control args ---- end    private int mLastSelectedIndex = -1;    private int mMinSelectableIndex = Integer.MIN_VALUE;    private int mMaxSelectableIndex = Integer.MAX_VALUE;    public WheelView(Context context) {        super(context);        init(null);    }    public WheelView(Context context, AttributeSet attrs) {        super(context, attrs);        init(attrs);    }    public WheelView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(attrs);    }    protected void init(AttributeSet attrs) {        float density = getResources().getDisplayMetrics().density;        mCenterMarkWidth = (int) (density * 1.5f + 0.5f);        mMarkWidth = density;        mHighlightColor = 0xFFF74C39;        mMarkTextColor = 0xFF666666;        mMarkColor = 0xFFEEEEEE;        mCursorSize = density * 18;        mCenterTextSize = density * 22;        mNormalTextSize = density * 18;        mBottomSpace = density * 6;        TypedArray ta = attrs == null ? null : getContext().obtainStyledAttributes(attrs, R.styleable.lwvWheelView);        if (ta != null) {            mHighlightColor = ta.getColor(R.styleable.lwvWheelView_lwvHighlightColor, mHighlightColor);            mMarkTextColor = ta.getColor(R.styleable.lwvWheelView_lwvMarkTextColor, mMarkTextColor);            mMarkColor = ta.getColor(R.styleable.lwvWheelView_lwvMarkColor, mMarkColor);            mIntervalFactor = ta.getFloat(R.styleable.lwvWheelView_lwvIntervalFactor, mIntervalFactor);            mMarkRatio = ta.getFloat(R.styleable.lwvWheelView_lwvMarkRatio, mMarkRatio);            mAdditionCenterMark = ta.getString(R.styleable.lwvWheelView_lwvAdditionalCenterMark);            mCenterTextSize = ta.getDimension(R.styleable.lwvWheelView_lwvCenterMarkTextSize, mCenterTextSize);            mNormalTextSize = ta.getDimension(R.styleable.lwvWheelView_lwvMarkTextSize, mNormalTextSize);            mCursorSize = ta.getDimension(R.styleable.lwvWheelView_lwvCursorSize, mCursorSize);        }        mFadeMarkColor = mHighlightColor & 0xAAFFFFFF;        mIntervalFactor = Math.max(1, mIntervalFactor);        mMarkRatio = Math.min(1, mMarkRatio);        mTopSpace = mCursorSize + density * 2;        mMarkPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mMarkTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);        mMarkTextPaint.setTextAlign(Paint.Align.CENTER);        mMarkTextPaint.setColor(mHighlightColor);        mMarkPaint.setColor(mMarkColor);        mMarkPaint.setStrokeWidth(mCenterMarkWidth);        mMarkTextPaint.setTextSize(mCenterTextSize);        calcIntervalDis();        mScroller = new OverScroller(getContext());        mContentRectF = new RectF();        mGestureDetectorCompat = new GestureDetectorCompat(getContext(), this);        selectIndex(0);    }    /**     * calculate interval distance between items     */    private void calcIntervalDis() {        if (mMarkTextPaint == null) {            return;        }        String defaultText = "888888";        Rect temp = new Rect();        int max = 0;        if (mItems != null && mItems.size() > 0) {            for (String i : mItems) {                mMarkTextPaint.getTextBounds(i, 0, i.length(), temp);                if (temp.width() > max) {                    max = temp.width();                }            }        } else {            mMarkTextPaint.getTextBounds(defaultText, 0, defaultText.length(), temp);            max = temp.width();        }        if (!TextUtils.isEmpty(mAdditionCenterMark)) {            mMarkTextPaint.setTextSize(mNormalTextSize);            mMarkTextPaint.getTextBounds(mAdditionCenterMark, 0, mAdditionCenterMark.length(), temp);            mAdditionCenterMarkWidth = temp.width();            max += temp.width();        }        mIntervalDis = max * mIntervalFactor;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));    }    private int measureWidth(int widthMeasureSpec) {        int measureMode = MeasureSpec.getMode(widthMeasureSpec);        int measureSize = MeasureSpec.getSize(widthMeasureSpec);        int result = getSuggestedMinimumWidth();        switch (measureMode) {            case MeasureSpec.AT_MOST:            case MeasureSpec.EXACTLY:                result = measureSize;                break;            default:                break;        }        return result;    }    private int measureHeight(int heightMeasure) {        int measureMode = MeasureSpec.getMode(heightMeasure);        int measureSize = MeasureSpec.getSize(heightMeasure);        int result = (int) (mBottomSpace + mTopSpace * 2 + mCenterTextSize);        switch (measureMode) {            case MeasureSpec.EXACTLY:                result = Math.max(result, measureSize);                break;            case MeasureSpec.AT_MOST:                result = Math.min(result, measureSize);                break;            default:                break;        }        return result;    }    public void fling(int velocityX, int velocityY) {        mScroller.fling(getScrollX(), getScrollY(),                velocityX, velocityY,                (int) (-mMaxOverScrollDistance + mMinSelectableIndex * mIntervalDis), (int) (mContentRectF.width() - mMaxOverScrollDistance - (mMarkCount - 1 - mMaxSelectableIndex) * mIntervalDis),                0, 0,                (int) mMaxOverScrollDistance, 0);        ViewCompat.postInvalidateOnAnimation(this);    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        if (w != oldw || h != oldh) {            mHeight = h;            mMaxOverScrollDistance = w / 2.f;            mContentRectF.set(0, 0, (mMarkCount - 1) * mIntervalDis, h);            mViewScopeSize = (int) Math.ceil(mMaxOverScrollDistance / mIntervalDis);        }    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        mCenterIndicatorPath.reset();        float sizeDiv2 = mCursorSize / 2f;        float sizeDiv3 = mCursorSize / 3f;        mCenterIndicatorPath.moveTo(mMaxOverScrollDistance - sizeDiv2 + getScrollX(), 0);        mCenterIndicatorPath.rLineTo(0, sizeDiv3);        mCenterIndicatorPath.rLineTo(sizeDiv2, sizeDiv2);        mCenterIndicatorPath.rLineTo(sizeDiv2, -sizeDiv2);        mCenterIndicatorPath.rLineTo(0, -sizeDiv3);        mCenterIndicatorPath.close();        mMarkPaint.setColor(mHighlightColor);        canvas.drawPath(mCenterIndicatorPath, mMarkPaint);        int start = mCenterIndex - mViewScopeSize;        int end = mCenterIndex + mViewScopeSize + 1;        start = Math.max(start, -mViewScopeSize * 2);        end = Math.min(end, mMarkCount + mViewScopeSize * 2);        // extends both ends        if (mCenterIndex == mMaxSelectableIndex) {            end += mViewScopeSize;        } else if (mCenterIndex == mMinSelectableIndex) {            start -= mViewScopeSize;        }        float x = start * mIntervalDis;        float markHeight = mHeight - mBottomSpace - mCenterTextSize - mTopSpace;        // small scale Y offset        float smallMarkShrinkY = markHeight * (1 - mMarkRatio) / 2f;        smallMarkShrinkY = Math.min((markHeight - mMarkWidth) / 2f, smallMarkShrinkY);        for (int i = start; i < end; i++) {            float tempDis = mIntervalDis / 5f;            // offset: Small mark offset Big mark            for (int offset = -2; offset < 3; offset++) {                float ox = x + offset * tempDis;                if (i >= 0 && i <= mMarkCount && mCenterIndex == i) {                    int tempOffset = Math.abs(offset);                    if (tempOffset == 0) {                        mMarkPaint.setColor(mHighlightColor);                    } else if (tempOffset == 1) {                        mMarkPaint.setColor(mFadeMarkColor);                    } else {                        mMarkPaint.setColor(mMarkColor);                    }                } else {                    mMarkPaint.setColor(mMarkColor);                }                if (offset == 0) {                    // center mark                    mMarkPaint.setStrokeWidth(mCenterMarkWidth);                    canvas.drawLine(ox, mTopSpace, ox, mTopSpace + markHeight, mMarkPaint);                } else {                    // other small mark                    mMarkPaint.setStrokeWidth(mMarkWidth);                    canvas.drawLine(ox, mTopSpace + smallMarkShrinkY, ox, mTopSpace + markHeight - smallMarkShrinkY, mMarkPaint);                }            }            // mark text            if (mMarkCount > 0 && i >= 0 && i < mMarkCount) {                CharSequence temp = mItems.get(i);                if (mCenterIndex == i) {                    mMarkTextPaint.setColor(mHighlightColor);                    mMarkTextPaint.setTextSize(mCenterTextSize);                    if (!TextUtils.isEmpty(mAdditionCenterMark)) {                        float off = mAdditionCenterMarkWidth / 2f;                        float tsize = mMarkTextPaint.measureText(temp, 0, temp.length());                        canvas.drawText(temp, 0, temp.length(), x - off, mHeight - mBottomSpace, mMarkTextPaint);                        mMarkTextPaint.setTextSize(mNormalTextSize);                        canvas.drawText(mAdditionCenterMark, x + tsize / 2f, mHeight - mBottomSpace, mMarkTextPaint);                    } else {                        canvas.drawText(temp, 0, temp.length(), x, mHeight - mBottomSpace, mMarkTextPaint);                    }                } else {                    mMarkTextPaint.setColor(mMarkTextColor);                    mMarkTextPaint.setTextSize(mNormalTextSize);                    canvas.drawText(temp, 0, temp.length(), x, mHeight - mBottomSpace, mMarkTextPaint);                }            }            x += mIntervalDis;        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (mItems == null || mItems.size() == 0 || !isEnabled()) {            return false;        }        boolean ret = mGestureDetectorCompat.onTouchEvent(event);        if (!mFling && MotionEvent.ACTION_UP == event.getAction()) {            autoSettle();            ret = true;        }        return ret || super.onTouchEvent(event);    }    @Override    public void computeScroll() {        super.computeScroll();        if (mScroller.computeScrollOffset()) {            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());            refreshCenter();            invalidate();        } else {            if (mFling) {                mFling = false;                autoSettle();            }        }    }    public void setAdditionCenterMark(String additionCenterMark) {        mAdditionCenterMark = additionCenterMark;        calcIntervalDis();        invalidate();    }    private void autoSettle() {        int sx = getScrollX();        float dx = mCenterIndex * mIntervalDis - sx - mMaxOverScrollDistance;        mScroller.startScroll(sx, 0, (int) dx, 0);        postInvalidate();        if (mLastSelectedIndex != mCenterIndex) {            mLastSelectedIndex = mCenterIndex;            if (null != mOnWheelItemSelectedListener) {                mOnWheelItemSelectedListener.onWheelItemSelected(this, mCenterIndex);            }        }    }    /**     * limit center index in bounds.     *     * @param center     * @return     */    private int safeCenter(int center) {        if (center < mMinSelectableIndex) {            center = mMinSelectableIndex;        } else if (center > mMaxSelectableIndex) {            center = mMaxSelectableIndex;        }        return center;    }    private void refreshCenter(int offsetX) {        int offset = (int) (offsetX + mMaxOverScrollDistance);        int tempIndex = Math.round(offset / mIntervalDis);        tempIndex = safeCenter(tempIndex);        if (mCenterIndex == tempIndex) {            return;        }        mCenterIndex = tempIndex;        if (null != mOnWheelItemSelectedListener) {            mOnWheelItemSelectedListener.onWheelItemChanged(this, mCenterIndex);        }    }    private void refreshCenter() {        refreshCenter(getScrollX());    }    public void selectIndex(int index) {        mCenterIndex = index;        post(new Runnable() {            @Override            public void run() {                scrollTo((int) (mCenterIndex * mIntervalDis - mMaxOverScrollDistance), 0);                invalidate();                refreshCenter();            }        });    }    public void smoothSelectIndex(int index) {        if (!mScroller.isFinished()) {            mScroller.abortAnimation();        }        int deltaIndex = index - mCenterIndex;        mScroller.startScroll(getScrollX(), 0, (int) (deltaIndex * mIntervalDis), 0);        invalidate();    }    public int getMinSelectableIndex() {        return mMinSelectableIndex;    }    public void setMinSelectableIndex(int minSelectableIndex) {        if (minSelectableIndex > mMaxSelectableIndex) {            minSelectableIndex = mMaxSelectableIndex;        }        mMinSelectableIndex = minSelectableIndex;        int afterCenter = safeCenter(mCenterIndex);        if (afterCenter != mCenterIndex) {            selectIndex(afterCenter);        }    }    public int getMaxSelectableIndex() {        return mMaxSelectableIndex;    }    public void setMaxSelectableIndex(int maxSelectableIndex) {        if (maxSelectableIndex < mMinSelectableIndex) {            maxSelectableIndex = mMinSelectableIndex;        }        mMaxSelectableIndex = maxSelectableIndex;        int afterCenter = safeCenter(mCenterIndex);        if (afterCenter != mCenterIndex) {            selectIndex(afterCenter);        }    }    public List getItems() {        return mItems;    }    public void setItems(List items) {        if (mItems == null) {            mItems = new ArrayList<>();        } else {            mItems.clear();        }        mItems.addAll(items);        mMarkCount = null == mItems ? 0 : mItems.size();        if (mMarkCount > 0) {            mMinSelectableIndex = Math.max(mMinSelectableIndex, 0);            mMaxSelectableIndex = Math.min(mMaxSelectableIndex, mMarkCount - 1);        }        mContentRectF.set(0, 0, (mMarkCount - 1) * mIntervalDis, getMeasuredHeight());        mCenterIndex = Math.min(mCenterIndex, mMarkCount);        calcIntervalDis();        invalidate();    }    public int getSelectedPosition() {        return mCenterIndex;    }    public void setOnWheelItemSelectedListener(OnWheelItemSelectedListener onWheelItemSelectedListener) {        mOnWheelItemSelectedListener = onWheelItemSelectedListener;    }    @Override    public boolean onDown(MotionEvent e) {        if (!mScroller.isFinished()) {            mScroller.forceFinished(false);        }        mFling = false;        if (null != getParent()) {            getParent().requestDisallowInterceptTouchEvent(true);        }        return true;    }    @Override    public void onShowPress(MotionEvent e) {    }    @Override    public boolean onSingleTapUp(MotionEvent e) {        playSoundEffect(SoundEffectConstants.CLICK);        refreshCenter((int) (getScrollX() + e.getX() - mMaxOverScrollDistance));        autoSettle();        return true;    }    @Override    public void onLongPress(MotionEvent e) {    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        float dis = distanceX;        float scrollX = getScrollX();        if (scrollX < mMinSelectableIndex * mIntervalDis - 2 * mMaxOverScrollDistance) {            dis = 0;        } else if (scrollX < mMinSelectableIndex * mIntervalDis - mMaxOverScrollDistance) {            dis = distanceX / 4.f;        } else if (scrollX > mContentRectF.width() - (mMarkCount - mMaxSelectableIndex - 1) * mIntervalDis) {            dis = 0;        } else if (scrollX > mContentRectF.width() - (mMarkCount - mMaxSelectableIndex - 1) * mIntervalDis - mMaxOverScrollDistance) {            dis = distanceX / 4.f;        }        scrollBy((int) dis, 0);        refreshCenter();        return true;    }    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        float scrollX = getScrollX();        if (scrollX < -mMaxOverScrollDistance + mMinSelectableIndex * mIntervalDis || scrollX > mContentRectF.width() - mMaxOverScrollDistance - (mMarkCount - 1 - mMaxSelectableIndex) * mIntervalDis) {            return false;        } else {            mFling = true;            fling((int) -velocityX, 0);            return true;        }    }    @Override    public Parcelable onSaveInstanceState() {        Parcelable superState = super.onSaveInstanceState();        SavedState ss = new SavedState(superState);        ss.index = getSelectedPosition();        ss.min = mMinSelectableIndex;        ss.max = mMaxSelectableIndex;        return ss;    }    @Override    public void onRestoreInstanceState(Parcelable state) {        SavedState ss = (SavedState) state;        super.onRestoreInstanceState(ss.getSuperState());        mMinSelectableIndex = ss.min;        mMaxSelectableIndex = ss.max;        selectIndex(ss.index);        requestLayout();    }    public interface OnWheelItemSelectedListener {        void onWheelItemChanged(WheelView wheelView, int position);        void onWheelItemSelected(WheelView wheelView, int position);    }    static class SavedState extends BaseSavedState {        public static final Creator CREATOR                = new Creator() {            public SavedState createFromParcel(Parcel in) {                return new SavedState(in);            }            public SavedState[] newArray(int size) {                return new SavedState[size];            }        };        int index;        int min;        int max;        SavedState(Parcelable superState) {            super(superState);        }        private SavedState(Parcel in) {            super(in);            index = in.readInt();            min = in.readInt();            max = in.readInt();        }        @Override        public void writeToParcel(Parcel out, int flags) {            super.writeToParcel(out, flags);            out.writeInt(index);            out.writeInt(min);            out.writeInt(max);        }        @Override        public String toString() {            return "WheelView.SavedState{"                    + Integer.toHexString(System.identityHashCode(this))                    + " index=" + index + " min=" + min + " max=" + max + "}";        }    }}

6.attrs.xml:

<?xml version="1.0" encoding="utf-8"?>                                                                                

7.颜色:

<?xml version="1.0" encoding="utf-8"?>    #333333    #666666    #D81B60    #333    #888

 

更多相关文章

  1. 直播源码Android(安卓)屏幕常亮N秒后自动暗屏
  2. Android(安卓)横竖屏切换小结
  3. Webview setLayoutAlgorithm
  4. android AlertDialog 捕获返回键
  5. Android(安卓)自定义FloatView实现悬浮视图
  6. android listview滑动设置浮标半透明效果
  7. AndEngine 分析之八------Texture
  8. android PowerManager wakelock
  9. Android(安卓)通过FontPaint计算字符宽

随机推荐

  1. 彻底了解RxJava(一)基础知识
  2. Android - 从@drawable String打开资源
  3. 同时兼容高低版本的setBackground跟setTe
  4. Android逆向实例笔记—那些搜不到的中文
  5. Android学习笔记(一):基本概念
  6. Android基础 - 对话框和浮动Activity
  7. 安装使用Android-x86打造快速流畅的Aandr
  8. 赵雅智_setImageResource和setImageBitma
  9. 疯狂android讲义(第三版)总结之 2.11 使用
  10. Android界面的.9.png图片显示出错,怎么回