|
1 | 1 | package com.allen.androidcustomview.widget; |
2 | 2 |
|
| 3 | +import android.animation.ValueAnimator; |
3 | 4 | import android.content.Context; |
| 5 | +import android.content.res.TypedArray; |
4 | 6 | import android.graphics.Canvas; |
| 7 | +import android.graphics.LinearGradient; |
5 | 8 | import android.graphics.Paint; |
| 9 | +import android.graphics.Path; |
| 10 | +import android.graphics.Shader; |
6 | 11 | import android.util.AttributeSet; |
7 | 12 | import android.view.View; |
| 13 | +import android.view.animation.LinearInterpolator; |
| 14 | + |
| 15 | +import com.allen.androidcustomview.R; |
8 | 16 |
|
9 | 17 | /** |
10 | 18 | * Created by allen on 2016年12月13日. |
|
14 | 22 |
|
15 | 23 | public class WaveView extends View { |
16 | 24 |
|
17 | | - private Paint paint; |
| 25 | + /** |
| 26 | + * 上下文对象 |
| 27 | + */ |
| 28 | + private Context mContext; |
| 29 | + /** |
| 30 | + * 屏幕高度 |
| 31 | + */ |
| 32 | + private int mScreenHeight; |
| 33 | + /** |
| 34 | + * 屏幕宽度 |
| 35 | + */ |
| 36 | + private int mScreenWidth; |
| 37 | + |
| 38 | + /** |
| 39 | + * 波浪的画笔 |
| 40 | + */ |
| 41 | + private Paint mWavePaint; |
| 42 | + /** |
| 43 | + * 一个周期波浪的长度 |
| 44 | + */ |
| 45 | + private int mWaveLength; |
| 46 | + /** |
| 47 | + * 一个周期波浪的默认长度 |
| 48 | + */ |
| 49 | + private int mdefaultWaveLength = 500; |
| 50 | + |
| 51 | + /** |
| 52 | + * 屏幕宽度内波浪显示几个周期 |
| 53 | + */ |
| 54 | + private int mWaveCount; |
| 55 | + |
| 56 | + /** |
| 57 | + * 波纹的中间轴(基准线) |
| 58 | + */ |
| 59 | + private int mCenterY; |
| 60 | + /** |
| 61 | + * 波浪的路径 |
| 62 | + */ |
| 63 | + Path mWavePath; |
| 64 | + |
| 65 | + /** |
| 66 | + * 平移偏移量 |
| 67 | + */ |
| 68 | + private int mOffset; |
| 69 | + |
| 70 | + /** |
| 71 | + * 渐变色shader |
| 72 | + */ |
| 73 | + private Shader mShader; |
| 74 | + /** |
| 75 | + * 渐变色shade配置参数 |
| 76 | + */ |
| 77 | + private int colors[] = new int[2]; |
| 78 | + |
| 79 | + /** |
| 80 | + * 渐变波开始的颜色 |
| 81 | + */ |
| 82 | + private int mWaveStartColor; |
| 83 | + |
| 84 | + /** |
| 85 | + * 渐变波结束的颜色 |
| 86 | + */ |
| 87 | + private int mWaveEndColor; |
| 88 | + |
| 89 | + /** |
| 90 | + * 颜色渐变波默认开始颜色 |
| 91 | + */ |
| 92 | + private int mWaveDefaultStartColor; |
| 93 | + /** |
| 94 | + * 颜色渐变波默认结束颜色 |
| 95 | + */ |
| 96 | + private int mWaveDefaultEndColor; |
| 97 | + |
| 98 | + /** |
| 99 | + * 振幅 |
| 100 | + */ |
| 101 | + private int mWaveAmplitude; |
| 102 | + |
| 103 | + /** |
| 104 | + * 水波动画延时 |
| 105 | + */ |
| 106 | + private int mWaveDuration; |
| 107 | + |
| 108 | + private boolean mWaveFillTop; |
18 | 109 |
|
19 | | - private float lineX0; |
20 | | - private float lineY0; |
| 110 | + private boolean mWaveFillBottom; |
21 | 111 |
|
22 | | - private float lineX1; |
23 | | - private float lineY1; |
24 | 112 |
|
25 | 113 | public WaveView(Context context) { |
26 | | - super(context); |
27 | | - init(); |
| 114 | + this(context, null); |
28 | 115 | } |
29 | 116 |
|
30 | 117 | public WaveView(Context context, AttributeSet attrs) { |
31 | | - super(context, attrs); |
32 | | - init(); |
| 118 | + this(context, attrs, 0); |
33 | 119 | } |
34 | 120 |
|
35 | 121 | public WaveView(Context context, AttributeSet attrs, int defStyleAttr) { |
36 | 122 | super(context, attrs, defStyleAttr); |
| 123 | + mContext = context; |
| 124 | + mWaveDefaultStartColor = getResources().getColor(R.color.wave_start); |
| 125 | + mWaveDefaultEndColor = getResources().getColor(R.color.wave_end); |
| 126 | + getAttr(attrs); |
37 | 127 | init(); |
38 | 128 | } |
39 | 129 |
|
| 130 | + private void getAttr(AttributeSet attrs) { |
| 131 | + TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.WaveView); |
| 132 | + |
| 133 | + mWaveLength = typedArray.getDimensionPixelOffset(R.styleable.WaveView_waveLength, mdefaultWaveLength); |
| 134 | + mWaveDuration = typedArray.getDimensionPixelOffset(R.styleable.WaveView_waveDuration, 2000); |
| 135 | + mWaveAmplitude = typedArray.getDimensionPixelOffset(R.styleable.WaveView_waveAmplitude, dip2px(mContext, 20)); |
| 136 | + mWaveStartColor = typedArray.getColor(R.styleable.WaveView_waveStartColor, mWaveDefaultStartColor); |
| 137 | + mWaveEndColor = typedArray.getColor(R.styleable.WaveView_waveEndColor, mWaveDefaultEndColor); |
| 138 | + |
| 139 | + mWaveFillTop = typedArray.getBoolean(R.styleable.WaveView_mWaveFillTop, true); |
| 140 | + mWaveFillBottom = typedArray.getBoolean(R.styleable.WaveView_mWaveFillBottom, false); |
| 141 | + |
| 142 | + typedArray.recycle(); |
| 143 | + } |
| 144 | + |
40 | 145 | private void init() { |
41 | 146 | initPaint(); |
42 | | - |
| 147 | +Animation(); |
43 | 148 | } |
44 | 149 |
|
| 150 | + |
45 | 151 | /** |
46 | 152 | * 初始化画笔 |
47 | 153 | */ |
48 | 154 | private void initPaint() { |
49 | | - paint = new Paint(); |
50 | | - paint.setStrokeWidth(5); |
51 | | - paint.setStyle(Paint.Style.STROKE); |
52 | | - paint.setAlpha(60); |
53 | | - paint.setAntiAlias(true); |
| 155 | + |
| 156 | + mWavePath = new Path(); |
| 157 | + |
| 158 | + colors[0] = mWaveStartColor; |
| 159 | + colors[1] = mWaveEndColor; |
| 160 | + |
| 161 | + mWavePaint = new Paint(); |
| 162 | + |
| 163 | + mWavePaint.setStrokeWidth(1); |
| 164 | + mWavePaint.setStyle(Paint.Style.FILL_AND_STROKE); |
| 165 | + mWavePaint.setAntiAlias(true); |
| 166 | + |
54 | 167 | } |
55 | 168 |
|
56 | 169 |
|
| 170 | + @Override |
| 171 | + protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
| 172 | + super.onSizeChanged(w, h, oldw, oldh); |
| 173 | + mScreenHeight = h; |
| 174 | + mScreenWidth = w; |
| 175 | + |
| 176 | + mWaveCount = (int) Math.round(mScreenWidth / mWaveLength + 1.5); |
| 177 | + |
| 178 | + mCenterY = mScreenHeight - mWaveAmplitude; |
| 179 | + |
| 180 | + } |
| 181 | + |
57 | 182 | @Override |
58 | 183 | protected void onDraw(Canvas canvas) { |
59 | 184 | super.onDraw(canvas); |
60 | 185 |
|
| 186 | + mShader = new LinearGradient(0, 0, getWidth(), 0, colors, null, Shader.TileMode.CLAMP); |
| 187 | + mWavePaint.setShader(mShader); |
| 188 | + |
| 189 | + drawWave(canvas); |
| 190 | + } |
| 191 | + |
| 192 | + private void drawWave(Canvas canvas) { |
| 193 | + mWavePath.reset(); |
| 194 | + mWavePath.moveTo(-mWaveLength + mOffset, mCenterY); |
| 195 | + |
| 196 | + for (int i = 0; i < mWaveCount; i++) { |
| 197 | + mWavePath.quadTo((-mWaveLength * 3 / 4) + (i * mWaveLength) + mOffset, mCenterY + mWaveAmplitude, (-mWaveLength / 2) + (i * mWaveLength) + mOffset, mCenterY); |
| 198 | + mWavePath.quadTo((-mWaveLength / 4) + (i * mWaveLength) + mOffset, mCenterY - mWaveAmplitude, i * mWaveLength + mOffset, mCenterY); |
| 199 | + } |
| 200 | + if (mWaveFillTop) { |
| 201 | + fillTop(); |
| 202 | + } |
| 203 | + |
| 204 | + canvas.drawPath(mWavePath, mWavePaint); |
| 205 | + } |
| 206 | + |
| 207 | + |
| 208 | + /** |
| 209 | + * 填充波浪上面部分 |
| 210 | + */ |
| 211 | + private void fillTop() { |
| 212 | + mWavePath.lineTo(mScreenWidth, 0); |
| 213 | + mWavePath.lineTo(0, 0); |
| 214 | + mWavePath.close(); |
| 215 | + |
61 | 216 | } |
62 | 217 |
|
| 218 | + /** |
| 219 | + * 填充波浪下面部分 |
| 220 | + */ |
| 221 | + private void fillBottom() { |
| 222 | + //填充矩形 |
| 223 | + mWavePath.lineTo(mScreenWidth, mScreenHeight); |
| 224 | + mWavePath.lineTo(0, mScreenHeight); |
| 225 | + mWavePath.close(); |
| 226 | + |
| 227 | + } |
| 228 | + |
| 229 | + private void Animation() { |
| 230 | + |
| 231 | + ValueAnimator waveAnimator = ValueAnimator.ofInt(0, mWaveLength); |
| 232 | + waveAnimator.setDuration(mWaveDuration); |
| 233 | + waveAnimator.setRepeatCount(ValueAnimator.INFINITE); |
| 234 | + waveAnimator.setInterpolator(new LinearInterpolator()); |
| 235 | + waveAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { |
| 236 | + @Override |
| 237 | + public void onAnimationUpdate(ValueAnimator animation) { |
| 238 | + mOffset = (int) animation.getAnimatedValue(); |
| 239 | + invalidate(); |
| 240 | + } |
| 241 | + }); |
| 242 | + waveAnimator.start(); |
| 243 | + } |
| 244 | + |
| 245 | + /** |
| 246 | + * 单位转换工具类 |
| 247 | + * |
| 248 | + * @param context 上下文对象 |
| 249 | + * @param dipValue 值 |
| 250 | + * @return 返回值 |
| 251 | + */ |
| 252 | + public int dip2px(Context context, float dipValue) { |
| 253 | + final float scale = context.getResources().getDisplayMetrics().density; |
| 254 | + return (int) (dipValue * scale + 0.5f); |
| 255 | + } |
63 | 256 |
|
64 | 257 | } |
0 commit comments