当前位置: 首页 > news >正文

c#进度条刻度_自定义滑动刻度进度条

这次来弄的是自定义view的滑动进度条,继承于AppCompatSeekBar的基础上进行二次开发。先看效果图

test.gif

做到以上的效果图,就可以知道,两个模式,1:就是常用的seekbar模式,然后只不过安装自己的要求改了下滑动块而已,不多说,2:就是带有刻度点的seekbar模式,并且带有粘性数值处理,实现滑到刻度周边滑块自动吸引过去的效果。

重点说下第二种模式的,拆分下工作点:因为继承的是SeekBar,所以线和滑块我们就不用再处理了,只需要通过代码块去控制线的颜色和滑动块的背景就OK,还有就是根据数值在线上绘制相应的点。说白了就是重要点。

首先,定义相应的自定义属性,额,没办法,上头要求,所以规范点

新建一个bar_attrs.xml文件

然后就是代码中取得相应的属性值和设置默认值

TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SegmentBar);

maxLength = typedArray.getInteger(R.styleable.SegmentBar_max_length,100);

node = typedArray.getInteger(R.styleable.SegmentBar_node,0);

blockBg = typedArray.getResourceId(R.styleable.SegmentBar_block_bg,R.drawable.bar_back);

spotColor = typedArray.getResourceId(R.styleable.SegmentBar_spot_color,R.color.bar_point);

type = typedArray.getInteger(R.styleable.SegmentBar_bar_type,0);

lineColor = typedArray.getResourceId(R.styleable.SegmentBar_line_color,R.color.bar_line);

lineBg = typedArray.getResourceId(R.styleable.SegmentBar_line_bg,R.color.bar_line_bg);

checkItem = typedArray.getInteger(R.styleable.SegmentBar_check_item,1);

spotSize = typedArray.getInteger(R.styleable.SegmentBar_spot_size,15);

lineColor = ContextCompat.getColor(getContext(),lineColor);

lineBg = ContextCompat.getColor(getContext(),lineBg);

spotColor = ContextCompat.getColor(getContext(),spotColor);

typedArray.recycle();

initColor();

然后修改seekbar的线的颜色和滑动块的属性,通过代码定义一个Drawable属性来进行处理

public void initColor(){

this.setMax(maxLength);

this.setProgressDrawable(ContextCompat.getDrawable(getContext(),

R.drawable.bar_background));

/*Drawable thumbDraw = zoomDrawable(),2,2);*/

this.setThumb(ContextCompat.getDrawable(getContext(),

blockBg));

Rect bounds = this.getProgressDrawable().getBounds();

Drawable[] drawables = new Drawable[3];

drawables[0] = new PaintDrawable(lineBg);

drawables[2] = new ClipDrawable(new PaintDrawable(lineColor),Gravity.LEFT,ClipDrawable.HORIZONTAL);

drawables[1] = new ClipDrawable(new PaintDrawable(lineBg),Gravity.LEFT,ClipDrawable.HORIZONTAL);

LayerDrawable layerDrawable1 = new LayerDrawable(drawables);

this.setProgressDrawable(layerDrawable1);

this.getProgressDrawable().setBounds(bounds);

if (type == DEFAULT){

this.setProgress(getProgress()-1);

this.setProgress(getProgress());

}else {

int tmp = maxLength / (node+1);

int pro = checkItem * tmp;

if (checkItem == 0){

this.setProgress(1);

this.setProgress(0);

}else if (checkItem == node){

this.setProgress(maxLength-1);

this.setProgress(maxLength);

}else {

this.setProgress(pro-1);

this.setProgress(pro);

}

}

invalidate();

}

然后就是在onDraw里面绘制点

绘制点之前,需要获取几个数据点,1、seekbar的线的x,y轴,和点的xy轴。

线xy轴可以就是view的高度的对半点就是y轴的点,x轴的起始点一般就是0和view的宽度

至于点的话,可以通过线的长度/点的数量(得到平均刻度值)然后乘以相应的点的位置数量值就是得到了各个点的相应的x轴坐标,拿到了相应的xy轴,就可以绘制相应的点了

/**

* 在刻度模式下,进行绘制刻度点

* @param canvas

*/

@Override

protected synchronized void onDraw(Canvas canvas) {

float startX = 0 ;

float startY ;

float stopX ;

float stopY ;

if (type == SCALE){

//间隔宽度

int nodeWidth = 0;

if (node >= 1){

nodeWidth = (viewWidth-mPaddingLeft-mPaddingRight)/(node+1);

}

if (!isActtonUp){

checkItem = this.getProgress()/(maxLength / (node+1));

}

for (int i = 0;i <= (node+1);i++){

if (i == checkItem){

//正在处于的刻度点

if (isActtonUp){

linePaint.setColor(tran);

}else {

linePaint.setColor(lineColor);

}

}else if (i < checkItem){

//已经划过的刻度点

linePaint.setColor(lineColor);

}else {

//未划过的刻度点

linePaint.setColor(spotColor);

}

stopX = mPaddingLeft+(nodeWidth*i);

startX = stopX;

canvas.drawCircle(startX,getMeasuredHeight()/2,spotSize,linePaint);

}

}

super.onDraw(canvas);

}

