android 自定义 环形进度条
2015-11-09 19:17
405 查看
欢迎大家访问我的博客http://blog.csdn.net/mikejaps,专注于android
ios app 开发
其实这个控件很简单,继承View,在onDraw 中 绘制一个圆和一个圆弧即可,代码如下,对外暴露了一个设置进度的方法 ,难点主要是数学计算
效果图如下
ios app 开发
其实这个控件很简单,继承View,在onDraw 中 绘制一个圆和一个圆弧即可,代码如下,对外暴露了一个设置进度的方法 ,难点主要是数学计算
public class CircleView extends View{ private Paint mPaint; private int edgeMargin;//进度条与边界的距离 private int rotateRaduis;//圆形进度条的半径 private static final int mMaring = 25;//进度条与罗盘之间的距离 private static final String TAG = "com.example.android.view.MusicRotateView"; private Context mContext; private Point centPoint; private Paint Gpaint; private Paint pPaint; private RectF oval; private boolean isDraging;//是否可以拖动小球 private Point mRockBollPosition = new Point();//进度条上的小球位置 private int mRadius = 8; private int playedRadian;//进度条已经播放的角度 public MusicRotateView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; initValues(); init(); } private void initValues() { rotateRaduis = 3*getScreenWidth()/8; edgeMargin = getScreenWidth()/8; mPaint = new Paint();//画圆盘的画笔 mPaint.setAntiAlias(true); mPaint.setColor(Color.parseColor("#FFFFFF")); centPoint = new Point(rotateRaduis+edgeMargin, rotateRaduis+edgeMargin); Gpaint = new Paint();//画进度条背景 Gpaint.setColor(Color.GRAY); //设置圆环的颜色 Gpaint.setStyle(Paint.Style.STROKE); //设置空心 Gpaint.setStrokeWidth(8f); //设置圆环的宽度 Gpaint.setAntiAlias(true); //消除锯齿 pPaint = new Paint();//画进度条进度的画笔 pPaint.setColor(Color.RED); //设置圆环的颜色 pPaint.setStyle(Paint.Style.STROKE); //设置空心 pPaint.setStrokeWidth(8f); //设置圆环的宽度 pPaint.setAntiAlias(true); //消除锯齿 oval = new RectF((float)(centPoint.x-rotateRaduis),(float)(centPoint.y-rotateRaduis), (float)(centPoint.x+rotateRaduis),(float)(centPoint.y+rotateRaduis)); } private void init() { //InputStream is = getResources().openRawResource(R.drawable.img_record); //bgBitmap = BitmapFactory.decodeStream(is); //Matrix matrix = new Matrix(); //float scale = (float)rotateRaduis*2/(float)bgBitmap.getWidth(); //matrix.postScale(scale, scale); //bgBitmap = Bitmap.createBitmap(bgBitmap,0,0, bgBitmap.getWidth() ,bgBitmap.getHeight() ,matrix, true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawCircle(centPoint.x, centPoint.y, rotateRaduis, Gpaint); //画出圆环 canvas.drawArc(oval, 270, playedRadian, false, pPaint); // if(isShowRock){ // } canvas.drawCircle(mRockBollPosition.x, mRockBollPosition.y, mRadius , mPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(rotateRaduis*2+edgeMargin*2, rotateRaduis*2+edgeMargin*2); } private int getScreenWidth(){ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); return wm.getDefaultDisplay().getWidth(); } @Override public boolean onTouchEvent(MotionEvent event) { Point cp ; Point rp ; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Point np = new Point((int)event.getX(), (int)event.getY()); int distance = distance(centPoint ,np); System.out.println("distance:"+distance+",小:"+(rotateRaduis-mMaring)+",大:"+(rotateRaduis+mMaring)); cp = new Point((int)event.getX(), (int)event.getY()); rp = getOnRadius(cp); if(distance>=rotateRaduis-mMaring && distance<=rotateRaduis+mMaring){ mRockBollPosition.set(rp.x,rp.y); Log.i(TAG, "点下有效"); mRadius = mMaring; isDraging = true; //Point pp = new Point((int)event.getX(),(int)event.getY()); flushRadian(centPoint ,cp); } break; case MotionEvent.ACTION_MOVE: if(isDraging){ cp = new Point((int) event.getX(), (int) event.getY()); rp = getOnRadius(cp); mRockBollPosition.set(rp.x, rp.y); flushRadian(centPoint, cp); } break; case MotionEvent.ACTION_UP: isDraging = false; mRadius = 8; break; default: break; } invalidate(); return true; } private Point getOnRadius(Point cp) { float radian = getRadian(cp, centPoint); int cX = centPoint.x + (int) (rotateRaduis * Math.cos(radian)); int cY = centPoint.y - (int) (rotateRaduis * Math.sin(radian)); return new Point(cX, cY); } private void flushRadian(Point cp, Point pp) { float lenA = pp.x - cp.x; float lenB = cp.y - pp.y; // float lenC = (float) Math.sqrt(lenA*lenA+lenB*lenB); float a = lenA/lenB; // System.out.println("余数----------》"+a); double atan = Math.atan(lenA/lenB); double radian = (atan/Math.PI)*180; if(pp.x>cp.x){ if(radian>0){ playedRadian = (int) radian; }else{ playedRadian = (int) (180+radian); } }else{ if(radian>=0){ playedRadian = (int) (180+radian); }else{ playedRadian = (int) (360+radian); } } progressListener.setProgresschanged((float)playedRadian/360f); // System.out.println("atan:"+(atan/Math.PI)*180); } private int distance(Point cp, Point np) { try { int dx = np.x-cp.x; int dy = np.y -cp.y; return (int) Math.sqrt(Math.abs(dx*dx)+Math.abs(dy*dy)); } catch (Exception e) { e.printStackTrace(); } return 0; } /** * @describe 触摸点与中心点之间直线与水平方向的夹角角 * @param a * @param b * @return */ public static float getRadian(Point a, Point b) { float lenA = a.x - b.x; float lenB = a.y - b.y; float lenC = (float) Math.sqrt(lenA * lenA + lenB * lenB); float ang = (float) Math.acos(lenA / lenC); ang = ang * (b.y < a.y ? -1 : 1); return ang; } /** * 根据进度条角度刷新小球的位置 * * @param playedRadian2 */ private void flushRockPosition(int ang) { // mRockBollPosition.s mRockBollPosition.y = (int) (centPoint.y - (Math.cos(((float)ang/180f)*Math.PI)*rotateRaduis)); mRockBollPosition.x = (int) (centPoint.x + (Math.sin(((float)ang/180f)*Math.PI)*rotateRaduis)); // Log.i(TAG, "角度ang="+ang); // Log.i(TAG, "小球位置x="+mRockBollPosition.x+",y="+mRockBollPosition.y); } public void setProgress(float progress){ playedRadian = (int) (360*progress); flushRockPosition(playedRadian); invalidate(); } private ProgressChangedListener progressListener; public void setProgressListener(ProgressChangedListener progressListener) { this.progressListener = progressListener; } public interface ProgressChangedListener{ void setProgresschanged(float progress); } }
效果图如下
相关文章推荐
- Error: Activity class {XXX} does not exist的问题解决
- Android 之 text relocations的简单解决方法
- Android. ImageView with SVG Support
- android如何让后台服务service不被杀死(设置前台服务)
- 使用Android Studio搭建Android5.0集成开发环境
- Android自定义progress
- Android自定义相机,切换前后摄像头,照相机拍照
- Intent
- 详解Android中Service组件(一)
- android开发遇到的问题
- Android设备二维码扫描竖屏显示
- android判断当前应用在前台还是后台
- Android 计算器的开发
- Android监听程序进入后台
- SlidingMenu 在Android Studio使用详解
- Android 一张图看明白Hander的运行机制
- 调用 BitmapFactory.decodeByteArray 函数返回 null 值
- [Android开发]三级缓存初探索
- 支持addHeaderView、 addFooterView、分页加载数据的RecyclerView
- 怎样用 Android Annotations 写出高性能代码