自定义控件(三)--弧线展示图与音频条形图

前言:

当Android系统原生的控件无法满足我们的需求时,我们就可以完全创建一个新的自定义View来实现需要的功能。创建一个自定义View,难点在于绘制控件和实现交互,这也是评价一个自定义View优劣的标准之一。通常需要继承View()类,并重写他的onDraw(),onMeasure()方法来实现绘制逻辑,同时重写onTouchEvent()等触控事件来实现交互逻辑。当然,我们还可以实现组合控件的方式那样,通过引入自定义属性,丰富自定义Viewd的可自定义Viewd的可定制性。


自定义控件(三)--弧线展示图与音频条形图_第1张图片

一 弧线展示图

上面的图片非常清楚的展示一个项目所占的比例,简洁明了。因此,实现这样一个自定义View用在我们的程序中,可以让整个程序实现比较清晰的数据展示效果。那么该如何创建一个这样的自定义View呢?很明显,这个自定义View分为三个部分,分别是中间的圆形,中间展示的文字和外圈的弧线。既然有了这样的思路,只要在onDraw()方法中一个个去绘制就可以了。这里为了方便,我们把View的绘制长度直接设置为屏幕的宽度。首先,在初始的时候,设置好三种图形的参数。园的代码如下所示:

  mCircleXY = length / 2;
  mRadius = (float) (length * 0.5 / 2);
绘制弧线,需要指定其椭圆的外接矩形,代码如下所示。

mArcRectF = new RectF(
                (float) (length * 0.1),
                (float) (length * 0.1),
                (float) (length * 0.9),
                (float) (length * 0.9));

绘制文字,只需要设置好文字的起始绘制位子即可。

接下来,我们就可以在onDraw()方法中进行绘制了,代码如下所示。

 // 绘制圆
        canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);
        // 绘制弧线
        canvas.drawArc(mArcRectF, 270, mSweepAngle, false, mArcPaint);
        // 绘制文字
        canvas.drawText(mShowText, 0, mShowText.length(),
                mCircleXY, mCircleXY + (mShowTextSize / 4), mTextPaint);

如果这些图单独绘制,应该是非常容易的事情,只是这里进行了一下组合,就创建了一个新的View。其实,不论多复杂的图形,控件,他都是由这些最基本的图形绘制出来的,关键是在于你如何去分解,设计这些图形,当你脑海中有一副设计图时,剩下的事情就只是对坐标的计算了。

当然,对于这个简单的view,有一些方法可以让调用者来设置不同的状态值,代码如下所示。

public void setSweepValue(float sweepValue) {
        if (sweepValue != 0) {
            mSweepValue = sweepValue;
        } else {
            mSweepValue = 25;
        }
        this.invalidate();
    }

例如,当用户不知道具体的比例值时,可以设置默认为25,而调用者可以通过如下代码来设置相应的比例值。



二 音频条形图

 在上面的图片中,我们也看到了这个简单的案例,由于只是演示一下自定义View的用法,我们就不去真实的监听音频输入了,随机模拟一些数字即可。这个实例比上面的比例图稍微复杂一些,主要复杂在绘制的坐标计算和动画效果上,我们先来看一下,要实现这样一个条形图,相信大家应该可以很快找到思路,也就是绘制一个个的矩形,每个矩形之间稍微偏移一点距离即可。如下展示了一种坐标的计算方法。

@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		for(int i = 0;i< mRectCount;i++){
		     canvas.drawRect(
                    (float) (mWidth * 0.4 / 2 + mRectWidth * i + offset),
                    currentHeight,
                    (float) (mWidth * 0.4 / 2 + mRectWidth * (i + 1)),
                    mRectHeight,
                    mPaint);
		}
	}


 如上代码中我们通过循环创建了这些小的矩形,其中currentHeight就是每个小矩形的高,通过坐标的不断偏移,就绘制出了这些静态的小矩形。下面我们再让这些小矩形的高度进行随机变化,通过Math.random()方法来随机改变这些高度值,并赋值给currentHeight,代码如下所示:

mRandom =Math.random();
float currentHeight=(float)(mRectHeight*mRandom);

这样,我们就完成了静态效果的绘制,那么如何实现动态效果呢?其实非常简单,只要在onDraw()方法中再去调用invalidata()方法通知View进行重绘就可以了。不过,在这里不需要每次一绘制新的就通知View进行重绘,这样会因为绘制速度太快反而影响效果。因此,我们可以使用如下代码进行View的延迟重绘,代码如下所示。

postInvalidateDelayed(300);

这样每隔300ms通知View进行重绘,就可以得到一个比较好的视觉效果了。最后,为了自定义View更加逼真,可以在绘制小矩形的时候,给绘制的Paint对象增加一个LinearGradient渐变效果,这样不同高度的矩形就会有不同颜色的渐变效果,更加能够模拟音频条形图的风格,代码所示。

@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		mWidth = getWidth();
		mRectHeight = getHeight();
		mRectWidth = (int)(mWidth * 0.6 / mRectCount);
		mLinearGradient = new LinearGradient(0, 0, mRectWidth, mRectHeight, Color.YELLOW, Color.BLUE, Shader.TileMode.CLAMP);
		mPaint.setShader(mLinearGradient);
		
	}

从这个例子中,我们就可以知道,在创建自定义View的时候,需要一步一步来,从一个基本的效果开始,慢慢的增加功能,绘制更加复杂的效果。不论是多么复杂的自定义View,他一定是慢慢迭代起来的功能。

源码地址:http://blog.csdn.net/qq_31307919/article/details/51098418


你可能感兴趣的:(android,自定义控件)