做好以上的处理,基本的view的操作就OK了,但是呢,体验感不是很ok,就是没有滑动块的粘性处理。这可不行,所以弄下粘性处理吧,让滑动块滑到点的附近,根据距离点的值来进行吸引滑动块,这个可以在 onTouchEvent里面进行事件监听和拦截,当用户的手指离开屏幕时,获取当前滑块的位置,对比左右点的相差距离,决定滑动时向左点自动滑动还是向右点自动滑动

@Override

public boolean onTouchEvent(MotionEvent event) {

if(event.getAction() == MotionEvent.ACTION_UP) {

isActtonUp = true;

if (type == SCALE){

//粘性处理,通过滑动的数值计算出最近的点

int tmp = maxLength / (node+1);

int checkPro = getProgress();

int tmpLength = checkItem*tmp-checkPro;

if (tmpLength < 0){

if (Math.abs(tmpLength) < ( tmp /2)){

setProgress(checkItem*tmp);

}else {

int t = (Math.abs(tmpLength)+( tmp /2))/tmp;

if (t > 1){

checkItem += t;

}else {

checkItem += 1;

}

setProgress(checkItem*tmp);

}

}else {

if (tmpLength < ( tmp /2)){

setProgress(checkItem*tmp);

}else {

int t = (Math.abs(tmpLength)+( tmp /2))/tmp;

if (t > 1){

checkItem -= t;

}else {

checkItem -= 1;

}

setProgress(checkItem*tmp);

}

}

invalidate();

if (onItemCheckBarListener != null){

onItemCheckBarListener.itemCheckBarListener(this);

}

return true;

}

} else if (event.getAction() == MotionEvent.ACTION_DOWN) {

isActtonUp = false;

}

return super.onTouchEvent(event);

}

注意的一点是,在监听到用户手势离开屏幕的事件后,得消耗此事件,别让此事件分发继续下去,不然,seekbar则会重新绘制,覆盖以上的效果,在消耗的此事件之后,seekbar的滑动停止监听事件也就无效了,到时候我们就自己最佳一个接口,然使用者可以随时拿到停止滑动的线的数值

public interface OnItemCheckBarListener {

void itemCheckBarListener(SegmentBar segmentBar);

}

private OnItemCheckBarListener onItemCheckBarListener;

public void setOnItemCheckBarListener(OnItemCheckBarListener onItemCheckBarListener){

this.onItemCheckBarListener = onItemCheckBarListener;

}

嗯,以上就是达到效果图的效果了

完整代码贴出:

/*

*

* 自定义滑动进度条

* Created by caisongliang on 2019/7/24 14:29

*/

