seekBar的分段显示
来源:互联网 发布:centos 设备管理器 编辑:程序博客网 时间:2024/05/22 05:13
自定义seekBar的分段显示,这个以后也会用的到。下面的这个代码是自己在网上搜的(源链接:http://blog.csdn.net/lyj1005353553/article/details/77099578),然后自己把需要添加注释的代码都添加了注释,方便大家理解,自己也做了一些小改动现在可以直接拿去用,用的时候只需要在XML文件和代码中写几句代码就可以了。
首先需要在attr文件中添加
<declare-styleable name="RangeSliderView"> <attr name="rangeCount" format="integer"/> <attr name="filledColor" format="color"/> <attr name="emptyColor" format="color"/> <attr name="barHeightPercent" format="float"/> <attr name="circleRadiusPercent" format="float"/> <attr name="sliderRadiusPercent" format="float"/></declare-styleable>
- XML文件中配置属性,需要在根布局中声明xmlns:rsv=”http://schemas.android.com/apk/res-auto”
rsv:emptyColor=”#自定义” //一级背景颜色
rsv:filledColor=”#自定义” //二级背景颜色 Activity中
rangeSliderBar = (RangeSliderBar) findViewById(R.id.rsv_custom);
rangeSliderBar.setRangeCount(mDatas.length); //设置分段的个数
rangeSliderBar.setContext(this);
rangeSliderBar.setNums(mDatas); //设置分段的数据
//实现的接口
rangeSliderBar.setOnSelectRangeBarListener(new RangeSliderBar.OnSelectRangeBarListener() {
@Override
public void OnSelectRange(int rangeNum) {
Toast.makeText(MainActivity.this,
“我现在的位置是” + rangeNum,
Toast.LENGTH_SHORT).show();
}
});自定义控件完整代码:
public class RangeSliderBar extends View { private static final String TAG = "RangeSliderBar"; private Context context; /** 画笔的默认的宽度 */ private static final int DEFAULT_PAINT_STROKE_WIDTH = 8; /** seekBar的默认二级背景 */ private static final int DEFAULT_FILLED_COLOR = Color.parseColor("#FFA500"); /** seekBar的默认一级背景 */ private static final int DEFAULT_EMPTY_COLOR = Color.parseColor("#ff0000"); /** * rangebar粗细 */ private static final float DEFAULT_BAR_HEIGHT_PERCENT = 0.10f; /** * 设置自定义seekBar的长度 * 这个长度要与传进来数组的长度一致 */ private static final int DEFAULT_RANGE_COUNT = 6; /** * rangebar高度 */ private static final int DEFAULT_HEIGHT_IN_DP = 90; /** * seekBar的画笔 */ protected Paint paint; /** * 分段显示的画笔 */ protected Paint mPaint; /** * 当前的索引位置 */ private int currentIndex; /** * 当前的X坐标 */ private float currentSlidingX; /** * 当前的Y坐标 */ private float currentSlidingY; /** * 具体分段显示的数值 */ private int[] circlePositions; /** * 分段显示的距离数组 */ private float[] circlePositions2 = new float[DEFAULT_RANGE_COUNT]; /** * 填充颜色 */ private int filledColor = DEFAULT_FILLED_COLOR; /** * 空白颜色 */ private int emptyColor = DEFAULT_EMPTY_COLOR; private float barHeightPercent = DEFAULT_BAR_HEIGHT_PERCENT; /** * 分段显示的数量 */ private int rangeCount = DEFAULT_RANGE_COUNT; private int barHeight, locationY; private float downX; private float downY; /** * seekBar滑块的图片 */ private Bitmap bitmap_point; private int layoutHeight;// private boolean mPopupStyle;//是否显示pop private PopupWindow mPopup; View popView; TextView tv; int indexNum; //位置数值 private int[] mPosition; public RangeSliderBar(Context context) { this(context, null); this.context = context; initPop(); } public RangeSliderBar(Context context, AttributeSet attrs) { this(context, attrs, -1); this.context = context; initPop(); } public void setContext(Context context) { this.context = context; } public void setShowPopText(String str) { tv.setText(str); } void initPop() { mPosition = new int[2];// popView = LayoutInflater.from(context).inflate(R.layout.seekbar_pop, null);// mPopup = new PopupWindow(popView, popView.getWidth(), popView.getHeight(), true);// tv = (TextView) popView.findViewById(R.id.tv_showtxt); } public RangeSliderBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //自定义属性 if (attrs != null) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable .RangeSliderView); TypedArray sa = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.layout_height}); try { layoutHeight = sa.getLayoutDimension( 0, 0); rangeCount = a.getInt( R.styleable.RangeSliderView_rangeCount, DEFAULT_RANGE_COUNT); filledColor = a.getColor( R.styleable.RangeSliderView_filledColor, DEFAULT_FILLED_COLOR); emptyColor = a.getColor( R.styleable.RangeSliderView_emptyColor, DEFAULT_EMPTY_COLOR); barHeightPercent = a.getFloat( R.styleable.RangeSliderView_barHeightPercent, DEFAULT_BAR_HEIGHT_PERCENT); barHeightPercent = a.getFloat( R.styleable.RangeSliderView_barHeightPercent, DEFAULT_BAR_HEIGHT_PERCENT); } finally { a.recycle(); sa.recycle(); } } setBarHeightPercent(barHeightPercent); setRangeCount(rangeCount); paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStrokeWidth(DEFAULT_PAINT_STROKE_WIDTH); paint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.WHITE); mPaint.setTextSize(30);// mPaint.setAntiAlias(true); //自定义控件UI的监听器 getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver .OnPreDrawListener() { @Override public boolean onPreDraw() { getViewTreeObserver().removeOnPreDrawListener(this); // Update radius after we got new height updateRadius(getHeight()); // Compute drawing position again preComputeDrawingPosition(); // Ready to draw now return true; } }); //设置默认选中第二个位置 currentIndex = 2;// setShowPopText(circlePositions[currentIndex] + ""); } private void updateRadius(int height) { barHeight = (int) (height * barHeightPercent); locationY = barHeight + DEFAULT_HEIGHT_IN_DP; //Y位置 } /** * 设置分段显示的数据 */ public void setNums(int[] nums) { this.circlePositions = nums; } /** * 设置分段显示的长度,必须与数据的大小一致! * @param rangeCount */ public void setRangeCount(int rangeCount) { if (rangeCount < 2) { throw new IllegalArgumentException("rangeCount must be >= 2"); } this.rangeCount = rangeCount; } public void setBarHeightPercent(float percent) { if (percent <= 0.0 || percent > 1.0) { throw new IllegalArgumentException("Bar height percent must be in" + " (0, 1]"); } this.barHeightPercent = percent; } /** * Perform all the calculation before drawing, should only run once * 计算各分段显示的位置,这里采取均匀分开! */ private void preComputeDrawingPosition() { int w = getWidthWithPadding(); int h = getHeightWithPadding(); initPop(); /** Space between each circle */ int spacing = w / rangeCount; /** Center vertical */ int y = getPaddingTop() + h / 2; currentSlidingY = y; int x = getPaddingLeft() + (spacing / 2); /** Store the position of each circle index */ for (int i = 0; i < circlePositions.length; ++i) { circlePositions2[i] = x; Log.e("--------->", "circlePositions[i]==" + circlePositions[i]); if (i == currentIndex) { currentSlidingX = x; } //这里采用均匀距离,若是想根据值来显示距离,这里需要自己修改! x += spacing; } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight (heightMeasureSpec)); } /** * Measures height according to the passed measure spec * * @param measureSpec int measure spec to use * @return int pixel size */ private int measureHeight(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); int result; if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { final int height; if (layoutHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { height = dpToPx(getContext(), DEFAULT_HEIGHT_IN_DP); } else if (layoutHeight == ViewGroup.LayoutParams.MATCH_PARENT) { height = getMeasuredHeight(); } else { height = layoutHeight; } result = height + getPaddingTop() + getPaddingBottom() + (2 * DEFAULT_PAINT_STROKE_WIDTH); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } /** * Measures width according to the passed measure spec * * @param measureSpec int measure spec to use * @return int pixel size */ private int measureWidth(int measureSpec) { int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); int result; if (specMode == MeasureSpec.EXACTLY) { result = specSize; } else { result = specSize + getPaddingLeft() + getPaddingRight() + (2 * DEFAULT_PAINT_STROKE_WIDTH); if (specMode == MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } } return result; } private void updateCurrentIndex() { float min = Float.MAX_VALUE; int j = 0; /** Find the closest to x */ for (int i = 0; i < rangeCount; ++i) { float dx = Math.abs(currentSlidingX - circlePositions2[i]); if (dx < min) { min = dx; j = i; } } currentIndex = j; /** Correct position */ currentSlidingX = circlePositions2[j]; Log.e("updateCurrentIndex==", "currentSlidingX=" + currentSlidingX); downX = currentSlidingX; downY = currentSlidingY; invalidate(); } @Override public boolean onTouchEvent(MotionEvent event) { float y = event.getY(); float x = event.getX(); final int action = event.getActionMasked(); switch (action) { case MotionEvent.ACTION_DOWN: downX = x; downY = y; this.getLocationOnScreen(mPosition);// mPopup.showAsDropDown(this, (int) downX, -170 - bitmap_point.getHeight()); break; case MotionEvent.ACTION_MOVE: if (x >= circlePositions2[0] && x <= circlePositions2[rangeCount - 1]) { currentSlidingX = x; currentSlidingY = y; invalidate(); } break; case MotionEvent.ACTION_UP: currentSlidingX = x; currentSlidingY = y;// mPopup.dismiss(); updateCurrentIndex(); invalidate(); if (onSelectRangeBarListener != null) { int range = circlePositions[currentIndex];// setShowPopText(range + ""); onSelectRangeBarListener.OnSelectRange(range); } break; } return true; } private void drawDefaultCircle(Canvas canvas) { paint.setColor(emptyColor); int h = getHeightWithPadding(); int y = getPaddingTop() + (h >> 1); for (int i = 0; i < circlePositions.length; ++i) { //每个对应数字下画竖线 /** * 画线参数:startX,startY,endX,endY * 画文字参数:文字,起始坐标X,起始坐标Y */ canvas.drawLine(circlePositions2[i], y + barHeight + 5, circlePositions2[i], y + barHeight + 20, mPaint); canvas.drawText(circlePositions[i] + "s", circlePositions2[i] - 10, y + barHeight + 50, mPaint); } } private void drawSlidRangeCircle(Canvas canvas, int x0, int spc) { paint.setColor(filledColor); int h = getHeightWithPadding(); int y = getPaddingTop() + (h >> 1); for (int i = 0; i < circlePositions.length; ++i) { canvas.drawText(circlePositions[i] + "", circlePositions2[i] - 10, y + barHeight + 50, mPaint); } } /** * 画rangebar * * @param canvas * @param from * @param to * @param color */ private void drawBar(Canvas canvas, int from, int to, int color) { paint.setColor(color); int half = (barHeight >> 1); int y = getPaddingTop() + barHeight + DEFAULT_HEIGHT_IN_DP; //设置bar位置 /** * 画长方形 */// canvas.drawRect(from, y - half, to, y + half, paint); /** * 画圆角矩形 */// RectF oval3 = new RectF(from, y - half, to, y + half);// canvas.drawRoundRect(oval3, 3, 3, paint);//画圆角矩形 /** * 画线 */ canvas.drawLine(from, y, to, y, paint); } private int getViewWidth(View v) { int w = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); int h = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); v.measure(w, h); return v.getMeasuredWidth(); } private int getViewHeight(View v) { int w = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); int h = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); v.measure(w, h); return v.getMeasuredHeight(); } public void onDraw(Canvas canvas) { super.onDraw(canvas); int w = getWidthWithPadding(); int spacing = w / rangeCount; int border = (spacing >> 1); int x0 = getPaddingLeft() + border; if (mPopup != null) { try { this.getLocationOnScreen(mPosition); mPopup.update((int) downX, -170, getViewWidth(popView) , getViewHeight(popView)); } catch (Exception e) { } }// bitmap_point = BitmapFactory.decodeResource(getResources(), AppMgr.iDraw("dot_chart")); bitmap_point = BitmapFactory.decodeResource(getResources(), R.mipmap.seekbar_yelloe); /** Draw empty bar 画一级背景*/ drawBar(canvas, (int) circlePositions2[0], (int) circlePositions2[rangeCount - 1], emptyColor); /** Draw filled bar 画二级背景*/ drawBar(canvas, x0, (int) currentSlidingX, filledColor); int bitmap_pointHeight = bitmap_point.getHeight(); Log.e(TAG,bitmap_pointHeight+""); //56 //seekBar滑块的位置,这里根据自己的需要进行调整 //画移动背景图 canvas.drawBitmap(bitmap_point, (int) currentSlidingX - 30, x0 , null); /** Draw the selected range circle */ paint.setColor(filledColor); drawDefaultCircle(canvas);// drawSlidRangeCircle(canvas, (int) currentSlidingX, spacing); } public int getHeightWithPadding() { return getHeight() - getPaddingBottom() - getPaddingTop(); } public int getWidthWithPadding() { return getWidth() - getPaddingLeft() - getPaddingRight(); } @Override public Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState ss = new SavedState(superState); ss.saveIndex = this.currentIndex; return ss; } @Override public void onRestoreInstanceState(Parcelable state) { if (!(state instanceof SavedState)) { super.onRestoreInstanceState(state); return; } SavedState ss = (SavedState) state; super.onRestoreInstanceState(ss.getSuperState()); this.currentIndex = ss.saveIndex; } /** * 保存状态的类,横竖屏切换的时候用来保存切换之前的状态 */ static class SavedState extends BaseSavedState { int saveIndex; SavedState(Parcelable superState) { super(superState); } private SavedState(Parcel in) { super(in); this.saveIndex = in.readInt(); } @Override public void writeToParcel(Parcel out, int flags) { super.writeToParcel(out, flags); out.writeInt(this.saveIndex); } //required field that makes Parcelables from a Parcel 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]; } }; } /** * Helper method to convert dp to pixel * * @param context * @param dp * @return */ static int dpToPx(final Context context, final float dp) { return (int) (dp * context.getResources().getDisplayMetrics().density); } OnSelectRangeBarListener onSelectRangeBarListener; /** * 自定义接口,提供接口让外部实现处理自己的逻辑 */ public interface OnSelectRangeBarListener { /** * 实现接口需要实现的方法,这里的参数rangeNum就是seekBar滑动停止后的位置所对应的数据 */ void OnSelectRange(int rangeNum); } public void setOnSelectRangeBarListener(OnSelectRangeBarListener onSelectRangeBarListener) { this.onSelectRangeBarListener = onSelectRangeBarListener; }}
最后再次注明一下源链接:http://blog.csdn.net/lyj1005353553/article/details/77099578
- seekBar的分段显示
- SeekBar也玩分段
- 带百分比显示的seekbar
- 自定义SeekBar分段显示并填充数据pop显示当前选中位置
- 关于自定义SeekBar写法以及seekbar不显示的问题
- android ListView的分段显示、分页显示
- SeekBar,thumb不居中显示的解决办法
- SeekBar thumb不居中显示的解决办法
- 带数字显示的自定义SeekBar
- 一个带数字显示的SeekBar
- SeekBar,thumb不居中显示的解决办法
- android SeekBar thumb显示不全的原因
- xcode 函数查看的时候分段显示
- highcharts分段显示不通的颜色
- android ListView的分段显示、分页显示(附源码)
- 解决自定义seekbar和listview显示冲突的问题
- SeekBar,thumb和背景不居中显示的解决办法
- SeekBar中thumb的透明背景显示父布局颜色
- 【剑指offer】正则匹配
- Oracle insert 插入数据 加 where 条件
- Redis主从复制和集群配置
- Android客户端Push 透传与通知栏
- tomcat日志监控工具probe
- seekBar的分段显示
- BeanShell Sample与控制台交互
- Java保留两位小数问题
- Android 6.0 Reboot 流程源代码分析
- 关于递归
- java读取文件工具类
- JS追加当前时间
- CoordinatorLayout,协调者布局
- PAT 1043. Is It a Binary Search Tree (25) 建树