音乐播放时跳动的音符

package com.ble.gsense.rbq.view;

/**
 * Created by rbq on 2016/12/8.
 */
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;

import com.ble.gsense.rbq.R;


public class MusicPlayBarView extends View {

    private byte[] mBytes;
    private Rect mRect = new Rect();
    private Paint mForePaint = new Paint();

    //添加这个标志的原因是用于判断当前是否进入循环了。如果没有则在onDraw()方法的时候进入。为什么需要这样呢。原因是RecyclerView的一个资源节约的机制来的,在item不在页面显示中的时候就会销毁掉这个View,导致无法在重新进入的时候跳动。然后就是有的时候他不会销毁,但是会暂停住整个状态,就是这个item处于第一个超出界面的item时不会销毁(个人猜测没看源码)。所以导致了滑动RecyclerView回来之后不会跳动的问题。所以添加这个用于解决此问题。
    private AtomicBoolean mInHandlerFlag=new AtomicBoolean(false);


    public MusicPlayBarView (Context context) {
        super(context);
        init();
    }


    public MusicPlayBarView (Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }


    public MusicPlayBarView (Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    public boolean isShow() {
        return super.isShown();
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        mInHandlerFlag.set(false);

    }
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            if (!MusicPlayBarView .this.isShown())
                return;

            mHandler.removeMessages(0);
            mInHandlerFlag.set(true);
            Random random = new Random();
            byte[] bytes = getBytes(987);

            bytes = getBytes(random.nextInt());
            if (isShow.get()) {
                mHandler.sendEmptyMessageDelayed(0, 100);
            }
            updateVisualizer(bytes);
        }
    };


    public void show() {
        if (!isShow.get()) {
            isShow.set(true);
            mHandler.sendEmptyMessage(0);
        }


    }
    public void hide() {
        isShow.set(false);
        mHandler.sendEmptyMessage(0);
    }


    private AtomicBoolean isShow = new AtomicBoolean(false);


    private byte[] getBytes(int data) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        bytes[2] = (byte) ((data & 0xff0000) >> 16);
        bytes[3] = (byte) ((data & 0xff000000) >> 24);
        return bytes;
    }


    public static byte[] getBytes(long data) {
        byte[] bytes = new byte[8];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data >> 8) & 0xff);
        bytes[2] = (byte) ((data >> 16) & 0xff);
        bytes[3] = (byte) ((data >> 24) & 0xff);
        bytes[4] = (byte) ((data >> 32) & 0xff);
        bytes[5] = (byte) ((data >> 40) & 0xff);
        bytes[6] = (byte) ((data >> 48) & 0xff);
        bytes[7] = (byte) ((data >> 56) & 0xff);
        return bytes;
    }


    public byte[] getBytes(float data) {
        int intBits = Float.floatToIntBits(data);
        return getBytes(intBits);
    }


    public byte[] getBytes(double data) {
        long intBits = Double.doubleToLongBits(data);
        return getBytes(intBits);
    }


    private void init() {
        mBytes = null;
        mForePaint.setStrokeWidth(1f);
        mForePaint.setAntiAlias(true);
        mForePaint.setColor(Color.rgb(0, 143, 229));
    }


    public void updateVisualizer(byte[] bytes) {
        byte[] model = new byte[bytes.length];
        for (int i = 0; i < bytes.length - 1; i++) {
            model[i] = bytes[i];
        }
        mBytes = bytes;
        invalidate();
    }


    private void drawRect(float left, float width, float top, Canvas canvas) {
        final float right = left + width;
        final float bottom = getHeight();
        final float thickness = 3.0f;
        float currenttop = bottom;
        while (true) {
            canvas.drawRect(left, currenttop - thickness, right, currenttop,
                    mForePaint);
            currenttop -= thickness;

            if (currenttop <= top)
                break;
        }
    }



    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if(isShow.get()&&!mInHandlerFlag.get()){
            mHandler.sendEmptyMessage(0);
            return;
        }
        if (mBytes == null) {
            return;
        }
        int sum = 0;
        for (int i = 0; i < mBytes.length; i++)
            sum += mBytes[i];


        if (sum == 0)
            return;


        mRect.set(0, 0, getWidth(), getHeight());
        int length = mBytes.length;
        final float width = getResources().getDimensionPixelSize(
                R.dimen.music_play_animation_width);// play bar width
        final float blankWidth = getResources().getDimensionPixelSize(
                R.dimen.music_play_animation_blank_area_width);// blank area width
        final float lastOffSet = width + blankWidth;
        float left, top;
        for (int i = 0; i < length; i++) {
            left = lastOffSet * i;// every play bar start x position.
            top = mRect.height() / 2 + ((byte) mBytes[i])
                    * (mRect.height() / 2) / 128;
            drawRect(left, width, top, canvas);
        }
    }
}
原文地址:https://www.cnblogs.com/Free-Thinker/p/6144980.html