Created “bars and waves” visualization for media resource playback

1 the screenshot

2.

XML attributes provided by 1

  • BarColor horizontal barColor
  • BarHeight Height of the bar
  • WaveRange range of wavy bars (difference between highest and lowest)
  • waveMinHeight
  • WaveColor Minimum height of wavy bar
  • WaveWidth Wavy bar color
  • WaveNumber Width of a wave bar
  • WaveInterval Number of wavy bars

2 Main Methods

  1. setFallAutomaticallyEnable(boolean enable)Automatically fall when the waveMinHeight is set to greater than the waveMinHeight (using property animation).
  2. setWaveHeight(float[] hs)Set the height of the waveMinHeight. The height value is a floating point number ranging from 0 to 1, that is, the percentage of the waveRange. When 0 is waveMinHeight, the waveMinHeight is waveMinHeight + waveRange.
  3. setWaveColor(int[] color)Sets the color of a wavy bar. This method sets the specified color for each wavy bar.
  4. setWaveColor(int[][] color)Sets the color of the wavy bar, specifying two colors for each wavy bar that will be drawn as a vertical gradient.
  5. setWaveColor(int color)Set the color of the wavy bar so that all wavy bars display the same color.
  6. setBarColor(int color)Sets the color of the bar.
  7. setFallDuration(int duration)Set the animation duration when Auto Fall is enabled. If Auto Fall is not enabled, this method will enable Auto Fall.

3 How to Use it

Copy the barwavesView.java file from the library into your project, changing the package name, and at the same time copy the attrs properties from the library directory into your own attrs (if you don’t have the attrs file, copy the file directly).

Use in XML:

<! -- Remember to change the package name --! > <com.duan.library.BarWavesView android:id="@+id/BarWavesView_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="-230dp" app:waveNumber="35" app:waveWidth="30dp" app:waveRange="600dp" app:waveMinHeight="0dp" app:waveInterval="5dp" app:waveColor="#7eaeaeae" app:barHeight="0dp" />Copy the code

Used in Java:

// omit the code
public class MainActivity extends AppCompatActivity {
    private BarWavesView barWavesView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        barWavesView = (BarWavesView) findViewById(R.id.BarWavesView);
        barWavesView.setBarColor(ColorUtils.getRandomColor()); / / ColorUtils getRandomColor () to obtain a random color
        
        int[][] cs = new int[barWavesView.getWaveNumber()][2];
        for (int i = 0; i < cs.length; i++) {
            // Control allows you to set a separate color for each wavy bar. The two colors will be drawn as a vertical gradient
            cs[i][0] = ColorUtils.getRandomColor(); 
            cs[i][1] = ColorUtils.getRandomColor();
        }
        barWavesView.setWaveColor(cs);
        
        // barWavesView.setWaveHeight(float[] hs); Modifies control wavy bar height}}// omit the code
Copy the code

See app module example for details.

4 Principle Analysis

4.1 onMeasure

The onMeasure method is used to measure the width and height of the control and adjust the property size of the control.

  • Width = mWaveWidth * mWaveNumber + mWaveInterval * (mWaveNumber – 1); height = mWaveMinHeight + mWaveRange + mBarHeight;

