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

更多相关文章

  1. Android(安卓)Selector和Shape的用法
  2. 【android】shape使用总结
  3. Android(安卓)样式之shape入门使用
  4. Android中的Shape属性
  5. shape 圆角
  6. Android(安卓)ViewPagerIndicator小圆点效果实现
  7. Android TextView设置阴影效果
  8. Android 简单的圆形刻度刻画
  9. Android Studio属性学习(一)——shape属性

随机推荐

  1. android与webService的数据传输---数据表
  2. Android清除本地数据缓存代码案例
  3. Android(安卓)Robotium小结
  4. 利用半透明对话框实现新浪微博android客
  5. Android内核学习——SearchManager分析
  6. android 自定义水平和圆形progressbar 只
  7. Android(安卓)系统启动时自启动一个app
  8. 编译Android内核模块
  9. Android(安卓)build.gradle buildConfigF
  10. VMware安装Android虚拟机及adb调试