完全自定义控件-自定义雷达扫描控件(学习Shader、Matrix)

elply1988 8年前
   <h3><strong>自定义雷达扫描控件</strong></h3>    <p>效果展示</p>    <p><img src="https://simg.open-open.com/show/426c13bd6ba8ac359e974ba6eebf13c9.gif"></p>    <p style="text-align:center">效果图</p>    <h3><strong>涉及知识点</strong></h3>    <p><strong>Shader类</strong></p>    <p>在Android中,提供了Shader类专门用来渲染图像以及一些几何图形。</p>    <ul>     <li>使用Shader类进行图像渲染时,首先需要构建Shader对象,然后通过Paint的setShader()方法来设置渲染对象,最后将这个Paint对象绘制到屏幕上即可。</li>     <li>Shader类包括了5个直接子类      <ul>       <li>BitmapShader 图像渲染</li>       <li>ComposeShader 混合渲染</li>       <li>LinearGradient 线性渲染</li>       <li>RadialGradient 环形渲染</li>       <li>SweepGradient 梯度渲染<br> SweepGradient也称为扫描渲染,是指在某一中心以x轴正方向逆时针旋转一周而形成的扫描效果的渲染形式。 <pre>  <code class="language-java">//坐标(cx,cy)决定了中心点的位置,会绕着该中心点进行360度旋转。color0表示的是起点的颜色位置,color1表示的是终点的颜色位置。  public SweepGradient(float cx, float cy, int[] colors, float[] positions)  public SweepGradient(float cx, float cy, int color0, int color1)</code></pre> </li>      </ul> </li>    </ul>    <p><a href="/misc/goto?guid=4959713336924280238" rel="nofollow,noindex">图像渲染的详细介绍</a></p>    <p><strong>Matrix类</strong></p>    <p>Matrix是一个矩阵,主要功能是坐标映射,数值转换。</p>    <ul>     <li>Matrix类有四种基本变换      <ul>       <li>平移 setTranslate(); 平移意味着在x轴和y轴上简单地移动图像。</li>       <li>缩放 setScale(); 它采用两个浮点数作为参数,分别表示在每个轴上所产生的缩放量。</li>       <li>旋转 setRotate(); 它采用一个浮点数表示旋转的角度。围绕默认点(0,0),正数将顺时针旋转图像,而负数将逆时针旋转图像,其中默认点是图像的左上角。</li>       <li>错切 setSkew(); 对于错切变换,在数学上又称为Shear mapping(可译为“剪切变换”)或者Transvection(缩并),它是一种比较特殊的线性变换。</li>      </ul> </li>    </ul>    <p><a href="/misc/goto?guid=4959713337021483968" rel="nofollow,noindex">Matrix原理</a></p>    <h3><strong>实现思路</strong></h3>    <ol>     <li>新建RadarView4类继承View</li>     <li>重写onDraw()方法,画四个无锯齿空心圆环,两条直线</li>     <li>画以最大圆为半径的实心渐变圆</li>     <li>创建矩阵,旋转画布,重绘,并用Handler实现循环</li>    </ol>    <p><strong>1. 初始化数据</strong></p>    <pre>  <code class="language-java">public RadarView4(Context context) {          this(context, null);      }        public RadarView4(Context context, AttributeSet attrs) {          this(context, attrs, 0);      }        public RadarView4(Context context, AttributeSet attrs, int defStyleAttr) {          super(context, attrs, defStyleAttr);            //为了避免在onDraw中重复创建对象,所以将一些初始化工作放入构造方法中来做          init();            //提交计划任务马上执行          mHandler.post(run);      }        private void init() {          //创建圆环画笔          mCirclePaint = new Paint();          mCirclePaint.setColor(Color.GRAY);          //设置画笔的宽度          mCirclePaint.setStrokeWidth(3);          //设置抗锯齿模式          mCirclePaint.setAntiAlias(true);          //设置画笔风格          mCirclePaint.setStyle(Paint.Style.STROKE);            //创建扫描线画笔          mShaderPaint = new Paint();          mShaderPaint.setAntiAlias(true);          //设置画笔风格为填充模式          mShaderPaint.setStyle(Paint.Style.FILL);      }</code></pre>    <p><strong>2. 开始绘制</strong></p>    <pre>  <code class="language-java">protected void onDraw(Canvas canvas) {          super.onDraw(canvas);          w = getMeasuredWidth();//获取view的宽度          h = getMeasuredHeight();//获取view的高度            //以中点为圆心          canvas.drawCircle(w / 2, h / 2, w / 12, mCirclePaint);          canvas.drawCircle(w / 2, h / 2, w / 6, mCirclePaint);          canvas.drawCircle(w / 2, h / 2, w / 4, mCirclePaint);          canvas.drawCircle(w / 2, h / 2, w / 3, mCirclePaint);          //画两条直线          canvas.drawLine(w / 2 - w / 3, h / 2, w / 2 + w / 3, h / 2, mCirclePaint);          canvas.drawLine(w / 2, h / 2 - w / 3, w / 2, h / 2 + w / 3, mCirclePaint);            //避免重复创建对象          if (mShader == null)              //新建扫描渲染,扫描边由透明->红色进行渐变              mShader = new SweepGradient(w / 2, h / 2, Color.TRANSPARENT, getResources().getColor(R.color.RED));            //设置渲染对象          mShaderPaint.setShader(mShader);          //指定画布的当前矩阵          canvas.concat(mMatrix);          //画一个扫描图像          canvas.drawCircle(w / 2, h / 2, w / 3, mShaderPaint);      }</code></pre>    <p><strong>3.通过Handler循环绘制实现转动</strong></p>    <pre>  <code class="language-java">private Handler mHandler = new Handler();  Runnable run = new Runnable() {      @Override     public void run() {        start++;        mMatrix = new Matrix();        //为矩阵设置旋转坐标        mMatrix.setRotate(start, w / 2, h / 2);        //刷新ui        postInvalidate();        //如果到了360度,则重新开始        start = start == 360 ? 0 : start;        //延迟执行        postDelayed(this, 10);      }  };</code></pre>    <p>这里是 <a href="/misc/goto?guid=4959713337098573703" rel="nofollow,noindex">项目地址</a> 。</p>    <p>参考</p>    <p><a href="/misc/goto?guid=4959713337186134518" rel="nofollow,noindex">http://blog.csdn.net/itjianghuxiaoxiong/article/details/50207009</a></p>    <p><a href="/misc/goto?guid=4959713337265743095" rel="nofollow,noindex">http://www.jianshu.com/p/4918034e3f0e#</a></p>    <p><a href="/misc/goto?guid=4959713337341851043" rel="nofollow,noindex">http://blog.csdn.net/sahadev_/article/details/50432764</a></p>    <p> </p>    <p>来自:http://www.jianshu.com/p/954982ad3385</p>    <p> </p>