public class SegmentBar extends AppCompatSeekBar {

private static final int DEFAULT = 0;//默认模式

private static final int SCALE = 1;//有刻度模式

private int maxLength = 100;

private int minLength = 0;

//滑块背景

private int blockBg = 0;

//刻度

private int node = 4;

private int type = DEFAULT;

private int checkItem = 0;

//刻度的点的颜色

private int spotColor = 0 ;

//线的颜色

private int lineColor = 0;

//刻度点的大小

private int spotSize = 15;

private int lineBg = 0;

private int maxHeight = 0;

public SegmentBar(Context context) {

super(context);

initView(null);

}

public SegmentBar(Context context, AttributeSet attrs) {

super(context, attrs);

initView(attrs);

}

public int getMaxLength() {

return maxLength;

}

public void setMaxLength(int maxLength) {

this.maxLength = maxLength;

this.setProgress(maxLength);

}

public int getBlockBg() {

return blockBg;

}

public void setBlockBg(int blockBg) {

this.blockBg = blockBg;

}

public int getNode() {

return node;

}

public void setNode(int node) {

this.node = node;

initColor();

}

public int getType() {

return type;

}

public void setType(int type) {

this.type = type;

}

public int getSpotColor() {

return spotColor;

}

public void setSpotColor(int spotColor) {

this.spotColor = ContextCompat.getColor(getContext(),spotColor);

invalidate();

}

public int getLineColor() {

return lineColor;

}

public void setLineColor(int lineColor) {

this.lineColor = ContextCompat.getColor(getContext(),lineColor);

initColor();

}

public int getSpotSize() {

return spotSize;

}

public void setSpotSize(int spotSize) {

this.spotSize = spotSize;

invalidate();

}

public int getLineBg() {

return lineBg;

}

public void setLineBg(int lineBg) {

this.lineBg = ContextCompat.getColor(getContext(),lineBg);

initColor();

}

private boolean isActtonUp = false;

@Override

public boolean onTouchEvent(MotionEvent event) {

if(event.getAction() == MotionEvent.ACTION_UP) {

isActtonUp = true;

if (type == SCALE){

//粘性处理,通过滑动的数值计算出最近的点

int tmp = maxLength / (node+1);

int checkPro = getProgress();

int tmpLength = checkItem*tmp-checkPro;

if (tmpLength < 0){

if (Math.abs(tmpLength) < ( tmp /2)){

setProgress(checkItem*tmp);

}else {

int t = (Math.abs(tmpLength)+( tmp /2))/tmp;

if (t > 1){

checkItem += t;

}else {

checkItem += 1;

}

setProgress(checkItem*tmp);

}

}else {

if (tmpLength < ( tmp /2)){

setProgress(checkItem*tmp);

}else {

int t = (Math.abs(tmpLength)+( tmp /2))/tmp;

if (t > 1){

checkItem -= t;

}else {

checkItem -= 1;

}

setProgress(checkItem*tmp);

}

}

invalidate();

if (onItemCheckBarListener != null){

onItemCheckBarListener.itemCheckBarListener(this);

}

return true;

}

} else if (event.getAction() == MotionEvent.ACTION_DOWN) {

isActtonUp = false;

}

return super.onTouchEvent(event);

}

public interface OnItemCheckBarListener {

void itemCheckBarListener(SegmentBar segmentBar);

}

private OnItemCheckBarListener onItemCheckBarListener;

public void setOnItemCheckBarListener(OnItemCheckBarListener onItemCheckBarListener){

this.onItemCheckBarListener = onItemCheckBarListener;

}

public SegmentBar(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

initView(attrs);

}

public int getCheckItem() {

return checkItem;

}

public void setCheckItem(int checkItem) {

this.checkItem = checkItem;

}

private void initView(AttributeSet attrs) {

TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SegmentBar);

maxLength = typedArray.getInteger(R.styleable.SegmentBar_max_length,100);

node = typedArray.getInteger(R.styleable.SegmentBar_node,0);

blockBg = typedArray.getResourceId(R.styleable.SegmentBar_block_bg,R.drawable.bar_back);

spotColor = typedArray.getResourceId(R.styleable.SegmentBar_spot_color,R.color.bar_point);

type = typedArray.getInteger(R.styleable.SegmentBar_bar_type,0);

lineColor = typedArray.getResourceId(R.styleable.SegmentBar_line_color,R.color.bar_line);

lineBg = typedArray.getResourceId(R.styleable.SegmentBar_line_bg,R.color.bar_line_bg);

checkItem = typedArray.getInteger(R.styleable.SegmentBar_check_item,1);

spotSize = typedArray.getInteger(R.styleable.SegmentBar_spot_size,15);

lineColor = ContextCompat.getColor(getContext(),lineColor);

lineBg = ContextCompat.getColor(getContext(),lineBg);

spotColor = ContextCompat.getColor(getContext(),spotColor);

typedArray.recycle();

initColor();

}

public void initColor(){

this.setMax(maxLength);

this.setProgressDrawable(ContextCompat.getDrawable(getContext(),

R.drawable.bar_background));

/*Drawable thumbDraw = zoomDrawable(),2,2);*/

this.setThumb(ContextCompat.getDrawable(getContext(),

blockBg));

Rect bounds = this.getProgressDrawable().getBounds();

Drawable[] drawables = new Drawable[3];

drawables[0] = new PaintDrawable(lineBg);

drawables[2] = new ClipDrawable(new PaintDrawable(lineColor),Gravity.LEFT,ClipDrawable.HORIZONTAL);

drawables[1] = new ClipDrawable(new PaintDrawable(lineBg),Gravity.LEFT,ClipDrawable.HORIZONTAL);

LayerDrawable layerDrawable1 = new LayerDrawable(drawables);

this.setProgressDrawable(layerDrawable1);

this.getProgressDrawable().setBounds(bounds);

if (type == DEFAULT){

this.setProgress(getProgress()-1);

this.setProgress(getProgress());

}else {

int tmp = maxLength / (node+1);

int pro = checkItem * tmp;

if (checkItem == 0){

this.setProgress(1);

this.setProgress(0);

}else if (checkItem == node){

this.setProgress(maxLength-1);

this.setProgress(maxLength);

}else {

this.setProgress(pro-1);

this.setProgress(pro);

}

}

invalidate();

}

