自定义View实现点值选择效果(二)
来源:互联网 发布:新时代证券交易软件 编辑:程序博客网 时间:2024/05/14 19:25
在前几天写的博客中,通过使用自定义View画了一个可以实现点值选择的seekBar,但是在实际使用中还是会有一点问题,在点击处于连个值之间时,如何进行选择等。本篇博客对上次的自定义View进行了重新编码,最新的效果如下:
只是对上次自定义的View进行了一些细节方面的优化,在这里就不详细叙述了,看一下具体实现代码:
import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * Created by Administrator on 2017/8/27 0027. */public class LevelSeekBar extends View { private int mTextSize = 12; private String[] labels = new String[]{"L1","L2","L3","L4","L5"}; private float mPrewidth; private int mWidth; private int mHeight; private int mDotSize; private Paint mPaint; private int mThumbnailSize; private int count = 4; private Bitmap mBasicLine; private int mLine_position_y; private int mLine_position_x; private int mDensity = 2; private float progress = 50; private float mMaxProgress = 100.0f; private float mThumbnail_position_x; private int mLineWidth; private int mLineStroke = 4; private OnLevelSeekBarChangeListener mListener; private boolean mMustBeSelected = true; private int mPreProgress; public interface OnLevelSeekBarChangeListener{ void onStartChanged(int progress); void onProgressChanged(int process); void onEndProgressChanged(int progress); } public LevelSeekBar(Context context) { super(context); init(); } public LevelSeekBar(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public LevelSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public LevelSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } private void init(){ mTextSize = 12*mDensity; mDotSize = 8*mDensity; mThumbnailSize = 16*mDensity; mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setFilterBitmap(true); mPaint.setColor(Color.RED); count = labels.length-1; mLine_position_x = mThumbnailSize; mLineStroke = 4*mDensity; mPreProgress = (int)(mMaxProgress/count); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mWidth = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); mHeight = height>calculateHeight()?height:calculateHeight(); mPrewidth = (mWidth-2*mThumbnailSize)/count; mLine_position_y = mHeight-(mThumbnailSize); mLineWidth = mWidth-mThumbnailSize*2; mBasicLine = getBasicLine(mWidth,mHeight); setMeasuredDimension(mWidth,mHeight); } private int calculateHeight(){ int height = mThumbnailSize*2+mTextSize+15; return height; } @Override protected void onDraw(Canvas canvas) { mBasicLine = getBasicLine(mWidth,mHeight); canvas.drawBitmap(mBasicLine,0,0,mPaint); mThumbnail_position_x = (progress/mMaxProgress)*mLineWidth+mThumbnailSize; canvas.drawCircle(mThumbnail_position_x,mLine_position_y,mThumbnailSize,mPaint); } private Bitmap getBasicLine(int width,int height){ Bitmap b = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888); Canvas c = new Canvas(b); Paint p = new Paint(); p.setColor(Color.GRAY); p.setStrokeWidth(mLineStroke); p.setTextSize(mTextSize); p.setFakeBoldText(true); c.drawLine(mLine_position_x,mLine_position_y,mWidth-mLine_position_x,mLine_position_y,p); for(int i = 0;i<labels.length;i++){ c.drawCircle(mLine_position_x+mPrewidth*i,mLine_position_y,mDotSize,p); } for(int i = 0;i<labels.length;i++){ Rect r = new Rect(); p.getTextBounds(labels[i],0,labels[i].length(),r); float mPos = mLine_position_x+mPrewidth*i; Log.i("zyq","progress :1111111 = "+progress); if(Math.abs(progress - mPreProgress*i)<1){ p.setColor(Color.RED); }else{ p.setColor(Color.GRAY); } c.drawText(labels[i],mPos-r.width()/2,mHeight-(2*mThumbnailSize+15),p); } p.setColor(Color.GRAY); return b; } @Override public boolean onTouchEvent(MotionEvent event) { float x ; float dest_x; switch (event.getAction()){ case MotionEvent.ACTION_DOWN: x = event.getX()-getPaddingLeft()-mThumbnailSize; if(mMustBeSelected){ dest_x = ((int)((x+mPrewidth/2)/mPrewidth))*mPrewidth; x = dest_x; } progress = ((x/mLineWidth)*mMaxProgress); invalidate(); if(mListener != null){ mListener.onStartChanged((int)progress); } break; case MotionEvent.ACTION_MOVE: x = event.getX()-getPaddingLeft()-mThumbnailSize; progress = ((x/mLineWidth)*mMaxProgress); invalidate(); if(mListener != null){ mListener.onProgressChanged((int)progress); } break; case MotionEvent.ACTION_UP: x = event.getX()-getPaddingLeft()-mThumbnailSize; if(mMustBeSelected){ dest_x = ((int)((x+mPrewidth/2)/mPrewidth))*mPrewidth; x = dest_x; } progress = ((x/mLineWidth)*mMaxProgress); invalidate(); if(mListener != null){ mListener.onEndProgressChanged((int)progress); } break; } return true; } public void setLevelSeekBarChangeListener(OnLevelSeekBarChangeListener l){ mListener = l; } public void setCanSelected(boolean selectable){ mMustBeSelected = selectable; if(mMustBeSelected){ float x = (progress*mLineWidth/mMaxProgress); float des_x = ((int)((x+mPrewidth/2)/mPrewidth))*mPrewidth; progress = ((des_x/mLineWidth)*mMaxProgress); Log.i("zyq","progress = "+progress); } invalidate(); } public void setLabels(String[] infos){ labels = infos; init(); mPrewidth = (mWidth-2*mThumbnailSize)/count; if(mMustBeSelected){ float x = (progress*mLineWidth/mMaxProgress); float des_x = ((int)((x+mPrewidth/2)/mPrewidth))*mPrewidth; progress = ((des_x/mLineWidth)*mMaxProgress); Log.i("zyq","progress = "+progress); } invalidate(); } public boolean getSelectable() { return mMustBeSelected; }}
在这里有一个地方需要注意下,在刚开始的时候,labels中的字符串数量为5,可以把seekBar的进度条分为四份,此时得到的每段长度极有可能是整数,在计算过程中,即使出现数据精度的丢失,那么丢失的数据在UI上也体现的不怎么明显,但是一旦要把seekBar分成奇数份,数据就会出现丢失严重的情况,在UI上反应就是Thumbnail绘制的位置不准确,特别是在点值选择的情况下,Thumbnail无法在准确的位置绘制,所以在某些变量的类型使用时需要考虑到底是使用int类型还是float类型。
其他的就没有什么好说的了,关于这个自定义的View还有很多需要优化的地方,在这里大神就不要喷我了,有兴趣的朋友可以关注我一下,有什么问题大家可以相互讨论,谢谢查阅本篇博客!!!
阅读全文
0 0
- 自定义View实现点值选择效果(二)
- 自定义View实现SeekBar点值选择效果(一)
- 自定义view实现《最美有物》点赞效果
- Android 自定义View 实现QQ红点拖动删除效果
- 自定义View(二)橡皮擦效果
- Android自定义View——从零开始实现书籍翻页效果(二)
- 自定义View 实现字母选择
- 自定义View实现刮刮卡效果
- 自定义View实现SwichButton效果
- 自定义 View 实现钟表效果
- 自定义View实现索引效果
- 自定义view实现炸弹效果
- 自定义View-仿即刻点赞效果
- 自定义View学习二(Banner实现)
- Android 自定义View(二),点,线的绘制
- # Android 自定义View(二) 下雨效果
- 自定义view实现水波纹效果(已优化)
- 自定义View(四) Graphics2D 实现动态效果
- iOS Swift Crash的捕获
- uva 1476 Error Curves(三分)
- Scikit-Learn框架
- TCP/IP三次握手详解
- Git学习笔记
- 自定义View实现点值选择效果(二)
- P1017 进制转换
- iOS第三方库汇总
- 详解ios之ARkit为何碾压对手(一)
- 2. Add Two Numbers
- android studio 环境配置
- VS2013中MSComm通讯控件的配置
- Spark SQL基础学习【三】以json的方式存储
- 51Nod1574(新姿势:使序列有序的最小交换次数)