[自定义控件]android自定义view实战之太极图
16lz
2021-01-24
android自定义view实战之太极图
尊重原创,转载请注明出处: http://blog.csdn.net/qq137722697
自定义view是Android工程师进阶不可避免要接触的,我的学习心得就是动手写,之后将推出系列自定view的文章,敬请期待,本篇将带来一个非常简单的自定义控件——>太极图。
先来看看最终的效果:
大部分自定义view无外乎包含三个方面的内容:
- 图形展示
- 用户交互
- 动画效果
先来分析这个图应该怎么画,来看一个动态图:
1、先画一个黑色的圆;
2、画左边的白色半圆;
3、画上边白色的中圆;
4、画下边黑色的中圆;
5、画上边黑色的小圆;
6、画下面白色的小圆。
另外就是关于屏幕的坐标系,不是数学中的那种哦看下图你就明白了,Y轴的方向是向下的:
下面来看看代码如何实现:
一、图形展示
第一步,创建一个继承至View的类,重写三个构造方法
public class TJView extends View { public TJView(Context context) { this(context, null); } public TJView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TJView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
第二步、来看看画太极需要属性
//画笔工具 private Paint mPaint; //圆心坐标--屏幕的宽高来设置-->目的是默认居中显示 private float currentX = 0; private float currentY = 0; //大圆半径 private float radiusBig = 200; //中圆半径 private float radiusCenter = radiusBig / 2; //小圆半径 private float radiusSmall = radiusCenter / 3; //边距(主要作用是画黑色大圆的时候,为了达到有边框的效果,半径需要比原来的大一点) private int padding = 8;
第三步、初始化画笔(第三个构造方法中)
public TJView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(); mPaint.setAntiAlias(true);//去掉锯齿 }
第四步、拿到屏幕中心点的坐标
这里需要重写onMeasure方法来拿到实际测量的值
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); currentX = MeasureSpec.getSize(widthMeasureSpec) / 2;//通过MeasureSpec拿到X轴 currentY = MeasureSpec.getSize(heightMeasureSpec) / 2;//通过MeasureSpec拿到Y轴 setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);//测绘 }
准备工作就绪,开始画
第五步、画一个黑色的大圆(此时圆点坐标、半径已经准备就绪了)
同样的需要重写onDraw方法—具体的业务抽成方法便于理解
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBg(canvas);//画黑色大圆 drawLeftHalfCirle(canvas);//画左边白色半圆 drawTBCirle(canvas);//画上下的四个圆 }
/** * 画黑色的背景底板 * * @param canvas */ private void drawBg(Canvas canvas) { mPaint.setColor(Color.BLACK);//设置背景颜色为黑色 canvas.drawCircle(currentX, currentY, radiusBig + padding, mPaint);//这里加padding才有边框效果 }
/** * 画左边半圆 * * @param canvas */ private void drawLeftHalfCirle(Canvas canvas) { mPaint.setColor(Color.WHITE); canvas.drawArc(new RectF(currentX - radiusBig, currentY - radiusBig, currentX + radiusBig, currentY + radiusBig), 90, 180, true, mPaint);//90度开始画 画180度 }
/** * 画上下两个圆--中圆和小圆 * * @param canvas */ private void drawTBCirle(Canvas canvas) { //画上面的白中圆 mPaint.setColor(Color.WHITE); canvas.drawCircle(currentX, currentY - radiusBig / 2, radiusCenter, mPaint); //画上面的黑小圆 mPaint.setColor(Color.BLACK); canvas.drawCircle(currentX, currentY - radiusBig / 2, radiusSmall, mPaint); //画下面的黑中圆 mPaint.setColor(Color.BLACK); canvas.drawCircle(currentX, currentY + radiusBig / 2, radiusCenter, mPaint); //画下面的白小圆 mPaint.setColor(Color.WHITE); canvas.drawCircle(currentX, currentY + radiusBig / 2, radiusSmall, mPaint); }
这样一个标准的太极图就画出来了,效果图就是一开始那个;
二、用户交互
下面加点交互效果,——>用户拖动的时候太极图会随手指的移动而移动;
这里需要重写onTouchEvent方法
上代码:
@Override public boolean onTouchEvent(MotionEvent event) { currentX = event.getX();//获取当前手指所在x轴 currentY = event.getY();//获取当前手指所在y轴 invalidate();//立刻重绘 return true;//返回true表示不通知父控件处理,自己处理 }
三、动画效果
关于动画,下面就来加点缩放动画吧,同样先看效果:
/** * 设置缩放动画 */ private void setAnimation() { ScaleAnimation scaleAnimation2 = new ScaleAnimation(0.7f, 1.0f, 0.7f, 1.0f, ScaleAnimation.RELATIVE_TO_PARENT, 0.5f, ScaleAnimation.RELATIVE_TO_PARENT, 0.5f); scaleAnimation2.setDuration(500);// 设置持续时间 scaleAnimation2.setRepeatCount(99999);// 设置重复次数 scaleAnimation2.setFillAfter(true);// 保持动画结束时的状态 startAnimation(scaleAnimation2); }
在第三个构造方法中调用:
public TJView(Context context, AttributeSet attrs, int defStyleAttr) { //省略其余代码 setAnimation(); }
四、最后
最后贴出完整的代码:
调用处:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_tj" android:layout_width="match_parent" android:layout_height="match_parent"> <com.hdl.myhttputilssimple.TJView android:layout_width="match_parent" android:layout_height="match_parent" />RelativeLayout>
完整的TJView代码:
/** * 太极图 * Created by HDL on 2016/12/27. */public class TJView extends View { private static final String TAG = "TJView"; private int padding = 8; //画笔工具 private Paint mPaint; //圆心坐标 private float currentX = 0; private float currentY = 0; //大圆半径 private float radiusBig = 200; //中圆半径 private float radiusCenter = radiusBig / 2; //小圆半径 private float radiusSmall = radiusCenter / 3; public TJView(Context context) { this(context, null); } public TJView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TJView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(); mPaint.setAntiAlias(true); setAnimation(); } /** * 设置缩放动画 */ private void setAnimation() { ScaleAnimation scaleAnimation2 = new ScaleAnimation(0.7f, 1.0f, 0.7f, 1.0f, ScaleAnimation.RELATIVE_TO_PARENT, 0.5f, ScaleAnimation.RELATIVE_TO_PARENT, 0.5f); scaleAnimation2.setDuration(500);// 设置持续时间 scaleAnimation2.setRepeatCount(99999);// 设置重复次数 scaleAnimation2.setFillAfter(true);// 保持动画结束时的状态 startAnimation(scaleAnimation2); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBg(canvas); drawLeftHalfCirle(canvas); drawTBCirle(canvas); } /** * 画上下两个圆--中圆和小圆 * * @param canvas */ private void drawTBCirle(Canvas canvas) { //画上面的白中圆 mPaint.setColor(Color.WHITE); canvas.drawCircle(currentX, currentY - radiusBig / 2, radiusCenter, mPaint); //画上面的黑小圆 mPaint.setColor(Color.BLACK); canvas.drawCircle(currentX, currentY - radiusBig / 2, radiusSmall, mPaint); //画下面的黑中圆 mPaint.setColor(Color.BLACK); canvas.drawCircle(currentX, currentY + radiusBig / 2, radiusCenter, mPaint); //画下面的白小圆 mPaint.setColor(Color.WHITE); canvas.drawCircle(currentX, currentY + radiusBig / 2, radiusSmall, mPaint); } /** * 画左边半圆 * * @param canvas */ private void drawLeftHalfCirle(Canvas canvas) { mPaint.setColor(Color.WHITE); canvas.drawArc(new RectF(currentX - radiusBig, currentY - radiusBig, currentX + radiusBig, currentY + radiusBig), 90, 180, true, mPaint);//90度开始画180度 } /** * 画黑色的背景底板 * * @param canvas */ private void drawBg(Canvas canvas) { mPaint.setColor(Color.BLACK); canvas.drawCircle(currentX, currentY, radiusBig + padding, mPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); currentX = MeasureSpec.getSize(widthMeasureSpec) / 2; currentY = MeasureSpec.getSize(heightMeasureSpec) / 2; setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } @Override public boolean onTouchEvent(MotionEvent event) { currentX = event.getX(); currentY = event.getY(); invalidate(); return true; }}
尊重原创,转载请注明出处: http://blog.csdn.net/qq137722697
更多相关文章
- Android(安卓)Selector和Shape的用法
- 【android】shape使用总结
- Android(安卓)样式之shape入门使用
- Android中的Shape属性
- shape 圆角
- Android(安卓)ViewPagerIndicator小圆点效果实现
- Android TextView设置阴影效果
- Android 简单的圆形刻度刻画
- Android Studio属性学习(一)——shape属性