失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Android WheelView横向选择器

Android WheelView横向选择器

时间:2020-02-21 04:41:13

相关推荐

Android WheelView横向选择器

原文如下:

/Blog_Sun/article/details/95338124

最近项目让做了一个注册流程是选择年龄的,规定是手动横幅型的选择器,咱也不敢说咱也不敢怼毕竟我也是个小白,让做就做吧,顺便让他给了个模仿对象的apk

效果如下:

怎么办呢,最后反编译了那个apk,从里面找到了这个控件发现他也是引用的一个别人的依赖话不多说依赖先放这里:

dependencies {

compile 'com.lantouzi.wheelview:library:1.1.2'

}

然后这个大佬的 github 我也放这里,能用到这个控件的朋友可以看一下:

说一下如果大家不想用依赖的话,也是可以的

接下来是我将依赖中的代码提取出来的代码:

WheelView.java

package com.mon;

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.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 androidx.core.view.GestureDetectorCompat;

import androidx.core.view.ViewCompat;

import com.online.myceshidemo.R;

import java.util.ArrayList;

import java.util.List;

/**

* Created by kyle on 15/11/9.

*/

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<String> 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() {

puteScroll();

if (puteScrollOffset()) {

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<String> getItems() {

return mItems;

}

public void setItems(List<String> 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<SavedState> CREATOR

= new Creator<SavedState>() {

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 + "}";

}

}

}

这个是主要类的代码,这样还是不够的,我们看一下布局中的引用:

<com.mon.WheelView

android:id="@+id/rsv_ruler"

android:layout_width="match_parent"

android:layout_height="66dp"

android:layout_marginLeft="20dp"

android:layout_marginTop="50dp"

android:layout_marginRight="20dp"

android:scrollbarFadeDuration="1"

app:layout_constraintTop_toBottomOf="@id/iv_sex_man"

app:lwvCenterMarkTextSize="18sp"

app:lwvCursorSize="10dp"

app:lwvMarkTextSize="15sp" />

里面还有许多的属性: res-->values--> 创建attrs.xml文件

<resources>

<declare-styleable name="lwvWheelView">

<attr name="lwvHighlightColor" format="color|reference"/>

<attr name="lwvMarkColor" format="color|reference"/>

<attr name="lwvMarkTextColor" format="color|reference"/>

<attr name="lwvIntervalFactor" format="float"/>

<attr name="lwvMarkRatio" format="float"/>

<attr name="lwvCursorSize" format="dimension"/>

<attr name="lwvMarkTextSize" format="dimension"/>

<attr name="lwvCenterMarkTextSize" format="dimension"/>

<attr name="lwvAdditionalCenterMark" format="string|reference"/>

</declare-styleable>

</resources>

在Activity里面咱们调用方法:

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(6);

mWheelView.setOnWheelItemSelectedListener(new WheelView.OnWheelItemSelectedListener() {

@Override

public void onWheelItemChanged(WheelView wheelView, int position) {

}

@Override

public void onWheelItemSelected(WheelView wheelView, int position) {

age_num = position + 18;//选中数字因为position是从0开始的,所以要加上你初始化起始的数字大小

}

});

}

差不多到这里就完成了,有问题请留言,谢谢

————————————————

版权声明:本文为CSDN博主「你好世界丶」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:/Blog_Sun/article/details/95338124

如果觉得《Android WheelView横向选择器》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。