版权声明:本文为博主原创文章,未经博主允许不得转载。
转载请标明出处:http://blog.csdn.NET/lmj623565791/article/details/24252901
很多的Android入门程序猿来说对于Android自定义View,可能都是比较恐惧的,但是这又是高手进阶的必经之路,所有准备在自定义View上面花一些功夫,多写一些文章。先总结下自定义View的步骤:
1、自定义View的属性
2、在View的构造方法中获得我们自定义的属性
[ 3、重写onMesure ]
4、重写onDraw
我把3用[]标出了,所以说3不一定是必须的,当然了大部分情况下还是需要重写的。
1、自定义View的属性,首先在res/values/ 下建立一个attrs.xml , 在里面定义我们的属性和声明我们的整个样式。
第一步初始化:
//初试化操作 private void intiView() {circleRegion = new Region(); circlePath = new Path(); rectRegion = new Region(); rectPath = new Path(); SmallCircleRegion = new Region(); SmallCirclePath = new Path(); circlePain = new Paint(); rectPain = new Paint(); smallPain = new Paint(); }
系统帮我们测量的高度和宽度都是MATCH_PARNET,当我们设置明确的宽度和高度时,系统帮我们测量的结果就是我们设置的结果,当我们设置为WRAP_CONTENT,或者MATCH_PARENT系统帮我们测量的结果就是MATCH_PARENT的长度。
所以,当设置了WRAP_CONTENT时,我们需要自己进行测量,即重写onMesure方法”:
重写之前先了解MeasureSpec的specMode,一共三种类型:
EXACTLY:一般是设置了明确的值或者是MATCH_PARENT
AT_MOST:表示子布局限制在一个最大值内,一般为WARP_CONTENT
UNSPECIFIED:表示子布局想要多大就多大,很少使用
下面是我们重写onMeasure代码:
//得到属性 TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.CirCleView); circleRadius = array.getInteger(R.styleable.CirCleView_circleRadius, 300); smallCircleRadius = array.getInteger(R.styleable.CirCleView_smallCircleRadius, 150); textSize = array.getInteger(R.styleable.CirCleView_textSize, 50); circleColor = array.getInteger(R.styleable.CirCleView_circleColor, Color.RED); TextView = array.getString(R.styleable.CirCleView_TextView);
然后重写
onSizeChanged方法
width = w; height = h; // ▼在屏幕中间添加一个矩形 rectPath.addRect(w / 2 - 300, h / 2 - 300, w / 2 + 300, h / 2 + 300, Path.Direction.CW); // ▼将剪裁边界设置为视图大小 Region globalRegion = new Region(-w, -h, w, h); // ▼将 Path 添加到 Region 中 rectRegion.setPath(rectPath, globalRegion); //绘出中圆 circlePath.addCircle(w / 2, h / 2, circleRadius, Path.Direction.CW); // ▼将剪裁边界设置为视图大小 Region globalRegionCircle = new Region(-w, -h, w, h); // ▼将 Path 添加到 Region 中 circleRegion.setPath(circlePath, globalRegion); //绘出小圆 SmallCirclePath.addCircle(w / 2, h / 2, smallCircleRadius, Path.Direction.CW); // ▼将剪裁边界设置为视图大小 Region globalRegionCircle3 = new Region(-w, -h, w, h); // ▼将 Path 添加到 Region 中 SmallCircleRegion.setPath(SmallCirclePath, globalRegion); }重写OnDRAW方法
Path rect = rectPath; rectPain.setColor(Color.GREEN); // 绘制矩形 canvas.drawPath(rect, rectPain); //绘制圆形 Path circle = circlePath; circlePain.setColor(circleColor); canvas.drawPath(circle, circlePain); //绘制小圆 Path small = SmallCirclePath; smallPain.setColor(Color.WHITE); canvas.drawPath(small, smallPain); smallPain.setColor(Color.BLACK); smallPain.setTextSize(textSize); float yuan = smallPain.measureText(TextView); Paint.FontMetrics metrics = smallPain.getFontMetrics(); float ceil = (float) Math.ceil(metrics.descent - metrics.ascent); canvas.drawText("圆环", width / 2 - yuan / 2, height / 2 + ceil / 2, smallPain);触摸事件
@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: int x = (int) event.getX(); int y = (int) event.getY(); // ▼点击区域判断 if (SmallCircleRegion.contains(x, y)) { Toast.makeText(this.getContext(), "在小圆内", Toast.LENGTH_SHORT).show(); }else if (circleRegion.contains(x, y)) { Toast.makeText(this.getContext(), "在圆环内", Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(this.getContext(), "在圆环外", Toast.LENGTH_SHORT).show(); } break; } return true; }