最近研究自定义View,于是做了这个demo,供大家参考

参考了一位博主文章:http://blog.csdn.net/lilong85362952/article/details/41447967

自定义View的代码:


public class DrawView extends View implements ViewRefreshInterface, OnTouchListener {private RectF rectF;private List colors;private List mList;// 圆心private Point point;// 半径private int radius = 0;// view刷新private int a = 0;private int refeshAngle = 0;private int number = 0;private boolean isPause;Thread thread = new Thread();private ViewRefreshUtil viewRefreshUtil;private ViewRefreshUtil.ViewRefreshInterfaceEntity viewRefreshInterface;private ViewClickListener viewClickListener;private Context mContext;public DrawView(Context context) {super(context);init(context);}public DrawView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}@SuppressLint("ClickableViewAccessibility")private void init(Context context) {this.mContext = context;colors = new ArrayList();mList = new ArrayList();colors.add(Color.RED);colors.add(Color.GREEN);colors.add(Color.BLUE);colors.add(Color.YELLOW);viewRefreshUtil = ViewRefreshUtil.getRefreshUtil();viewRefreshInterface = viewRefreshUtil.addViewRefreshInterface(this);this.setOnTouchListener(this);DisplayMetrics dm = new DisplayMetrics();((Activity) mContext).getWindowManager().getDefaultDisplay().getMetrics(dm);isPause = false;}@SuppressLint("DrawAllocation")@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint paint = new Paint();paint.setAntiAlias(true);// 抗锯齿paint.setStyle(Style.STROKE);// Style.FILL: 实心, STROKE:空心, FILL_OR_STROKE:同时实心与空心//paint.setStrokeCap(Cap.ROUND);// 画笔样式:圆形 Cap.ROUND, 方形 Cap.SQUARE//paint.setStrokeJoin(Join.ROUND);// 平滑效果paint.setStrokeWidth(15);//paint.setColor(Color.BLUE);// canvas.drawLine(0, 50, 450, 50, paint);// 画线// canvas.drawRect(0, 0, 20, 60, paint);// 画矩形// canvas.drawCircle(100, 50, 50, paint);// 画圆//canvas.drawOval(rectF, paint);// 画椭圆或者圆a += 1;refeshAngle += 1;int temAngle = 0;paint.setStyle(Style.FILL);paint.setStrokeWidth(14);for (int i = 0; i < number; i++) {paint.setColor(colors.get(i));temAngle += mList.get(i).getEndAngle() - mList.get(i).getStartAngle();if (temAngle >= a) {drawMyView(canvas, paint, rectF, mList.get(i).getStartAngle(), refeshAngle);if (refeshAngle == mList.get(i).getEndAngle() - mList.get(i).getStartAngle()) {refeshAngle = 0;number = (number < mList.size()) ? number + 1 : mList.size();}} else {drawMyView(canvas, paint, rectF, mList.get(i).getStartAngle(), Math.abs(mList.get(i).getEndAngle() - mList.get(i).getStartAngle()));}}}private void drawMyView(Canvas canvas, Paint paint, RectF rectF, int startAngle, int endAngle) {paint.setStrokeJoin(Join.MITER);paint.setStrokeCap(Cap.SQUARE);canvas.drawArc(rectF, startAngle, endAngle, true, paint);}@SuppressLint("DrawAllocation")@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int measureWidth = getMeasureWH(widthMeasureSpec);int measureHeigh = getMeasureWH(heightMeasureSpec);if (measureWidth > measureHeigh) {radius = measureHeigh / 2;} else {radius = measureWidth / 2;}if (getMeasuredWidth() != 0 && getMeasuredHeight() != 0) {rectF = new RectF(0, 0, radius * 2, radius * 2);//this.start();}if (measureWidth > measureHeigh) {setMeasuredDimension(measureHeigh, measureHeigh);} else {setMeasuredDimension(measureWidth, measureWidth);}}private int getMeasureWH(int measureSpec) {int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);return specSize;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);}public void setData(List list) {if (!viewRefreshInterface.isRefresh() && !isPause) {this.mList = list;this.number = 1;//this.start();}}public boolean isRefresh() {return viewRefreshInterface.isRefresh();}// 开始public void start() {if (isPause) {viewRefreshInterface.setRefresh(true);viewRefreshUtil.startViewRefresh(viewRefreshInterface);isPause = false;}if (!viewRefreshInterface.isRefresh()) {viewRefreshInterface.setRefresh(true);viewRefreshUtil.startViewRefresh(viewRefreshInterface);isPause = false;}}// 暂停public void pause() {if (viewRefreshInterface.isRefresh() && !isPause) {viewRefreshInterface.setRefresh(false);isPause = true;}}// 停止public void stop() {viewRefreshInterface.setRefresh(false);a = 0;refeshAngle = 0;number = 0;init(mContext);postInvalidate();}@Overridepublic void refresh() {if (a >= 360) {viewRefreshInterface.setRefresh(false);} else {postInvalidate();}}@SuppressLint("DrawAllocation")@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);point = new Point((right - left) / 2 + left, (bottom - top) / 2 + top);}@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_UP:double x = Math.pow(point.x - event.getRawX(), 2);double y = Math.pow(point.y - event.getRawY(), 2);if (!viewRefreshInterface.isRefresh() && Math.sqrt(x + y) <= radius) {int tanX = (int) Math.abs(event.getRawX() - point.x);int tanY = (int) Math.abs(event.getRawY() - point.y);double clickAngle = getangle(tanX, tanY, (int) event.getRawX() - point.x, point.y - (int) event.getRawY());int mClickAngle = (int) clickAngle - 90;for (int i = 0; i < mList.size(); i++) {if (mClickAngle >= mList.get(i).getStartAngle() && mClickAngle <= mList.get(i).getEndAngle()) {viewClickListener.clickListener(mList.get(i));break;}}}break;}return true;}// 根据点击位置获取夹角private double getangle(int x, int y, int downx, int downy) {double angle = (float) 0.0;if (downx > 0 && downy < 0) {double c = (double) y / (double) x;double d = Math.toDegrees(Math.atan(c));angle = d + 90;} else if (downx <= 0 && downy <= 0) {double c = (double) x / (double) y;double d = Math.toDegrees(Math.atan(c));angle = d + 180;} else if (downx < 0 && downy >= 0) {double c = (double) y / (double) x;double d = Math.toDegrees(Math.atan(c));angle = d + 270;} else {double c = (double) x / (double) y;double d = Math.toDegrees(Math.atan(c));angle = d;}return angle;}public void setViewClickListenrt(ViewClickListener clickListener) {this.viewClickListener = clickListener;}public interface ViewClickListener {public void clickListener(SectorItem item);}}

这里有一些东西需要注意一下(这里不做详细说明):

1、当你在xml中为这个view设置margin属性的时候,在onLayout中获取的top,left,right,bottom的值都是你设置的2倍,所以再做一些计算时要注意,

2、在使用canvas.drawArc()方法画圆时,是以水平右方向顺时针画的,所以我在画圆的时候起始位置的角度为:-90,,竖直方向开始画圆,

3、onMeasure()这个方法在什么时候调用,调用几次,getMeasuredHeight()、getHeight()这两个方法区别,MeasureSpecMode()中几个不同Mode也是需要注意,

4、在画这个圆时,会有点慢,如果想改变速率,需要注意 refeshAngle 和 a 这两个参数,因为扇形时整数度数,我是一度一度慢慢绘制的,修改时需要注意

如果不需要慢慢绘制这个圆可以直接用for循环调用drawMyView(canvas, paint, rectF, mList.get(i).getStartAngle(), mList.get(i).getEndAngle());直接回执完整的圆,省去了 绘制的时间


ViewRefreshUtil代码:

public class ViewRefreshUtil implements Runnable {private Thread thread;private static ViewRefreshUtil viewRefreshUtil;private ArrayList viewRefreshInterfaces;public static ViewRefreshUtil getRefreshUtil() {if (null == viewRefreshUtil) {viewRefreshUtil = new ViewRefreshUtil();}return viewRefreshUtil;}private ViewRefreshUtil() {viewRefreshInterfaces = new ArrayList();}public ViewRefreshInterfaceEntity addViewRefreshInterface(ViewRefreshInterface viewRefreshInterface) {ViewRefreshInterfaceEntity viewRefreshInterfaceEntity = new ViewRefreshInterfaceEntity();viewRefreshInterfaceEntity.setViewRefreshInterface(viewRefreshInterface);viewRefreshInterfaces.add(viewRefreshInterfaceEntity);return viewRefreshInterfaceEntity;}public void startViewRefresh(ViewRefreshInterfaceEntity viewRefreshInterfaceEntity) {viewRefreshInterfaceEntity.setRefresh(true);if (null == thread || !thread.isAlive()) {thread = new Thread(this);            thread.start();}}public void stopViewRefresh(ViewRefreshInterfaceEntity viewRefreshInterfaceEntity) {viewRefreshInterfaceEntity.setRefresh(false);}public interface ViewRefreshInterface {void refresh();}@Overridepublic void run() {int i = 1;        while (i != 0) {            i=0;            for (ViewRefreshInterfaceEntity viewRefreshInterfaceEntity : viewRefreshInterfaces) {                if (viewRefreshInterfaceEntity.isRefresh()) {                viewRefreshInterfaceEntity.getViewRefreshInterface().refresh();                    i++;                }            }            try {                Thread.sleep(20);            } catch (InterruptedException e) {                e.printStackTrace();            }        }}public class ViewRefreshInterfaceEntity {private boolean isRefresh = false;private ViewRefreshInterface viewRefreshInterface;public boolean isRefresh() {return isRefresh;}public void setRefresh(boolean isRefresh) {this.isRefresh = isRefresh;}public ViewRefreshInterface getViewRefreshInterface() {return viewRefreshInterface;}public void setViewRefreshInterface(ViewRefreshInterface viewRefreshInterface) {this.viewRefreshInterface = viewRefreshInterface;}}}

SectorItem代码:

public class SectorItem implements Serializable {private int startAngle;private int endAngle;private String name;public int getStartAngle() {return startAngle;}public void setStartAngle(int startAngle) {this.startAngle = startAngle;}public int getEndAngle() {return endAngle;}public void setEndAngle(int endAngle) {this.endAngle = endAngle;}public String getName() {return name;}public void setName(String name) {this.name = name;}}


mainactivity代码:

public class MainActivity extends Activity implements OnClickListener {private DrawView drawView;private Button start, pause, stop;private List list;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);drawView = (DrawView) findViewById(R.id.dv);start = (Button) findViewById(R.id.start);pause = (Button) findViewById(R.id.pause);stop = (Button) findViewById(R.id.stop);start.setOnClickListener(this);pause.setOnClickListener(this);stop.setOnClickListener(this);drawView.setViewClickListenrt(new ViewClickListener() {@Overridepublic void clickListener(SectorItem item) {Toast.makeText(MainActivity.this, "You Click :" + item.getName() + " Area !", Toast.LENGTH_SHORT).show();}});}private void initData() {list = new ArrayList();SectorItem item = new SectorItem();item.setStartAngle(-90);item.setEndAngle(0);item.setName("Red");list.add(item);item = new SectorItem();item.setStartAngle(0);item.setEndAngle(80);item.setName("Green");list.add(item);item = new SectorItem();item.setStartAngle(80);item.setEndAngle(150);item.setName("BLUE");list.add(item);item = new SectorItem();item.setStartAngle(150);item.setEndAngle(270);item.setName("YELLOW");list.add(item);drawView.setData(list);}@Overrideprotected void onDestroy() {super.onDestroy();if (drawView.isRefresh()) {drawView.stop();}}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.start:initData();drawView.start();break;case R.id.pause:drawView.pause();break;case R.id.stop:drawView.stop();break;}}}


