效果图:
我们看xml:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FDE7F1">
<RelativeLayout
android:layout_width="284dp"
android:layout_height="284dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="45dp"
android:background="@drawable/background">
<nickgao.com.viewpagerswitchexample.view.WaveView
android:id="@+id/wave_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="36dp" />
<ProgressBar
android:id="@+id/temperature_device_loading_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="36dp"
android:indeterminateDrawable="@drawable/device_loading_bg" />
</RelativeLayout>
</RelativeLayout>
activity中调用:
WaveView mRateWave = (WaveView)findViewById(R.id.wave_view);
mRateWave.setWaveColor(getResources().getColor(R.color.color_9ff0f0), getResources().getColor(R.color.color_5ad3d3));
mRateWave.setBorder(DensityUtil.dp2px(this, 2), getResources().getColor(R.color.color_9ff0f0));
mWaveHelper = new WaveHelper(mRateWave);
mRateWave.setShowWave(true);
mRateWave.setWaveLengthRatio(1f);
mWaveHelper.start(0.7f);
WaveView的代码是:
public class WaveView extends View {
private static final float DEFAULT_AMPLITUDE_RATIO = 0.05f;
private static final float DEFAULT_WATER_LEVEL_RATIO = 0.5f;
private static final float DEFAULT_WAVE_LENGTH_RATIO = 1.0f;
private static final float DEFAULT_WAVE_SHIFT_RATIO = 0.0f;
public static final int DEFAULT_BEHIND_WAVE_COLOR = Color.parseColor("#28FFFFFF");
public static final int DEFAULT_FRONT_WAVE_COLOR = Color.parseColor("#3CFFFFFF");
public static final ShapeType DEFAULT_WAVE_SHAPE = ShapeType.CIRCLE;
public enum ShapeType {
CIRCLE,
SQUARE
}
// if true, the shader will display the wave
private boolean mShowWave;
// shader containing repeated waves
private BitmapShader mWaveShader;
// shader matrix
private Matrix mShaderMatrix;
// paint to draw wave
private Paint mViewPaint;
// paint to draw border
private Paint mBorderPaint;
private float mDefaultAmplitude;
private float mDefaultWaterLevel;
private float mDefaultWaveLength;
private double mDefaultAngularFrequency;
private float mAmplitudeRatio = DEFAULT_AMPLITUDE_RATIO;
private float mWaveLengthRatio = DEFAULT_WAVE_LENGTH_RATIO;
private float mWaterLevelRatio = DEFAULT_WATER_LEVEL_RATIO;
private float mWaveShiftRatio = DEFAULT_WAVE_SHIFT_RATIO;
private int mBehindWaveColor = DEFAULT_BEHIND_WAVE_COLOR;
private int mFrontWaveColor = DEFAULT_FRONT_WAVE_COLOR;
private ShapeType mShapeType = DEFAULT_WAVE_SHAPE;
public WaveView(Context context) {
super(context);
init();
}
public WaveView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public WaveView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mShaderMatrix = new Matrix();
mViewPaint = new Paint();
mViewPaint.setAntiAlias(true);
}
public float getWaveShiftRatio() {
return mWaveShiftRatio;
}
/**
* Shift the wave horizontally according to <code>waveShiftRatio</code>.
*
* @param waveShiftRatio Should be 0 ~ 1. Default to be 0.
* Result of waveShiftRatio multiples width of WaveView is the length to shift.
*/
public void setWaveShiftRatio(float waveShiftRatio) {
if (mWaveShiftRatio != waveShiftRatio) {
mWaveShiftRatio = waveShiftRatio;
invalidate();
}
}
public float getWaterLevelRatio() {
return mWaterLevelRatio;
}
/**
* Set water level according to <code>waterLevelRatio</code>.
*
* @param waterLevelRatio Should be 0 ~ 1. Default to be 0.5.
* Ratio of water level to WaveView height.
*/
public void setWaterLevelRatio(float waterLevelRatio) {
if (mWaterLevelRatio != waterLevelRatio) {
mWaterLevelRatio = waterLevelRatio;
invalidate();
}
}
public float getAmplitudeRatio() {
return mAmplitudeRatio;
}
/**
* Set vertical size of wave according to <code>amplitudeRatio</code>
*
* @param amplitudeRatio Default to be 0.05. Result of amplitudeRatio + waterLevelRatio should be less than 1.
* Ratio of amplitude to height of WaveView.
*/
public void setAmplitudeRatio(float amplitudeRatio) {
if (mAmplitudeRatio != amplitudeRatio) {
mAmplitudeRatio = amplitudeRatio;
invalidate();
}
}
public float getWaveLengthRatio() {
return mWaveLengthRatio;
}
/**
* Set horizontal size of wave according to <code>waveLengthRatio</code>
*
* @param waveLengthRatio Default to be 1.
* Ratio of wave length to width of WaveView.
*/
public void setWaveLengthRatio(float waveLengthRatio) {
mWaveLengthRatio = waveLengthRatio;
}
public boolean isShowWave() {
return mShowWave;
}
public void setShowWave(boolean showWave) {
mShowWave = showWave;
}
public void setBorder(int width, int color) {
if (mBorderPaint == null) {
mBorderPaint = new Paint();
mBorderPaint.setAntiAlias(true);
mBorderPaint.setStyle(Style.STROKE);
}
mBorderPaint.setColor(color);
mBorderPaint.setStrokeWidth(width);
invalidate();
}
public void setWaveColor(int behindWaveColor, int frontWaveColor) {
mBehindWaveColor = behindWaveColor;
mFrontWaveColor = frontWaveColor;
if (getWidth() > 0 && getHeight() > 0) {
// need to recreate shader when color changed
mWaveShader = null;
createShader();
invalidate();
}
}
public void setShapeType(ShapeType shapeType) {
mShapeType = shapeType;
invalidate();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
createShader();
}
/**
* Create the shader with default waves which repeat horizontally, and clamp vertically
*/
private void createShader() {
mDefaultAngularFrequency = 2.0f * Math.PI / DEFAULT_WAVE_LENGTH_RATIO / getWidth();
mDefaultAmplitude = getHeight() * DEFAULT_AMPLITUDE_RATIO;
mDefaultWaterLevel = getHeight() * DEFAULT_WATER_LEVEL_RATIO;
mDefaultWaveLength = getWidth();
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint wavePaint = new Paint();
wavePaint.setStrokeWidth(2);
wavePaint.setAntiAlias(true);
// Draw default waves into the bitmap
// y=Asin(ωx+φ)+h
final int endX = getWidth() + 1;
final int endY = getHeight() + 1;
float[] waveY = new float[endX];
wavePaint.setColor(mBehindWaveColor);
for (int beginX = 0; beginX < endX; beginX++) {
double wx = beginX * mDefaultAngularFrequency;
float beginY = (float) (mDefaultWaterLevel + mDefaultAmplitude * Math.sin(wx));
canvas.drawLine(beginX, beginY, beginX, endY, wavePaint);
waveY[beginX] = beginY;
}
wavePaint.setColor(mFrontWaveColor);
final int wave2Shift = (int) (mDefaultWaveLength / 4);
for (int beginX = 0; beginX < endX; beginX++) {
canvas.drawLine(beginX, waveY[(beginX + wave2Shift) % endX], beginX, endY, wavePaint);
}
// use the bitamp to create the shader
mWaveShader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
mViewPaint.setShader(mWaveShader);
}
@Override
protected void onDraw(Canvas canvas) {
// modify paint shader according to mShowWave state
if (mShowWave && mWaveShader != null) {
// first call after mShowWave, assign it to our paint
if (mViewPaint.getShader() == null) {
mViewPaint.setShader(mWaveShader);
}
// sacle shader according to mWaveLengthRatio and mAmplitudeRatio
// this decides the size(mWaveLengthRatio for width, mAmplitudeRatio for height) of waves
mShaderMatrix.setScale(
mWaveLengthRatio / DEFAULT_WAVE_LENGTH_RATIO,
mAmplitudeRatio / DEFAULT_AMPLITUDE_RATIO,
0,
mDefaultWaterLevel);
// translate shader according to mWaveShiftRatio and mWaterLevelRatio
// this decides the start position(mWaveShiftRatio for x, mWaterLevelRatio for y) of waves
mShaderMatrix.postTranslate(
mWaveShiftRatio * getWidth(),
(DEFAULT_WATER_LEVEL_RATIO - mWaterLevelRatio) * getHeight());
// assign matrix to invalidate the shader
mWaveShader.setLocalMatrix(mShaderMatrix);
float borderWidth = mBorderPaint == null ? 0f : mBorderPaint.getStrokeWidth();
switch (mShapeType) {
case CIRCLE:
if (borderWidth > 0) {
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f,
(getWidth() - borderWidth) / 2f - 1f, mBorderPaint);
}
float radius = getWidth() / 2f - borderWidth;
canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, radius, mViewPaint);
break;
case SQUARE:
if (borderWidth > 0) {
canvas.drawRect(
borderWidth / 2f,
borderWidth / 2f,
getWidth() - borderWidth / 2f - 0.5f,
getHeight() - borderWidth / 2f - 0.5f,
mBorderPaint);
}
canvas.drawRect(borderWidth, borderWidth, getWidth() - borderWidth,
getHeight() - borderWidth, mViewPaint);
break;
}
} else {
mViewPaint.setShader(null);
}
}
}
github:https://github.com/nickgao1986/WaveHeader
如果你觉得效果好,请帮忙点个赞,谢谢