Android——自定义带刻度的SeekBar单向拖动条 原创 2017年04月21日 11:29:53 标签:android /listview /app /seekbar 1302 时间过得真快,
Android——自定义带刻度的SeekBar单向拖动条
原创 2017年04月21日 11:29:53时间过得真快,才发现好久没来逛逛了。没写博客的这段时间一直在做项目,连续完成了两个大型app,这个过程很享受,这是独立开发的,所以中途有很多很多的问题需要自己一个一个的去解决,现在接近尾声了,发现自己在这个阶段成长了不少,当然需要学习的知识还有很多很多,就让我们大家一起学习吧!
今天就分享一个自己在项目中,客户要求的功能,拖动条设置ListView列表中item的金额。这边主要的就是说seekbar这个东西,那我们开始吧!
看下效果:
大概就是这样,上面的刻度值是可以动态设置的,下面详细说一下,先看下自定义的代码块:
package com.ds.platform.view;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.TypeEvaluator;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.NinePatch;import android.graphics.Paint;import android.graphics.RadialGradient;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.Shader;import android.graphics.Typeface;import android.os.Parcel;import android.os.Parcelable;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import com.ds.platform.R;import com.ds.platform.utils.SharePreferencesUtils;/** * @author: Allen * @date: 2017/3/13 * @description: 自定义SeekBar 带刻度 */public class RangeSeekBar extends View { private static final float DEFAULT_RADIUS = 0.5f; //default seekbar's padding left and right private int DEFAULT_PADDING_LEFT_AND_RIGHT; private int defaultPaddingTop; //进度提示的背景 The background of the progress private final int mProgressHintBGId; // 按钮的背景 The background of the Drag button private final int mThumbResId; //刻度模式:number根据数字实际比例排列;other 均分排列 //Scale mode: // number according to the actual proportion of the number of arranged; // other equally arranged private final int mCellMode; //single是Seekbar模式,range是RangeSeekbar //single is Seekbar mode, range is angeSeekbar //single = 1; range = 2 private final int mSeekBarMode; //默认为1,当大于1时自动切回刻度模式 //The default is 1, and when it is greater than 1, // it will automatically switch back to the scale mode private int cellsCount = 1; //刻度与进度条间的间距 //The spacing between the scale and the progress bar private int textPadding; //进度提示背景与按钮之间的距离 //The progress indicates the distance between the background and the button private int mHintBGPadding; private int mSeekBarHeight; private int mThumbSize; //两个按钮之间的最小距离 //The minimum distance between two buttons private int reserveCount; private int mCursorTextHeight; private int mPartLength; private int heightNeeded; private int lineCorners; private int lineWidth; //选择过的进度条颜色 // the color of the selected progress bar private int colorLineSelected; //未选则的进度条颜色 // the color of the unselected progress bar private int colorLineEdge; //The foreground color of progress bar and thumb button. private int colorPrimary; //The background color of progress bar and thumb button. private int colorSecondary; //刻度文字与提示文字的大小 //Scale text and prompt text size private int mTextSize; private int mTextColor; private int lineTop, lineBottom, lineLeft, lineRight; //进度提示背景的高度,宽度如果是0的话会自适应调整 //Progress prompted the background height, width, // if it is 0, then adaptively adjust private float mHintBGHeight; private float mHintBGWith; private float offsetValue; private float cellsPercent; private float reserveValue; private float reservePercent; private float maxValue, minValue; //真实的最大值和最小值 //True maximum and minimum values private float mMin, mMax; private boolean isEnable = true; private final boolean mHideProgressHint; //刻度上显示的文字 private CharSequence[] mTextArray; private Bitmap mProgressHintBG; private Paint mMainPaint = new Paint(); private Paint mCursorPaint = new Paint(); private Paint mProgressPaint; private RectF line = new RectF(); private SeekBar leftSB; private SeekBar rightSB; private SeekBar currTouch; private OnRangeChangedListener callback; public RangeSeekBar(Context context) { this(context, null); } public RangeSeekBar(Context context, AttributeSet attrs) { super(context, attrs); TypedArray t = context.obtainStyledAttributes(attrs, R.styleable.RangeSeekBar); cellsCount = t.getInt(R.styleable.RangeSeekBar_cells, 1); reserveValue = t.getFloat(R.styleable.RangeSeekBar_reserve, 0); mMin = t.getFloat(R.styleable.RangeSeekBar_min, 0);//最小取值 //从缓存中拿值 float maxValue = SharePreferencesUtils.getFloat(context, "maxValue", 0); if (0 == maxValue) { mMax = t.getFloat(R.styleable.RangeSeekBar_max, 100);//最大取值 } else { mMax = maxValue; } mThumbResId = t.getResourceId(R.styleable.RangeSeekBar_seekBarResId, 0); mProgressHintBGId = t.getResourceId(R.styleable.RangeSeekBar_progressHintResId, 0); colorLineSelected = t.getColor(R.styleable.RangeSeekBar_lineColorSelected, 0xFF4BD962); colorLineEdge = t.getColor(R.styleable.RangeSeekBar_lineColorEdge, 0xFF0000); colorPrimary = t.getColor(R.styleable.RangeSeekBar_thumbPrimaryColor, 0); colorSecondary = t.getColor(R.styleable.RangeSeekBar_thumbSecondaryColor, 0); //从缓存中拿值 CharSequence tempArray[] = SharePreferencesUtils.getStringSet(context, "textArray", null); if (tempArray == null || tempArray.length == 0) { mTextArray = t.getTextArray(R.styleable.RangeSeekBar_markTextArray); } else { mTextArray = tempArray; } mHideProgressHint = t.getBoolean(R.styleable.RangeSeekBar_hideProgressHint, false); textPadding = (int) t.getDimension(R.styleable.RangeSeekBar_textPadding, dp2px(context, 20)); mTextSize = (int) t.getDimension(R.styleable.RangeSeekBar_textSize, dp2px(context, 12)); mTextColor = t.getColor(R.styleable.RangeSeekBar_textColor, ContextCompat.getColor(context, R.color.main_text)); mHintBGHeight = t.getDimension(R.styleable.RangeSeekBar_hintBGHeight, 0); mHintBGWith = t.getDimension(R.styleable.RangeSeekBar_hintBGWith, 0); mSeekBarHeight = (int) t.getDimension(R.styleable.RangeSeekBar_seekBarHeight, dp2px(context, 2)); mHintBGPadding = (int) t.getDimension(R.styleable.RangeSeekBar_hintBGPadding, 0); mThumbSize = (int) t.getDimension(R.styleable.RangeSeekBar_thumbSize, dp2px(context, 26)); mCellMode = t.getInt(R.styleable.RangeSeekBar_cellMode, 0); mSeekBarMode = t.getInt(R.styleable.RangeSeekBar_seekBarMode, 2); if (mSeekBarMode == 2) { leftSB = new SeekBar(-1); rightSB = new SeekBar(1); } else { leftSB = new SeekBar(-1); } // if you don't set the mHintBGWith or the mHintBGWith < default value, if will use default value if (mHintBGWith == 0) { DEFAULT_PADDING_LEFT_AND_RIGHT = dp2px(context, 25); } else { DEFAULT_PADDING_LEFT_AND_RIGHT = Math.max((int) (mHintBGWith / 2 + dp2px(context, 5)), dp2px(context, 25)); } setRules(mMin, mMax, reserveValue, cellsCount); initPaint(); initBitmap(); t.recycle(); defaultPaddingTop = mSeekBarHeight / 2; mHintBGHeight = mHintBGHeight == 0 ? (mCursorPaint.measureText("国") * 3) : mHintBGHeight; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); heightNeeded = 2 * (lineTop) + mSeekBarHeight; /** * onMeasure传入的widthMeasureSpec和heightMeasureSpec不是一般的尺寸数值,而是将模式和尺寸组合在一起的数值 * MeasureSpec.EXACTLY 是精确尺寸 * MeasureSpec.AT_MOST 是最大尺寸 * MeasureSpec.UNSPECIFIED 是未指定尺寸 */ if (heightMode == MeasureSpec.EXACTLY) { heightSize = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); } else if (heightMode == MeasureSpec.AT_MOST) { heightSize = MeasureSpec.makeMeasureSpec( heightSize < heightNeeded ? heightSize : heightNeeded, MeasureSpec.EXACTLY); } else { heightSize = MeasureSpec.makeMeasureSpec( heightNeeded, MeasureSpec.EXACTLY); } super.onMeasure(widthMeasureSpec, heightSize); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); //计算进度条的位置,并根据它初始化两个按钮的位置 // Calculates the position of the progress bar and initializes the positions of // the two buttons based on it lineLeft = DEFAULT_PADDING_LEFT_AND_RIGHT + getPaddingLeft(); lineRight = w - lineLeft - getPaddingRight(); lineTop = (int) mHintBGHeight + mThumbSize / 2 - mSeekBarHeight / 2 + 30; lineBottom = lineTop + mSeekBarHeight; lineWidth = lineRight - lineLeft; line.set(lineLeft, lineTop, lineRight, lineBottom); lineCorners = (int) ((lineBottom - lineTop) * 0.45f); leftSB.onSizeChanged(lineLeft, lineBottom, mThumbSize, lineWidth, cellsCount > 1, mThumbResId, getContext()); if (mSeekBarMode == 2) { rightSB.onSizeChanged(lineLeft, lineBottom, mThumbSize, lineWidth, cellsCount > 1, mThumbResId, getContext()); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制刻度,并且根据当前位置是否在刻度范围内设置不同的颜色显示 // Draw the scales, and according to the current position is set within // the scale range of different color display if (mTextArray != null) { mPartLength = lineWidth / (mTextArray.length - 1); for (int i = 0; i < mTextArray.length; i++) { final String text2Draw = mTextArray[i].toString(); float x; //平分显示 if (mCellMode == 1) { mCursorPaint.setColor(mTextColor); mCursorPaint.setAntiAlias(true); x = lineLeft + i * mPartLength - mCursorPaint.measureText(text2Draw) / 2; } else { float num = Float.parseFloat(text2Draw); float[] result = getCurrentRange(); if (compareFloat(num, result[0]) != -1 && compareFloat(num, result[1]) != 1 && mSeekBarMode == 2) { mCursorPaint.setColor(ContextCompat.getColor(getContext(), R.color.colorAccent)); } else { mCursorPaint.setColor(mTextColor); mCursorPaint.setAntiAlias(true); } //按实际比例显示 x = lineLeft + lineWidth * (num - mMin) / (mMax - mMin) - mCursorPaint.measureText(text2Draw) / 2; } float y = lineTop - textPadding; canvas.drawText(text2Draw, x, y, mCursorPaint); } } //绘制进度条 // draw the progress bar mMainPaint.setColor(colorLineEdge); canvas.drawRoundRect(line, lineCorners, lineCorners, mMainPaint); mMainPaint.setColor(colorLineSelected); if (mSeekBarMode == 2) { canvas.drawRect(leftSB.left + leftSB.widthSize / 2 + leftSB.lineWidth * leftSB.currPercent, lineTop, rightSB.left + rightSB.widthSize / 2 + rightSB.lineWidth * rightSB.currPercent, lineBottom, mMainPaint); } else { canvas.drawRect(leftSB.left + leftSB.widthSize / 2, lineTop, leftSB.left + leftSB.widthSize / 2 + leftSB.lineWidth * leftSB.currPercent, lineBottom, mMainPaint); } leftSB.draw(canvas); if (mSeekBarMode == 2) { rightSB.draw(canvas); } } /** * 初始化画笔 * init the paints */ private void initPaint() { mMainPaint.setStyle(Paint.Style.FILL); mMainPaint.setColor(colorLineEdge); mCursorPaint.setStyle(Paint.Style.FILL); mCursorPaint.setColor(colorLineEdge); mCursorPaint.setTextSize(mTextSize); mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mProgressPaint.setTypeface(Typeface.DEFAULT); mProgressPaint.setColor(0xFF0000); //计算文字的高度 //Calculate the height of the text Paint.FontMetrics fm = mCursorPaint.getFontMetrics(); mCursorTextHeight = (int) (Math.ceil(fm.descent - fm.ascent) + 2); } /** * 初始化进度提示的背景 */ private void initBitmap() { if (mProgressHintBGId != 0) { mProgressHintBG = BitmapFactory.decodeResource(getResources(), mProgressHintBGId); } else { mProgressHintBG = BitmapFactory.decodeResource(getResources(), R.drawable.progress_hint_bg); } } //*********************************** SeekBar ***********************************// private class SeekBar { private int lineWidth; private int widthSize, heightSize; private int left, right, top, bottom; private float currPercent; private float material = 0; public boolean isShowingHint; private boolean isLeft; private Bitmap bmp; private ValueAnimator anim; private RadialGradient shadowGradient; private Paint defaultPaint; private String mHintText2Draw; private Boolean isPrimary = true; public SeekBar(int position) { if (position < 0) { isLeft = true; } else { isLeft = false; } } /** * 计算每个按钮的位置和尺寸 * Calculates the position and size of each button * * @param x * @param y * @param hSize * @param parentLineWidth * @param cellsMode * @param bmpResId * @param context */ protected void onSizeChanged(int x, int y, int hSize, int parentLineWidth, boolean cellsMode, int bmpResId, Context context) { heightSize = hSize; widthSize = heightSize; left = x - widthSize / 2; right = x + widthSize / 2; top = y - heightSize / 2; bottom = y + heightSize / 10; if (cellsMode) { lineWidth = parentLineWidth; } else { lineWidth = parentLineWidth; } if (bmpResId > 0) { Bitmap original = BitmapFactory.decodeResource(context.getResources(), bmpResId); if (original != null) { Matrix matrix = new Matrix(); float scaleHeight = mThumbSize * 1.0f / original.getHeight(); float scaleWidth = scaleHeight; matrix.postScale(scaleWidth, scaleHeight); bmp = Bitmap.createBitmap(original, 0, 0, original.getWidth(), original.getHeight(), matrix, true); } } else { defaultPaint = new Paint(Paint.ANTI_ALIAS_FLAG); int radius = (int) (widthSize * DEFAULT_RADIUS); int barShadowRadius = (int) (radius * 0.95f); int mShadowCenterX = widthSize / 2; int mShadowCenterY = heightSize / 2; shadowGradient = new RadialGradient(mShadowCenterX, mShadowCenterY, barShadowRadius, Color.BLACK, Color.TRANSPARENT, Shader.TileMode.CLAMP); } } /** * 绘制按钮和提示背景和文字 * Draw buttons and tips for background and text * * @param canvas */ protected void draw(Canvas canvas) { int offset = (int) (lineWidth * currPercent); canvas.save(); canvas.translate(offset, 0); String text2Draw = ""; int hintW = 0, hintH = 0; float[] result = getCurrentRange(); if (mHideProgressHint) { isShowingHint = false; } else { if (isLeft) { if (mHintText2Draw == null) { text2Draw = (int) result[0] + ""; } else { text2Draw = mHintText2Draw; } // if is the start,change the thumb color isPrimary = (compareFloat(result[0], mMin) == 0); } else { if (mHintText2Draw == null) { text2Draw = (int) result[1] + ""; } else { text2Draw = mHintText2Draw; } isPrimary = (compareFloat(result[1], mMax) == 0); } hintH = (int) mHintBGHeight - 20;//设置提示背景的高度 hintW = (int) (mHintBGWith == 0 ? (mCursorPaint.measureText(text2Draw) + DEFAULT_PADDING_LEFT_AND_RIGHT) : mHintBGWith); if (hintW < 1.5f * hintH) hintW = (int) (1.5f * hintH); } if (bmp != null) { canvas.drawBitmap(bmp, left, lineTop - bmp.getHeight() / 2, null); if (isShowingHint) { Rect rect = new Rect(); rect.left = left - (hintW / 2 - bmp.getWidth() / 2); rect.top = bottom - hintH - bmp.getHeight(); rect.right = rect.left + hintW; rect.bottom = rect.top + hintH - 10; drawNinePath(canvas, mProgressHintBG, rect); mCursorPaint.setColor(Color.WHITE);//提示字的颜色 mCursorPaint.setTextSize(mTextSize); int x = (int) (left + (bmp.getWidth() / 2) - mCursorPaint.measureText(text2Draw) / 2); int y = bottom - hintH - bmp.getHeight() + hintH / 2; canvas.drawText(text2Draw, x, y, mCursorPaint); } } else { canvas.translate(left, 0); if (isShowingHint) { Rect rect = new Rect(); rect.left = widthSize / 2 - hintW / 2; rect.top = defaultPaddingTop; rect.right = rect.left + hintW; rect.bottom = rect.top + hintH - 10; drawNinePath(canvas, mProgressHintBG, rect); mCursorPaint.setColor(Color.WHITE); mCursorPaint.setTextSize(mTextSize); int x = (int) (widthSize / 2 - mCursorPaint.measureText(text2Draw) / 2); // TODO: 2017/2/6 //这里和背景形状有关,暂时根据本图形状比例计算 //Here and the background shape, temporarily based on the shape of this figure ratio calculation int y = hintH / 3 + defaultPaddingTop + mCursorTextHeight / 2; canvas.drawText(text2Draw, x, y, mCursorPaint); } drawDefault(canvas); } canvas.restore(); } /** * 绘制 9Path * * @param c * @param bmp * @param rect */ public void drawNinePath(Canvas c, Bitmap bmp, Rect rect) { NinePatch patch = new NinePatch(bmp, bmp.getNinePatchChunk(), null); patch.draw(c, rect); } /** * 如果没有图片资源,则绘制默认按钮 * * If there is no image resource, draw the default button * * @param canvas */
private void drawDefault(Canvas canvas) { int centerX = widthSize / 2; int centerY = lineBottom - mSeekBarHeight / 2; int radius = (int) (widthSize * DEFAULT_RADIUS); // draw shadow defaultPaint.setStyle(Paint.Style.FILL); canvas.save(); canvas.translate(0, radius * 0.25f); canvas.scale(1 + (0.1f * material), 1 + (0.1f * material), centerX, centerY); defaultPaint.setShader(shadowGradient); canvas.drawCircle(centerX, centerY, radius, defaultPaint); defaultPaint.setShader(null); canvas.restore(); // draw body defaultPaint.setStyle(Paint.Style.FILL); if (isPrimary) { //if not set the color,it will use default color if (colorPrimary == 0) { defaultPaint.setColor(te.evaluate(material, 0xFFFFFFFF, 0xFFE7E7E7)); } else { defaultPaint.setColor(colorPrimary); } } else { if (colorSecondary == 0) { defaultPaint.setColor(te.evaluate(material, 0xFFFFFFFF, 0xFF0000)); } else { defaultPaint.setColor(colorSecondary); } } canvas.drawCircle(centerX, centerY, radius, defaultPaint); // draw border defaultPaint.setStyle(Paint.Style.STROKE); defaultPaint.setColor(0xFFD7D7D7); canvas.drawCircle(centerX, centerY, radius, defaultPaint); } final TypeEvaluator te = new TypeEvaluator() { @Override public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int alpha = (int) (Color.alpha(startValue) + fraction * (Color.alpha(endValue) - Color.alpha(startValue))); int red = (int) (Color.red(startValue) + fraction * (Color.red(endValue) - Color.red(startValue))); int green = (int) (Color.green(startValue) + fraction * (Color.green(endValue) - Color.green(startValue))); int blue = (int) (Color.blue(startValue) + fraction * (Color.blue(endValue) - Color.blue(startValue))); return Color.argb(alpha, red, green, blue); } }; /** * 拖动检测 * * @param event * @return */ protected boolean collide(MotionEvent event) { float x = event.getX(); float y = event.getY(); int offset = (int) (lineWidth * currPercent); return x > left + offset && x < right + offset && y > top && y < bottom; } private void slide(float percent) { if (percent < 0) percent = 0; else if (percent > 1) percent = 1; currPercent = percent; } private void materialRestore() { if (anim != null) anim.cancel(); anim = ValueAnimator.ofFloat(material, 0); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { material = (float) animation.getAnimatedValue(); invalidate(); } }); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { material = 0; invalidate(); } }); anim.start(); } public void setProgressHint(String hint) { mHintText2Draw = hint; } } //*********************************** SeekBar ***********************************// public interface OnRangeChangedListener { void onRangeChanged(RangeSeekBar view, float min, float max, boolean isFromUser); } public void setOnRangeChangedListener(OnRangeChangedListener listener) { callback = listener; } public void setValue(float min, float max) { min = min + offsetValue; max = max + offsetValue; if (min < minValue) { throw new IllegalArgumentException("setValue() min < (preset min - offsetValue) . #min:" + min + " #preset min:" + minValue + " #offsetValue:" + offsetValue); } if (max > maxValue) { throw new IllegalArgumentException("setValue() max > (preset max - offsetValue) . #max:" + max + " #preset max:" + maxValue + " #offsetValue:" + offsetValue); } if (reserveCount > 1) { if ((min - minValue) % reserveCount != 0) { throw new IllegalArgumentException("setValue() (min - preset min) % reserveCount != 0 . #min:" + min + " #preset min:" + minValue + "#reserveCount:" + reserveCount + "#reserve:" + reserveValue); } if ((max - minValue) % reserveCount != 0) { throw new IllegalArgumentException("setValue() (max - preset min) % reserveCount != 0 . #max:" + max + " #preset min:" + minValue + "#reserveCount:" + reserveCount + "#reserve:" + reserveValue); } leftSB.currPercent = (min - minValue) / reserveCount * cellsPercent; if (mSeekBarMode == 2) { rightSB.currPercent = (max - minValue) / reserveCount * cellsPercent; } } else { leftSB.currPercent = (min - minValue) / (maxValue - minValue); if (mSeekBarMode == 2) { rightSB.currPercent = (max - minValue) / (maxValue - minValue); } } if (callback != null) { if (mSeekBarMode == 2) { callback.onRangeChanged(this, leftSB.currPercent, rightSB.currPercent, false); } else { callback.onRangeChanged(this, leftSB.currPercent, leftSB.currPercent, false); } } invalidate(); } public void setValue(float value) { setValue(value, mMax); } public void setRange(float min, float max) { setRules(min, max, reserveCount, cellsCount); } public void setRules(float min, float max, float reserve, int cells) { if (max <= min) { throw new IllegalArgumentException("setRules() max must be greater than min ! #max:" + max + " #min:" + min); } mMax = max; mMin = min; if (min < 0) { offsetValue = 0 - min; min = min + offsetValue; max = max + offsetValue; } minValue = min; maxValue = max; if (reserve < 0) { throw new IllegalArgumentException("setRules() reserve must be greater than zero ! #reserve:" + reserve); } if (reserve >= max - min) { throw new IllegalArgumentException("setRules() reserve must be less than (max - min) ! #reserve:" + reserve + " #max - min:" + (max - min)); } if (cells < 1) { throw new IllegalArgumentException("setRules() cells must be greater than 1 ! #cells:" + cells); } cellsCount = cells; cellsPercent = 1f / cellsCount; reserveValue = reserve; reservePercent = reserve / (max - min); reserveCount = (int) (reservePercent / cellsPercent + (reservePercent % cellsPercent != 0 ? 1 : 0)); if (cellsCount > 1) { if (mSeekBarMode == 2) { if (leftSB.currPercent + cellsPercent * reserveCount <= 1 && leftSB.currPercent + cellsPercent * reserveCount > rightSB.currPercent) { rightSB.currPercent = leftSB.currPercent + cellsPercent * reserveCount; } else if (rightSB.currPercent - cellsPercent * reserveCount >= 0 && rightSB.currPercent - cellsPercent * reserveCount < leftSB.currPercent) { leftSB.currPercent = rightSB.currPercent - cellsPercent * reserveCount; } } else { if (1 - cellsPercent * reserveCount >= 0 && 1 - cellsPercent * reserveCount < leftSB.currPercent) { leftSB.currPercent = 1 - cellsPercent * reserveCount; } } } else { if (mSeekBarMode == 2) { if (leftSB.currPercent + reservePercent <= 1 && leftSB.currPercent + reservePercent > rightSB.currPercent) { rightSB.currPercent = leftSB.currPercent + reservePercent; } else if (rightSB.currPercent - reservePercent >= 0 && rightSB.currPercent - reservePercent < leftSB.currPercent) { leftSB.currPercent = rightSB.currPercent - reservePercent; } } else { if (1 - reservePercent >= 0 && 1 - reservePercent < leftSB.currPercent) { leftSB.currPercent = 1 - reservePercent; } } } invalidate(); } public float getMax() { return mMax; } public float getMin() { return mMin; } public float[] getCurrentRange() { float range = maxValue - minValue; if (mSeekBarMode == 2) { return new float[]{-offsetValue + minValue + range * leftSB.currPercent, -offsetValue + minValue + range * rightSB.currPercent}; } else { return new float[]{-offsetValue + minValue + range * leftSB.currPercent, -offsetValue + minValue + range * 1.0f}; } } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); this.isEnable = enabled; } public void setProgressDescription(String progress) { if (leftSB != null) { leftSB.setProgressHint(progress); } if (rightSB != null) { rightSB.setProgressHint(progress); } } public void setLeftProgressDescription(String progress) { if (leftSB != null) { leftSB.setProgressHint(progress); } } public void setRightProgressDescription(String progress) { if (rightSB != null) { rightSB.setProgressHint(progress); } } @Override public boolean onTouchEvent(MotionEvent event) { if (!isEnable) return true; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: boolean touchResult = false; if (rightSB != null && rightSB.currPercent >= 1 && leftSB.collide(event)) { currTouch = leftSB; touchResult = true; } else if (rightSB != null && rightSB.collide(event)) { currTouch = rightSB; touchResult = true; } else if (leftSB.collide(event)) { currTouch = leftSB; touchResult = true; } //Intercept parent TouchEvent if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } return touchResult; case MotionEvent.ACTION_MOVE: float percent; float x = event.getX(); currTouch.material = currTouch.material >= 1 ? 1 : currTouch.material + 0.1f; if (currTouch == leftSB) { if (cellsCount > 1) { if (x < lineLeft) { percent = 0; } else { percent = (x - lineLeft) * 1f / (lineWidth); } int touchLeftCellsValue = Math.round(percent / cellsPercent); int currRightCellsValue; if (mSeekBarMode == 2) { currRightCellsValue = Math.round(rightSB.currPercent / cellsPercent); } else { currRightCellsValue = Math.round(1.0f / cellsPercent); } percent = touchLeftCellsValue * cellsPercent; while (touchLeftCellsValue > currRightCellsValue - reserveCount) { touchLeftCellsValue--; if (touchLeftCellsValue < 0) break; percent = touchLeftCellsValue * cellsPercent; } } else { if (x < lineLeft) { percent = 0; } else { percent = (x - lineLeft) * 1f / (lineWidth); } if (mSeekBarMode == 2) { if (percent > rightSB.currPercent - reservePercent) { percent = rightSB.currPercent - reservePercent; } } else { if (percent > 1.0f - reservePercent) { percent = 1.0f - reservePercent; } } } leftSB.slide(percent); leftSB.isShowingHint = true; //Intercept parent TouchEvent if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } } else if (currTouch == rightSB) { if (cellsCount > 1) { if (x > lineRight) { percent = 1; } else { percent = (x - lineLeft) * 1f / (lineWidth); } int touchRightCellsValue = Math.round(percent / cellsPercent); int currLeftCellsValue = Math.round(leftSB.currPercent / cellsPercent); percent = touchRightCellsValue * cellsPercent; while (touchRightCellsValue < currLeftCellsValue + reserveCount) { touchRightCellsValue++; if (touchRightCellsValue > maxValue - minValue) break; percent = touchRightCellsValue * cellsPercent; } } else { if (x > lineRight) { percent = 1; } else { percent = (x - lineLeft) * 1f / (lineWidth); } if (percent < leftSB.currPercent + reservePercent) { percent = leftSB.currPercent + reservePercent; } } rightSB.slide(percent); rightSB.isShowingHint = true; } if (callback != null) { float[] result = getCurrentRange(); callback.onRangeChanged(this, result[0], result[1], true); } invalidate(); //Intercept parent TouchEvent if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } break; case MotionEvent.ACTION_CANCEL: if (mSeekBarMode == 2) { rightSB.isShowingHint = false; } leftSB.isShowingHint = false; if (callback != null) { float[] result = getCurrentRange(); callback.onRangeChanged(this, result[0], result[1], false); } //Intercept parent TouchEvent if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } break; case MotionEvent.ACTION_UP: if (mSeekBarMode == 2) { rightSB.isShowingHint = false; } leftSB.isShowingHint = false; currTouch.materialRestore(); if (callback != null) { float[] result = getCurrentRange(); callback.onRangeChanged(this, result[0], result[1], false); } //Intercept parent TouchEvent if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(true); } break; } return super.onTouchEvent(event); } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.minValue = minValue - offsetValue; ss.maxValue = maxValue - offsetValue; ss.reserveValue = reserveValue; ss.cellsCount = cellsCount; float[] results = getCurrentRange(); ss.currSelectedMin = results[0]; ss.currSelectedMax = results[1]; return ss; } @Override public void onRestoreInstanceState(Parcelable state) { SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); float min = ss.minValue; float max = ss.maxValue; float reserve = ss.reserveValue; int cells = ss.cellsCount; setRules(min, max, reserve, cells); float currSelectedMin = ss.currSelectedMin; float currSelectedMax = ss.currSelectedMax; setValue(currSelectedMin, currSelectedMax); } private class SavedState extends BaseSavedState { private float minValue; private float maxValue; private float reserveValue; private int cellsCount; private float currSelectedMin; private float currSelectedMax; SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); minValue = in.readFloat(); maxValue = in.readFloat(); reserveValue = in.readFloat(); cellsCount = in.readInt(); currSelectedMin = in.readFloat(); currSelectedMax = in.readFloat(); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeFloat(minValue); out.writeFloat(maxValue); out.writeFloat(reserveValue); out.writeInt(cellsCount); out.writeFloat(currSelectedMin); out.writeFloat(currSelectedMax); } } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ private int dp2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * Compare the size of two floating point numbers * * @param a * @param b * @return 1 is a > b * -1 is a < b * 0 is a == b */ private int compareFloat(float a, float b) { int ta = Math.round(a * 1000); int tb = Math.round(b * 1000); if (ta > tb) { return 1; } else if (ta < tb) { return -1; } else { return 0; } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
- 337
- 338
- 339
- 340
- 341
- 342
- 343
- 344
- 345
- 346
- 347
- 348
- 349
- 350
- 351
- 352
- 353
- 354
- 355
- 356
- 357
- 358
- 359
- 360
- 361
- 362
- 363
- 364
- 365
- 366
- 367
- 368
- 369
- 370
- 371
- 372
- 373
- 374
- 375
- 376
- 377
- 378
- 379
- 380
- 381
- 382
- 383
- 384
- 385
- 386
- 387
- 388
- 389
- 390
- 391
- 392
- 393
- 394
- 395
- 396
- 397
- 398
- 399
- 400
- 401
- 402
- 403
- 404
- 405
- 406
- 407
- 408
- 409
- 410
- 411
- 412
- 413
- 414
- 415
- 416
- 417
- 418
- 419
- 420
- 421
- 422
- 423
- 424
- 425
- 426
- 427
- 428
- 429
- 430
- 431
- 432
- 433
- 434
- 435
- 436
- 437
- 438
- 439
- 440
- 441
- 442
- 443
- 444
- 445
- 446
- 447
- 448
- 449
- 450
- 451
- 452
- 453
- 454
- 455
- 456
- 457
- 458
- 459
- 460
- 461
- 462
- 463
- 464
- 465
- 466
- 467
- 468
- 469
- 470
- 471
- 472
- 473
- 474
- 475
- 476
- 477
- 478
- 479
- 480
- 481
- 482
- 483
- 484
- 485
- 486
- 487
- 488
- 489
- 490
- 491
- 492
- 493
- 494
- 495
- 496
- 497
- 498
- 499
- 500
- 501
- 502
- 503
- 504
- 505
- 506
- 507
- 508
- 509
- 510
- 511
- 512
- 513
- 514
- 515
- 516
- 517
- 518
- 519
- 520
- 521
- 522
- 523
- 524
- 525
- 526
- 527
- 528
- 529
- 530
- 531
- 532
- 533
- 534
- 535
- 536
- 537
- 538
- 539
- 540
- 541
- 542
- 543
- 544
- 545
- 546
- 547
- 548
- 549
- 550
- 551
- 552
- 553
- 554
- 555
- 556
- 557
- 558
- 559
- 560
- 561
- 562
- 563
- 564
- 565
- 566
- 567
- 568
- 569
- 570
- 571
- 572
- 573
- 574
- 575
- 576
- 577
- 578
- 579
- 580
- 581
- 582
- 583
- 584
- 585
- 586
- 587
- 588
- 589
- 590
- 591
- 592
- 593
- 594
- 595
- 596
- 597
- 598
- 599
- 600
- 601
- 602
- 603
- 604
- 605
- 606
- 607
- 608
- 609
- 610
- 611
- 612
- 613
- 614
- 615
- 616
- 617
- 618
- 619
- 620
- 621
- 622
- 623
- 624
- 625
- 626
- 627
- 628
- 629
- 630
- 631
- 632
- 633
- 634
- 635
- 636
- 637
- 638
- 639
- 640
- 641
- 642
- 643
- 644
- 645
- 646
- 647
- 648
- 649
- 650
- 651
- 652
- 653
- 654
- 655
- 656
- 657
- 658
- 659
- 660
- 661
- 662
- 663
- 664
- 665
- 666
- 667
- 668
- 669
- 670
- 671
- 672
- 673
- 674
- 675
- 676
- 677
- 678
- 679
- 680
- 681
- 682
- 683
- 684
- 685
- 686
- 687
- 688
- 689
- 690
- 691
- 692
- 693
- 694
- 695
- 696
- 697
- 698
- 699
- 700
- 701
- 702
- 703
- 704
- 705
- 706
- 707
- 708
- 709
- 710
- 711
- 712
- 713
- 714
- 715
- 716
- 717
- 718
- 719
- 720
- 721
- 722
- 723
- 724
- 725
- 726
- 727
- 728
- 729
- 730
- 731
- 732
- 733
- 734
- 735
- 736
- 737
- 738
- 739
- 740
- 741
- 742
- 743
- 744
- 745
- 746
- 747
- 748
- 749
- 750
- 751
- 752
- 753
- 754
- 755
- 756
- 757
- 758
- 759
- 760
- 761
- 762
- 763
- 764
- 765
- 766
- 767
- 768
- 769
- 770
- 771
- 772
- 773
- 774
- 775
- 776
- 777
- 778
- 779
- 780
- 781
- 782
- 783
- 784
- 785
- 786
- 787
- 788
- 789
- 790
- 791
- 792
- 793
- 794
- 795
- 796
- 797
- 798
- 799
- 800
- 801
- 802
- 803
- 804
- 805
- 806
- 807
- 808
- 809
- 810
- 811
- 812
- 813
- 814
- 815
- 816
- 817
- 818
- 819
- 820
- 821
- 822
- 823
- 824
- 825
- 826
- 827
- 828
- 829
- 830
- 831
- 832
- 833
- 834
- 835
- 836
- 837
- 838
- 839
- 840
- 841
- 842
- 843
- 844
- 845
- 846
- 847
- 848
- 849
- 850
- 851
- 852
- 853
- 854
- 855
- 856
- 857
- 858
- 859
- 860
- 861
- 862
- 863
- 864
- 865
- 866
- 867
- 868
- 869
- 870
- 871
- 872
- 873
- 874
- 875
- 876
- 877
- 878
- 879
- 880
- 881
- 882
- 883
- 884
- 885
- 886
- 887
- 888
- 889
- 890
- 891
- 892
- 893
- 894
- 895
- 896
- 897
- 898
- 899
- 900
- 901
- 902
- 903
- 904
- 905
- 906
- 907
- 908
- 909
- 910
- 911
- 912
- 913
- 914
- 915
- 916
- 917
- 918
- 919
- 920
- 921
- 922
- 923
- 924
- 925
- 926
- 927
- 928
- 929
- 930
- 931
- 932
- 933
- 934
- 935
- 936
- 937
- 938
- 939
- 940
- 941
- 942
- 943
- 944
- 945
- 946
- 947
- 948
- 949
- 950
- 951
- 952
- 953
- 954
- 955
- 956
- 957
- 958
- 959
- 960
- 961
- 962
- 963
- 964
- 965
- 966
- 967
- 968
- 969
- 970
- 971
- 972
- 973
- 974
- 975
- 976
- 977
- 978
- 979
- 980
- 981
- 982
- 983
- 984
- 985
- 986
- 987
- 988
- 989
- 990
- 991
- 992
- 993
- 994
- 995
- 996
- 997
- 998
- 999
- 1000
- 1001
- 1002
- 1003
- 1004
- 1005
- 1006
- 1007
- 1008
- 1009
- 1010
- 1011
- 1012
- 1013
- 1014
- 1015
- 1016
- 1017
- 1018
- 1019
- 1020
- 1021
- 1022
- 1023
- 1024
- 1025
- 1026
- 1027
- 1028
- 1029
- 1030
- 1031
- 1032
- 1033
- 1034
- 1035
- 1036
- 1037
- 1038
- 1039
取拖动条的最大值代码块:
//从缓存中拿值 float maxValue = SharePreferencesUtils.getFloat(context, "maxValue", 0); if (0 == maxValue) { mMax = t.getFloat(R.styleable.RangeSeekBar_max, 100);//最大取值 } else { mMax = maxValue; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这边的maxValue 值是从缓存中取出来的,如果在缓存中这个key(maxValue)为空的话,默认值为0,为0的时候从本地的配置文件arrays.xml中拿取默认的最大值(100),该文件放置在values目录下面,代码如下:
<?xml version="1.0" encoding="utf-8"?><resources> <string-array name="markArray"> <item>0item> <item>10item> <item>20item> <item>30item> <item>50item> <item>100item> string-array>resources>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
还有一段就是获取刻度的array。
//从缓存中拿值 CharSequence tempArray[] = SharePreferencesUtils.getStringSet(context, "textArray", null); if (tempArray == null || tempArray.length == 0) { mTextArray = t.getTextArray(R.styleable.RangeSeekBar_markTextArray); } else { mTextArray = tempArray; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
一样的 存储方式,放在SharePreferences内存当中,默认为null,默认获取的就是上面的arrays.xml文件。不为空则在本内存中获取,那么这边可能有人会问,SharePreferences怎么存储和获取数组元素,我这边贴出来一下:
package com.ds.platform.utils;import android.content.Context;import android.content.SharedPreferences;import android.util.Log;import com.ds.platform.bean.Lot;import java.util.ArrayList;import java.util.Arrays;import java.util.HashSet;import java.util.Iterator;import java.util.Set;/** * 覆盖模式的SharePreference */public class SharePreferencesUtils { private final static String SP_NAME = "sp_cache"; private static SharedPreferences mPreferences; // SharedPreferences的实例 private static final String TAG = LogUtils.LogName; private static SharedPreferences getSp(Context context) { if (mPreferences == null) { mPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);//覆盖 } return mPreferences; } /** * 通过SP获得boolean类型的数据,没有默认为false * * @param context : 上下文 * @param key : 存储的key * @return */ public static boolean getBoolean(Context context, String key) { SharedPreferences sp = getSp(context); return sp.getBoolean(key, false); } /** * 通过SP获得boolean类型的数据,没有默认为false * * @param context : 上下文 * @param key : 存储的key * @param defValue : 默认值 * @return */ public static boolean getBoolean(Context context, String key, boolean defValue) { SharedPreferences sp = getSp(context); return sp.getBoolean(key, defValue); } /** * 设置int的缓存数据 * * @param context * @param key :缓存对应的key * @param value :缓存对应的值 */ public static void setBoolean(Context context, String key, boolean value) { SharedPreferences sp = getSp(context); SharedPreferences.Editor edit = sp.edit();// 获取编辑器 edit.putBoolean(key, value); edit.commit(); } /** * 缓存float * * @param context * @param key * @param defValue * @return */ public static void setFloat(Context context, String key, float defValue) { SharedPreferences sp = getSp(context); SharedPreferences.Editor edit = sp.edit();// 获取编辑器 edit.putFloat(key, defValue); edit.commit(); } /** * 获取int型数据 * @param context * @param key * @param defValue * @return */ public static int getInt(Context context, String key, int defValue) { SharedPreferences sp = getSp(context); return sp.getInt(key, defValue); } /** * 获取string值 * @param context * @param key * @param defValue * @return */ public static String getString(Context context, String key, String defValue) { SharedPreferences sp = getSp(context); return sp.getString(key, defValue); } public static float getFloat(Context context, String key, float defValue) { SharedPreferences sp = getSp(context); return sp.getFloat(key, defValue); } public static long getLong(Context context, String key, long defValue) { SharedPreferences sp = getSp(context); return sp.getLong(key, 0); } /** * 储存数组 */ public static void setArrayData(Context context, String key, CharSequence text[]) { if (text == null || text.length == 0) { return; } SharedPreferences sp = getSp(context); SharedPreferences.Editor edit = sp.edit();// 获取编辑器 Set set = new HashSet(); for (int i = 0; i < text.length; i++) { set.add(text[i]); } edit.putStringSet(key, set); edit.commit(); } /** * 获取数组 */ public static CharSequence[] getStringSet(Context context, String key, Set defValue) { CharSequence sequence[] = new CharSequence[6]; SharedPreferences sp = getSp(context); Set set = sp.getStringSet(key, defValue); if (set != null && set.size() > 0) { Iterator
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
上述是我项目中用到的,需要的可以看一下,另外分享一个小技巧,如果你想知道app中存入在Sp内存中的数据怎么看呢?可以在android studio中去查看,工具导航栏Tools–>Android–>Android Device Monitor ,打开之后点击右侧导航菜单的File Explorer ,找到data–>data–>自己的项目包名–>shared_prefs–>自己定义的sp名字,这边定义的是sp_cache,然后该目录下就存在一个sp_cache.xml的文件,点击右上角的图标 第一个导出电脑就可以查看了。好了,原归正传:
我怎么动态设置数组呢?先看下效果图:
不知你们有没有发现一些细节,每次拖动条上面的刻度文字跟跳转另一个activity输入框的数字是顺序大小一样,还有动态去设置刻度值得时候我没有从0开始,而是大于0的数字开始,我也做了启用停用的开关,停用之后不能使用拖动条功能,这个状态也是保存在SP内存里面的。
接下来看一下拖动条的对话框,我使用fragment做的,这边也一起说一下吧!
代码如下:
package com.ds.platform.dialog;import android.os.Bundle;import android.support.annotation.Nullable;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import com.ds.platform.R;import com.ds.platform.activity.OrderActivity;import com.ds.platform.utils.LogUtils;import com.ds.platform.view.RangeSeekBar;/** * @author: Allen. * @date: 2017/4/14 * @description: 拖动条对话框 */public class MyDialogFragment extends android.support.v4.app.DialogFragment { private RangeSeekBar seekbar1; private String progressData = "0";//初始第一个数值 private static final String TAG = LogUtils.LogName; private OrderActivity orderActivity; @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.dialog_balance_seekbar, null); orderActivity = (OrderActivity) getActivity(); initView(view);//初始控件 //去除标题 getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); setCancelable(true); return view; } /** * 获取控件 * * @param view */ private void initView(View view) { seekbar1 = (RangeSeekBar) view.findViewById(R.id.seekbar1); seekbar1.setValue(0);//设置默认值 //监听控件去设置列表订单的item金额 seekbar1.setOnRangeChangedListener(new RangeSeekBar.OnRangeChangedListener() { @Override public void onRangeChanged(RangeSeekBar view, float min, float max, boolean isFromUser) { seekbar1.setProgressDescription((int) min + ""); progressData = ((int) min) + ""; orderActivity.setMoney(Integer.parseInt(progressData)); } }); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
那怎么使用这个fragment呢?首先不用思考的,其父类必须继承FragmentActivity,然后在父类的layout中必须有
<FrameLayout android:id="@+id/fragment" android:layout_width="match_parent" android:layout_height="match_parent" />
- 1
- 2
- 3
- 4
然后可以通过view来触发这个fragment。
FragmentTransaction tran = getSupportFragmentManager().beginTransaction(); MyDialogFragment dialogFragment = new MyDialogFragment(); dialogFragment.show(tran, "myDialog");
- 1
- 2
- 3
需要注意的是要用V4的getSupportFragmentManager。
MyDialogFragment 的layout中需要使用自己定义的seekbar,如下:
"@+id/seekbar1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/view1" app:cellMode="number" app:lineColorEdge="@color/silery" app:lineColorSelected="@color/main_top" app:markTextArray="@array/markArray" app:seekBarMode="single" app:textPadding="15dp" app:textSize="@dimen/text14" app:textColor="@color/login_text" app:seekBarResId="@drawable/seekbar_thumb" /> </RelativeLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
该控件上的属性封装在attrs.xml中:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="RangeSeekBar"> <attr name="max" format="float"/> <attr name="min" format="float"/> <attr name="reserve" format="float"/> <attr name="cells" format="integer"/> <attr name="hideProgressHint" format="boolean"/> <attr name="lineColorSelected" format="color"/> <attr name="lineColorEdge" format="color"/> <attr name="thumbPrimaryColor" format="color"/> <attr name="thumbSecondaryColor" format="color"/> <attr name="markTextArray" format="reference"/> <attr name="seekBarResId" format="reference"/> <attr name="progressHintResId" format="reference"/> <attr name="textPadding" format="dimension" /> <attr name="textSize" format="dimension" /> <attr name="textColor" format="color" /> <attr name="hintBGHeight" format="dimension" /> <attr name="hintBGWith" format="dimension" /> <attr name="hintBGPadding" format="dimension" /> <attr name="seekBarHeight" format="dimension"/> <attr name="thumbSize" format="dimension"/> <attr name="cellMode" format="enum"> <enum name="number" value="0"/> <enum name="other" value="1"/> attr> <attr name="seekBarMode" format="enum"> <enum name="single" value="1"/> <enum name="range" value="2"/> attr> declare-styleable>resources>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
这边要注意progressHintResId属性,设置刻度提示背景必须使用.9的图片。
另一个跳转的activity页面我就不贴代码了,逻辑很简单,把输入的数字封装成数组,存入SP中,然后你每次弹出拖动条对话框,它都会去判断缓存中是否有值。
好了,今天先分享这个,感谢!
更多相关文章
- 三分钟学会缓存工具DiskLruCache
- android UI 优化系列之 创建RGB565的缓存
- Android缓存机制——一般存储实现
- 用Gson和SharedPreferences轻松构建android本地数据缓存
- 拖动ListView时背景出现黑色的解决办法!
- android实现拖动效果
- android ScrollView--Linearlayout可以上下拖动
- android缓存机制