private Drawable zoomDrawable(Drawable drawable, int w, int h) {

int width = drawable.getIntrinsicWidth();

int height = drawable.getIntrinsicHeight();

Bitmap oldbmp = drawableToBitmap(drawable);

Matrix matrix = new Matrix();

float scaleWidth = ((float) w / width);

float scaleHeight = ((float) h / height);

matrix.postScale(scaleWidth, scaleHeight);

Bitmap newbmp = BitmapUtil.scaleImage(oldbmp,w,h);

return new BitmapDrawable(null, newbmp);

}

private Bitmap drawableToBitmap(Drawable drawable) {

int width = drawable.getIntrinsicWidth();

int height = drawable.getIntrinsicHeight();

Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888

: Bitmap.Config.RGB_565;

Bitmap bitmap = Bitmap.createBitmap(width, height, config);

Canvas canvas = new Canvas(bitmap);

drawable.setBounds(0, 0, width, height);

drawable.draw(canvas);

return bitmap;

}

private int viewWidth = 0;

@Override

protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

viewWidth = getMeasuredWidth();

initSegmentBar();

}

private int mPaddingLeft;

private int mPaddingRight;

private Context mContext;

public void initSegmentBar(){

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {

mPaddingLeft = getPaddingLeft();

mPaddingRight = getPaddingRight();

} else {

mPaddingLeft = getPaddingStart();

mPaddingRight = getPaddingEnd();

}

}

@Override

public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {

super.setOnSeekBarChangeListener(l);

}

Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

int tran = getContext().getResources().getColor(R.color.bar_tran);

/**

* 在刻度模式下,进行绘制刻度点

* @param canvas

*/

@Override

protected synchronized void onDraw(Canvas canvas) {

float startX = 0 ;

float startY ;

float stopX ;

float stopY ;

if (type == SCALE){

//间隔宽度

int nodeWidth = 0;

if (node >= 1){

nodeWidth = (viewWidth-mPaddingLeft-mPaddingRight)/(node+1);

}

if (!isActtonUp){

checkItem = this.getProgress()/(maxLength / (node+1));

}

for (int i = 0;i <= (node+1);i++){

if (i == checkItem){

//正在处于的刻度点

if (isActtonUp){

linePaint.setColor(tran);

}else {

linePaint.setColor(lineColor);

}

}else if (i < checkItem){

//已经划过的刻度点

linePaint.setColor(lineColor);

}else {

//未划过的刻度点

linePaint.setColor(spotColor);

}

stopX = mPaddingLeft+(nodeWidth*i);

startX = stopX;

canvas.drawCircle(startX,getMeasuredHeight()/2,spotSize,linePaint);

}

}

super.onDraw(canvas);

}

}

------------------------------------转发请声明出处-----------------------------------------------


http://www.taodudu.cc/news/show-1944798.html

相关文章:

  • 【physx/wasm】在physx中添加自定义接口并重新编译wasm
  • excel---常用操作
  • Lora训练Windows[笔记]
  • linux基础指令讲解(ls、pwd、cd、touch、mkdir)
  • InnoDB 事务处理机制
  • 启明云端ESP32 C3 模组WT32C3通过 MQTT 连接 AWS
  • js ajax进度条,js 异步处理进度条
  • Android自定义gif进度条,Android自定义view-圆形百分比进度条效果
  • 可线性渐变的环形进度条的实现探究
  • android 消息循环滚动条,Android 电池电量进度条,上下滚动图片的进度条(battery)...
  • gif透明背景动画_PS教程:把静态照片做成GIF放大动画效果
  • vc++中实现进度条
  • 关于form提交后展示遮罩及显示进度条gif问题
  • 小程序影藏溢出的gif_动图制作方法,1分钟教会你如何制作gif表情包!
  • 自动生成动态gif的一个网站(进度条)
  • 进度条制作-GIF动画
  • 275页PDF:《编写高质量代码:改善Python程序的91个建议》
  • 【读书心得】 高质量C++/C编程指南-林锐
  • 高质量图片缩略图生成(编程笔记)
  • 极限编程
  • 全球编程厉害的14位大佬
  • 概率编程实战
  • 《高质量C++/C编程指南(林锐)》学习笔记
  • 高质量电子书分享
  • 构建高质量的前端工程完全指南
  • C#网络编程(Socket编程)
  • 改善代码质量的编程规范
  • 高质量程序好文分享之王垠《编程的智慧》
  • 高质量的C/C++编程(2)----程序员必看系列
  • 高质量计算机学习网站
  • 林锐的《高质量编程》学习笔记——内存分配方式
  • c语言是高级编程语言吗,C语言是高级编程语言吗?
  • 推荐一些高质量的自学网站
  • 《高质量C/C++编程》读书笔记
  • 高质量编程之编译警告级别
  • 高质量C编程00-汇总