  • When the control width or height is specified as march_parent or a specific value in XML, the width and height will be adjusted to fit the specified width and height using the corresponding adjustment strategy. (In most cases, the control user cannot allocate the width and height properly with fixed width and height. Calculate the number, width and gap of the wave bar to fit the current width and height. The method of adjustment is to adjust the specified properties or default properties in XML so that they are suitable for width and height with minimal modification of the specified properties. Width adjustment method:

private void adjustWidth(int width) {

        while (width < mWaveInterval * (mWaveNumber - 1) + mWaveWidth * mWaveNumber) {
            if (mWaveInterval > sMIN_WAVE_INTERVAL) {
                mWaveInterval--; // Adjust the wavy bar spacing
            } else {
                if (mWaveWidth > sMIN_WAVE_WIDTH) {
                    mWaveWidth--; // Select adjust wavy bar width
                } else {
                    width++; // Adjust the width of the setting as necessary}}}}Copy the code

Height adjustment method:

private void adjustHeight(int height) {

        while (mWaveMinHeight + mWaveRange + mBarHeight > height) {
            if (mBarHeight > sMIN_BAR_HEIGHT) {
                mBarHeight--; // Adjust the height of the bar
                continue;
            }

            if (mWaveMinHeight > sMIN_WAVE_HEIGHT) {
                mWaveMinHeight--; // Adjust the minimum height of the wavy bar
                continue;
            }

            if (mWaveRange > sMIN_WAVE_RANGE) {
                mWaveRange--; // Select adjust wavy bar range again}}}Copy the code
  • Control does not adapt properties such as padding and min/maxHeight
4.2 onLayout

The onLayout method is used to determine the position of the control within its parent control and is not overridden.

4.3 ontouch

The onDraw method is responsible for drawing the control, in which the main need to draw two parts: wavy bar, horizontal bar.

  • Draw the stripes
private void drawBar(Canvas canvas) {
        mPaint.setShader(null); // Draw the tilde bar so that the gradient shader is used, which is cleared here
        mPaint.setAlpha(255); // Draw a wavy bar so that the color may have an alpha layer. This should be removed, otherwise the alpha value will remain and interfere with the drawing of the bar
        mPaint.setColor(mBarColor);
        float right = mWaveInterval * (mWaveNumber - 1) + mWaveWidth * mWaveNumber; // The length of the bar is determined by the attributes of the wavy bar
        float top = getHeight() - mBarHeight;
        canvas.drawRect(0, top, right, getHeight(), mPaint);
    }
Copy the code
  • Draw wavy bar
private void drawWaves(Canvas canvas) {

        for (int i = 0; i < mWaveNumber; i++) {
            float left = mWaveWidth * i + mWaveInterval * i;
            float right = left + mWaveWidth;

            float bottom = getHeight() - mBarHeight;
            float fs = mWaveHeight[i];
            float top;
            top = bottom - mWaveMinHeight - (fs * mWaveRange); // Calculate the height to be drawn from the percentage, and then calculate its top coordinate value.
            LinearGradient lg = new LinearGradient(
                    left, bottom,
                    right, top,
                    mWaveColors[i],
                    null,
                    Shader.TileMode.CLAMP
            );
            mPaint.setAlpha(255); mPaint.setShader(lg); canvas.drawRect(left, top, right, bottom, mPaint); }}Copy the code
4.5 Modify the wavy bar height

To change the wavy bar height, simply pass in the new percentage array of wavy bar height. If Auto Fall animation is enabled, stop the animation first and redraw it again.

public void setWaveHeight(float[] hs) {
        if(mFallAnimEnable && mAnim ! =null && (mAnim.isStarted() || mAnim.isRunning())) {
            mAnim.cancel();
        }

        setWaveHeights(hs);
        invalidate();

        if (mFallAnimEnable) {
            if (mAnim == null) { initAnim(mFallDuration); } mAnim.start(); }}...private void setWaveHeights(float[] hs) {
        if (hs == null|| hs.length ! = mWaveNumber) {return;
        }
        mWaveHeight = hs;
    }
Copy the code
4.6 “Auto Fall” animation

Falls “automatic” animation initialization is as follows: use the property animation, update article traverse wave in animation attribute value, change from the current value of the height of the wave of accounted decline to 0, pay attention to in the article mWaveHeight for wave height is greater than the minimum height and less than the minimum height with poor part of array (wave height calculation for: MWaveHeight + mWaveHeight[I])

private void initAnim(int dur) {
        mAnim = ObjectAnimator.ofFloat(1.0 f.0.0 f);
        mAnim.setInterpolator(new AccelerateDecelerateInterpolator());
        mAnim.setDuration(dur);
        mAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float v = (float) animation.getAnimatedValue();
                for (int i = 0; i < mWaveHeight.length; i++) { mWaveHeight[i] *= v; } invalidate(); }}); }Copy the code

GitHub address: DuanJiaNing/BarWavesVew