实现原理
首先就是自定义个WaveView 继承View,然后再WaveView 内部实现代码逻辑:
① 水波就波嘛? sin函数? 贝塞尔曲线? 都行,这里就用二阶贝塞 尔曲线去画吧
② 波要动嘛,怎么动呢?线程? 好吧 这里用了个Handler。
③绘制波首先要找点,那么在onMeasure()里找出需要的点咯,这里就暂时展示一个波段吧,一个波长移动左边不就没了?OK 那就两个波吧,吼吼,两个波(猥琐男潜质表露无遗啊)。接下来就是Handler 结合 onDraw()绘制。OK,那就先看我Word绘制的粗瘪的波动图,请看VCR,oh,no... gif
意思就是波平移一个波长之后回到初始位置继续平移循环。
好吧,有人说了,这么简单的逻辑你要啰嗦那么多???
好吧,我承认,我有唐僧的潜质。。。
闲话就不说了,先上
效果图
示例代码如下
调用的Activity
* Created by LiuDong on 2016/12/22. * Email:15002102128@126.com */ public class WaveActivity extends Activity { LD_WaveView waveView;//方形 LD_WaveView waveCircleView;//圆形 private int progrees=0;//进度 private Handler mHandler=new Handler(){ @Override public void handleMessage(Message msg) { if (progrees==100) progrees=0; Log.i("progress",progrees+""); waveView.setmProgress(progrees++); waveCircleView.setmProgress(progrees++); mHandler.sendEmptyMessageDelayed(0,100); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_wave); waveView= (LD_WaveView) findViewById(R.id.waveView); waveCircleView= (LD_WaveView) findViewById(R.id.waveViewCircle); mHandler.sendEmptyMessageDelayed(0,10); } }
xml布局
自定义WaveView
public class LD_WaveView extends View { private int mProgress;//进度 private int mTimeStep = 10;//时间间隔 private int mSpeed = 5;//波单次移动的距离 private int mViewHeight;//视图宽高 private int mViewWidth;//视图宽度 private int mLevelLine;// 基准线 private int mWaveLength;//波长 暂定view宽度为一个波长 private int mStrokeWidth;//园的线宽 private RectF rectF;//圆环区域 private int mWaveHeight;//波峰高度 private int mLeftWaveMoveLength;//波平移的距离,用来控制波的起点位置 private int mWaveColor;//波的颜色 private Paint mPaint;//画笔 private Paint mCirclePaint;//圆环画笔 private Paint mBorderPaint;//边界画笔 private int mBorderWidth=4;//边界宽度 private Paint mTextPaint;//文字画笔 private Path mPath;//绘画线 private ListmPoints;//点的集合 private boolean isMeasure = false;//是否已测量过 private boolean isCircle=false;//是否圆形默认false,可属性代码设置 //处理消息 private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { initWaveMove(); } }; private void initWaveMove(){ mLeftWaveMoveLength+=mSpeed;//波向右移动距离增加mSpeed; if (mLeftWaveMoveLength>=mWaveLength){//当增加到一个波长时回复到0 mLeftWaveMoveLength=0; } invalidate(); } public LD_WaveView(Context context) { this(context, null); } public LD_WaveView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public LD_WaveView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); getAttr(context, attrs, defStyleAttr); init(); } private void init() { mPoints = new ArrayList (); //波浪轨迹画笔 mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setColor(mWaveColor); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPath = new Path(); //文字画笔 mTextPaint=new Paint(); mTextPaint.setColor(Color.RED); mTextPaint.setTextAlign(Paint.Align.CENTER); mTextPaint.setTextSize(48); //圆环画笔 mCirclePaint=new Paint(); mCirclePaint.setAntiAlias(true); mCirclePaint.setColor(Color.WHITE); mCirclePaint.setStyle(Paint.Style.STROKE); //边界线画笔 mBorderPaint=new Paint(); mBorderPaint.setAntiAlias(true); mBorderPaint.setColor(mWaveColor); mBorderPaint.setStrokeWidth(mBorderWidth); mBorderPaint.setStyle(Paint.Style.STROKE); } private void getAttr(Context context, AttributeSet attrs, int defStyle) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.LD_WaveView, defStyle, 0); mWaveColor = a.getColor(R.styleable.LD_WaveView_wave_color, Color.RED); isCircle=a.getBoolean(R.styleable.LD_WaveView_wave_circle,false); a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (!isMeasure&&Math.abs(getMeasuredHeight()-getMeasuredWidth())<50) {//只计算一次就够了 ,relativelayout的时候要绘制两次 加个宽高判断 mViewHeight = getMeasuredHeight(); mViewWidth = getMeasuredWidth(); mLevelLine = mViewHeight; //初始化波的准位线 起始位视图最底部 { mLevelLine = mViewHeight * (100-mProgress) / 100; if (mLevelLine < 0) mLevelLine = 0; } //计算波峰值 mWaveHeight = mViewHeight / 20;//波峰暂定为view高度的1/20,如果需要设置 可设置set方法赋值; mWaveLength = getMeasuredWidth(); //计算所有的点 这里取宽度为整个波长 往左再延伸一个波长 两个波长则需要9个点 for (int i = 0; i < 9; i++) { int y = 0; switch (i % 4) { case 0: y = mViewHeight; break; case 1: y =mViewHeight+ mWaveHeight; break; case 2: y = mViewHeight; break; case 3: y = mViewHeight-mWaveHeight; break; } Point point = new Point(-mWaveLength + i * mWaveLength / 4, y); mPoints.add(point); } int mIncircleRadius=mViewHeight =50)//如果进度达到50 颜色变为白色,没办法啊,进度在中间 不变颜色看不到 mTextPaint.setColor(Color.WHITE); else mTextPaint.setColor(mWaveColor); canvas.drawText(progress,0,progress.length(),mViewWidth/2,mViewHeight/2+textHeight/2,mTextPaint); if (isCircle) { canvas.drawArc(rectF, 0, 360, true, mCirclePaint); Paint circlePaint = new Paint(); circlePaint.setStrokeWidth(5); circlePaint.setColor(Color.WHITE); circlePaint.setAntiAlias(true); circlePaint.setStyle(Paint.Style.STROKE); canvas.drawCircle(mViewWidth / 2, mViewHeight / 2, mViewHeight / 2, circlePaint); mBorderPaint.setStrokeWidth(mBorderWidth/2); canvas.drawCircle(mViewWidth/2,mViewHeight/2,mViewHeight/2-mBorderWidth/2,mBorderPaint); }else { canvas.drawRect(0,0,mViewWidth,mViewHeight,mBorderPaint); } // handler.sendEmptyMessageDelayed(0,mTimeStep); } public void setmProgress(int mProgress) { this.mProgress = mProgress; mLevelLine=(100-mProgress)*mViewHeight/100; } public void setCircle(boolean circle) { isCircle = circle; } }
自定义属性
总结
好了,以上就是这篇文章的全部内容了,代码里备注应该还算比较清楚了,希望能对一些人有一些帮助,瑕疵不足之处欢迎指正,或者有好的建议。也可以留言交流。