mainactivity 的布局:

        


功能很简单,进入页面,点击start按钮开始竖直顺时针方向画圆,圆内有四种不同颜色的扇形,点击pause按钮暂停画圆,点击stop按钮停止画圆并清空view,当我们点击圆内不同颜色的扇形时,用Toast打印我们点击的扇形的颜色



最后,未经允许禁止转载

更多相关文章

  1. 没有一行代码,「2020 新冠肺炎记忆」这个项目却登上了 GitHub 中
  2. android,利用layoutParams代码动态布局空间位置
  3. Android与服务器通信——http方式通信
  4. Tiny210 从源代码开始创建Android
  5. Android(安卓)WebView 加载本地SD卡的html
  6. Android实现点击获取验证码60秒后重新获取功能
  7. android view增加点击效果,如:iReader书架书籍点击变暗
  8. Android解决CoordinatorLayout折叠布局RecyclerView最后一条数据
  9. Android-显示传感器的值

随机推荐

  1. Linux防火墙Firewall和Iptables的使用
  2. macrotask与microtask
  3. 开发者必备Docker命令
  4. [一些勘误]ubuntu16.04的Python版本,Pytho
  5. 【MySQL】 explicit_defaults_for_timest
  6. 初始化 Java 数据字段(学习 Java 编程语言
  7. 使用Maven插件构建Docker镜像
  8. VS Code源码简析
  9. 定制化IDE选型笔记
  10. mall在Linux环境下的部署(基于Docker容器)