您好,登錄后才能下訂單哦!
本文實(shí)例為大家分享了Android實(shí)現(xiàn)滑動(dòng)標(biāo)尺選擇值,效果圖
1.自定義屬性attrs.xml
<declare-styleable name="RulerView"> <attr name="textColor" format="color" /> <attr name="textSize" format="dimension" /> <attr name="lineColor" format="color" /> <attr name="lineSpaceWidth" format="dimension" /> <attr name="lineWidth" format="dimension" /> <attr name="lineMaxHeight" format="dimension" /> <attr name="lineMidHeight" format="dimension" /> <attr name="lineMinHeight" format="dimension" /> <attr name="textMarginTop" format="dimension" /> <attr name="alphaEnable" format="boolean" /> <attr name="minValue" format="float"/> <attr name="maxValue" format="float"/> <attr name="selectorValue" format="float"/> <attr name="perValue" format="float"/> </declare-styleable>
2.自定義RulerView
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.widget.Scroller; public class RulerView extends View { private int mMinVelocity; private Scroller mScroller; //Scroller是一個(gè)專(zhuān)門(mén)用于處理滾動(dòng)效果的工具類(lèi) 用mScroller記錄/計(jì)算View滾動(dòng)的位置,再重寫(xiě)View的computeScroll(),完成實(shí)際的滾動(dòng) private VelocityTracker mVelocityTracker; //主要用跟蹤觸摸屏事件(flinging事件和其他gestures手勢(shì)事件)的速率。 private int mWidth; private int mHeight; private float mSelectorValue = 50.0f; // 未選擇時(shí) 默認(rèn)的值 滑動(dòng)后表示當(dāng)前中間指針正在指著的值 private float mMaxValue = 200; // 最大數(shù)值 private float mMinValue = 100.0f; //最小的數(shù)值 private float mPerValue = 1; //最小單位 如 1:表示 每2條刻度差為1. 0.1:表示 每2條刻度差為0.1 // 在demo中 身高mPerValue為1 體重mPerValue 為0.1 private float mLineSpaceWidth = 5; // 尺子刻度2條線(xiàn)之間的距離 private float mLineWidth = 4; // 尺子刻度的寬度 private float mLineMaxHeight = 420; // 尺子刻度分為3中不同的高度。 mLineMaxHeight表示最長(zhǎng)的那根(也就是 10的倍數(shù)時(shí)的高度) private float mLineMidHeight = 30; // mLineMidHeight 表示中間的高度(也就是 5 15 25 等時(shí)的高度) private float mLineMinHeight = 17; // mLineMinHeight 表示最短的那個(gè)高度(也就是 1 2 3 4 等時(shí)的高度) private float mTextMarginTop = 10; //o private float mTextSize = 30; //尺子刻度下方數(shù)字 textsize private boolean mAlphaEnable = false; // 尺子 最左邊 最后邊是否需要透明 (透明效果更好點(diǎn)) private float mTextHeight; //尺子刻度下方數(shù)字 的高度 private Paint mTextPaint; // 尺子刻度下方數(shù)字( 也就是每隔10個(gè)出現(xiàn)的數(shù)值) paint private Paint mLinePaint; // 尺子刻度 paint private int mTotalLine; //共有多少條 刻度 private int mMaxOffset; //所有刻度 共有多長(zhǎng) private float mOffset; // 默認(rèn)狀態(tài)下,mSelectorValue所在的位置 位于尺子總刻度的位置 private int mLastX, mMove; private OnValueChangeListener mListener; // 滑動(dòng)后數(shù)值回調(diào) private int mLineColor = Color.GRAY; //刻度的顏色 private int mTextColor = Color.BLACK; //文字的顏色 public RulerView(Context context) { this(context, null); } public RulerView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public RulerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context, attrs); } protected void init(Context context, AttributeSet attrs) { mScroller = new Scroller(context); this.mLineSpaceWidth = myfloat(25.0F); this.mLineWidth = myfloat(2.0F); this.mLineMaxHeight = myfloat(100.0F); this.mLineMidHeight = myfloat(60.0F); this.mLineMinHeight = myfloat(40.0F); this.mTextHeight = myfloat(40.0F); final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RulerView); mAlphaEnable = typedArray.getBoolean(R.styleable.RulerView_alphaEnable, mAlphaEnable); mLineSpaceWidth = typedArray.getDimension(R.styleable.RulerView_lineSpaceWidth, mLineSpaceWidth); mLineWidth = typedArray.getDimension(R.styleable.RulerView_lineWidth, mLineWidth); mLineMaxHeight = typedArray.getDimension(R.styleable.RulerView_lineMaxHeight, mLineMaxHeight); mLineMidHeight = typedArray.getDimension(R.styleable.RulerView_lineMidHeight, mLineMidHeight); mLineMinHeight = typedArray.getDimension(R.styleable.RulerView_lineMinHeight, mLineMinHeight); mLineColor = typedArray.getColor(R.styleable.RulerView_lineColor, mLineColor); mTextSize = typedArray.getDimension(R.styleable.RulerView_textSize, mTextSize); mTextColor = typedArray.getColor(R.styleable.RulerView_textColor, mTextColor); mTextMarginTop = typedArray.getDimension(R.styleable.RulerView_textMarginTop, mTextMarginTop); mSelectorValue = typedArray.getFloat(R.styleable.RulerView_selectorValue, 0.0f); mMinValue = typedArray.getFloat(R.styleable.RulerView_minValue, 0.0f); mMaxValue = typedArray.getFloat(R.styleable.RulerView_maxValue, 100.0f); mPerValue = typedArray.getFloat(R.styleable.RulerView_perValue, 0.1f); mMinVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity(); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setTextSize(mTextSize); mTextPaint.setColor(mTextColor); mTextHeight = getFontHeight(mTextPaint); mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLinePaint.setStrokeWidth(mLineWidth); mLinePaint.setColor(mLineColor); // setValue(1990, 1940, 2016, 1); } public static int myfloat(float paramFloat) { return (int) (0.5F + paramFloat * 1.0f); } private float getFontHeight(Paint paint) { Paint.FontMetrics fm = paint.getFontMetrics(); return fm.descent - fm.ascent; } /** * @param selectorValue 未選擇時(shí) 默認(rèn)的值 滑動(dòng)后表示當(dāng)前中間指針正在指著的值 * @param minValue 最大數(shù)值 * @param maxValue 最小的數(shù)值 * @param per 最小單位 如 1:表示 每2條刻度差為1. 0.1:表示 每2條刻度差為0.1 在demo中 身高mPerValue為1 體重mPerValue 為0.1 */ public void setValue(float selectorValue, float minValue, float maxValue, float per) { this.mSelectorValue = selectorValue; this.mMaxValue = maxValue; this.mMinValue = minValue; this.mPerValue = (int) (per * 10.0f); this.mTotalLine = ((int) ((mMaxValue * 10 - mMinValue * 10) / mPerValue)) + 1; mMaxOffset = (int) (-(mTotalLine - 1) * mLineSpaceWidth); mOffset = (mMinValue - mSelectorValue) / mPerValue * mLineSpaceWidth * 10; invalidate(); setVisibility(VISIBLE); } public void setOnValueChangeListener(OnValueChangeListener listener) { mListener = listener; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (w > 0 && h > 0) { mWidth = w; mHeight = h; } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float left, height; String value; int alpha = 0; float scale; int srcPointX = mWidth / 2; for (int i = 0; i < mTotalLine; i++) { left = srcPointX + mOffset + i * mLineSpaceWidth; if (left < 0 || left > mWidth) { continue; // 先畫(huà)默認(rèn)值在正中間,左右各一半的view。 多余部分暫時(shí)不畫(huà)(也就是從默認(rèn)值在中間,畫(huà)旁邊左右的刻度線(xiàn)) } /*文字*/ if (i % 10 == 0) { value = String.valueOf((int) (mMinValue + i * mPerValue / 10)); if (mAlphaEnable) { mTextPaint.setAlpha(alpha); } canvas.drawText(value, left - mTextPaint.measureText(value) / 2, mTextHeight, mTextPaint); // 在為整數(shù)時(shí),畫(huà) 數(shù)值 } /*線(xiàn)條*/ if (i % 10 == 0) { height = mLineMinHeight; } else if (i % 5 == 0) { height = mLineMidHeight; } else { height = mLineMaxHeight; } if (mAlphaEnable) { scale = 1 - Math.abs(left - srcPointX) / srcPointX; alpha = (int) (255 * scale * scale); mLinePaint.setAlpha(alpha); } canvas.drawLine(left, mLineMaxHeight + mTextMarginTop + mTextHeight, left, height, mLinePaint); } } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); int xPosition = (int) event.getX(); if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); switch (action) { case MotionEvent.ACTION_DOWN: mScroller.forceFinished(true); mLastX = xPosition; mMove = 0; break; case MotionEvent.ACTION_MOVE: mMove = (mLastX - xPosition); changeMoveAndValue(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: countMoveEnd(); countVelocityTracker(); return false; default: break; } mLastX = xPosition; return true; } private void countVelocityTracker() { mVelocityTracker.computeCurrentVelocity(1000); //初始化速率的單位 float xVelocity = mVelocityTracker.getXVelocity(); //當(dāng)前的速度 if (Math.abs(xVelocity) > mMinVelocity) { mScroller.fling(0, 0, (int) xVelocity, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); } } /** * 滑動(dòng)結(jié)束后,若是指針在2條刻度之間時(shí),改變mOffset 讓指針正好在刻度上。 */ private void countMoveEnd() { mOffset -= mMove; if (mOffset <= mMaxOffset) { mOffset = mMaxOffset; } else if (mOffset >= 0) { mOffset = 0; } mLastX = 0; mMove = 0; mSelectorValue = mMinValue + Math.round(Math.abs(mOffset) * 1.0f / mLineSpaceWidth) * mPerValue / 10.0f; mOffset = (mMinValue - mSelectorValue) * 10.0f / mPerValue * mLineSpaceWidth; notifyValueChange(); postInvalidate(); } /** * 滑動(dòng)后的操作 */ private void changeMoveAndValue() { mOffset -= mMove; if (mOffset <= mMaxOffset) { mOffset = mMaxOffset; mMove = 0; mScroller.forceFinished(true); } else if (mOffset >= 0) { mOffset = 0; mMove = 0; mScroller.forceFinished(true); } mSelectorValue = mMinValue + Math.round(Math.abs(mOffset) * 1.0f / mLineSpaceWidth) * mPerValue / 10.0f; notifyValueChange(); postInvalidate(); } private void notifyValueChange() { if (null != mListener) { mListener.onValueChange(mSelectorValue); } } /** * 滑動(dòng)后的回調(diào) */ public interface OnValueChangeListener { void onValueChange(float value); } @Override public void computeScroll() { super.computeScroll(); if (mScroller.computeScrollOffset()) { //mScroller.computeScrollOffset()返回 true表示滑動(dòng)還沒(méi)有結(jié)束 if (mScroller.getCurrX() == mScroller.getFinalX()) { countMoveEnd(); } else { int xPosition = mScroller.getCurrX(); mMove = (mLastX - xPosition); changeMoveAndValue(); mLastX = xPosition; } } } }
3.xml中使用activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center_horizontal" android:orientation="vertical" android:visibility="visible"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:maxHeight="17.0sp" android:text="身高(cm)" android:textColor="#cc222222" android:textSize="15.0sp" /> <TextView android:id="@+id/tv_info_height_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="11.0dip" android:includeFontPadding="false" android:maxHeight="24.0sp" android:textColor="#cc222222" android:textSize="24.0sp" /> <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content"> <com.demo.ruleview.RulerView android:id="@+id/ruler_height" android:layout_width="fill_parent" android:layout_height="68.0dip" android:layout_marginTop="24.0dip" app:alphaEnable="true" app:lineColor="@color/gray" app:lineMaxHeight="40dp" app:lineMidHeight="30dp" app:lineMinHeight="20dp" app:lineSpaceWidth="10dp" app:lineWidth="2dip" app:maxValue="250.0" app:minValue="80.0" app:perValue="1" app:textColor="@color/black" /> <ImageView android:layout_width="14.0dip" android:layout_height="46.0dip" android:layout_centerHorizontal="true" android:layout_marginTop="40.0dip" android:scaleType="fitXY" android:src="@drawable/info_ruler" /> </RelativeLayout> <Button android:id="@+id/click" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="點(diǎn)擊改變" /> </LinearLayout> </LinearLayout>
4.Activity中使用MainActivity
public class MainActivity extends AppCompatActivity { private int maxValue = 250; private int minValue = 80; private RulerView rulerHeight; private TextView tvHeightValue; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rulerHeight = (RulerView) findViewById(R.id.ruler_height); tvHeightValue = (TextView) findViewById(R.id.tv_info_height_value); showNumInt(); findViewById(R.id.click).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { showNumInt(); } }); rulerHeight.setOnValueChangeListener(new RulerView.OnValueChangeListener() { @Override public void onValueChange(float value) { tvHeightValue.setText(String.valueOf(value)); } }); } private void showNumInt() { Random rand = new Random(); int value = rand.nextInt(maxValue - minValue + 1) + minValue; rulerHeight.setValue(value, minValue, maxValue, 1); tvHeightValue.setText(String.valueOf(Integer.valueOf(value))); } }
PS:可自行根據(jù)需要繪制線(xiàn)條和文字,上下選擇文字位置。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。