package com.goshenapps.clipboard.Siri; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.view.View; import com.goshenapps.clipboard.R; public class SiriWaveView extends View { private Path mPath; private Paint mPaint; private float frequency = 1.5f; private float IdleAmplitude = 0.00f; private int waveNumber = 2; private float phaseShift = 0.15f; private float initialPhaseOffset = 0.0f; private float waveHeight; private float waveVerticalPosition = 2; private int waveColor; private float phase; private float amplitude; private float level = 1.0f; ObjectAnimator mAmplitudeAnimator; public SiriWaveView(Context context) { super(context); if (!isInEditMode()) init(context, null); } public SiriWaveView(Context context, AttributeSet attrs) { super(context, attrs); if (!isInEditMode()) init(context, attrs); } public SiriWaveView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (!isInEditMode()) init(context, attrs); } public void init(Context context, AttributeSet attrs) { TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SiriWaveView); frequency = a.getFloat(R.styleable.SiriWaveView_waveFrequency, frequency); IdleAmplitude = a.getFloat(R.styleable.SiriWaveView_waveIdleAmplitude, IdleAmplitude); phaseShift = a.getFloat(R.styleable.SiriWaveView_wavePhaseShift, phaseShift); initialPhaseOffset = a.getFloat(R.styleable.SiriWaveView_waveInitialPhaseOffset, initialPhaseOffset); waveHeight = a.getDimension(R.styleable.SiriWaveView_waveHeight, waveHeight); waveColor = a.getColor(R.styleable.SiriWaveView_waveColor, waveColor); waveVerticalPosition = a.getFloat(R.styleable.SiriWaveView_waveVerticalPosition, waveVerticalPosition); waveNumber = a.getInteger(R.styleable.SiriWaveView_waveAmount, waveNumber); mPath = new Path(); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(2); mPaint.setColor(waveColor); a.recycle(); initAnimation(); } private void initAnimation() { if (mAmplitudeAnimator == null) { mAmplitudeAnimator = ObjectAnimator.ofFloat(this, "amplitude", 1f); mAmplitudeAnimator.setRepeatCount(ObjectAnimator.INFINITE); } if (!mAmplitudeAnimator.isRunning()) { mAmplitudeAnimator.start(); } } @Override protected void onDraw(Canvas canvas) { canvas.drawPath(mPath, mPaint); updatePath(); } private void updatePath() { mPath.reset(); phase += phaseShift; amplitude = Math.max(level, IdleAmplitude); for (int i = 0; i < waveNumber; i++) { float halfHeight = getHeight() / waveVerticalPosition; float width = getWidth(); float mid = width / 2.0f; float maxAmplitude = halfHeight - (halfHeight - waveHeight); // Progress is a value between 1.0 and -0.5, determined by the current wave idx, which is used to alter the wave's amplitude. float progress = 1.0f - (float) i / waveNumber; float normedAmplitude = (1.5f * progress - 0.5f) * amplitude; float multiplier = (float) Math.min(1.0, (progress / 3.0f * 2.0f) + (1.0f / 3.0f)); for (int x = 0; x < width; x++) { float scaling = (float) (-Math.pow(1 / mid * (x - mid), 2) + 1); float y = (float) (scaling * maxAmplitude * normedAmplitude * Math.sin(2 * Math.PI * (x / width) * frequency + phase + initialPhaseOffset) + halfHeight); if (x == 0) { mPath.moveTo(x, y); } else { mPath.lineTo(x, y); } } } //mPath.close(); } private void setAmplitude(float amplitude) { this.amplitude = amplitude; invalidate(); } private float getAmplitude() { return this.amplitude; } public void stopAnimation() { if (mAmplitudeAnimator != null) { mAmplitudeAnimator.removeAllListeners(); mAmplitudeAnimator.end(); mAmplitudeAnimator.cancel(); } } public void startAnimation() { if (mAmplitudeAnimator != null) { mAmplitudeAnimator.start(); } } public void setWaveColor(int waveColor) { mPaint.setColor(waveColor); invalidate(); } public void setStrokeWidth(float strokeWidth) { mPaint.setStrokeWidth(strokeWidth); invalidate(); } }