Android simple custom music fluctuation special effect map

Time:2021-10-27

This example shares the specific code of Android simple custom music fluctuation special effect map for your reference. The specific contents are as follows

Final effect:

Idea: draw a rectangle with changing height or a wide dotted line

1. Custom attributes:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="musicPlayViewAttr">
        <!-- Pointer color -- >
        <attr name="point_color" format="color" />
        <!-- Number of pointers -- >
        <attr name="point_num" format="integer" />
        <!-- Pointer width -- >
        <attr name="point_width" format="float" />
        <!-- Pointer fluctuation speed -- >
        <attr name="point_speed" format="integer" />
    </declare-styleable>
</resources>

2. Write a custom musicplayview

/**
 *Music play wave animation
 */
 
public class MusicPlayView extends View {
    //Coordinate origin x
    private float mBasePointX;
 
    //Coordinate origin y
    private float mBasePointY;
 
    //The number of pointers defaults to 10
    private int mPointNum;
 
    //The gap between pointers is 5dp by default
    private float mPointSpace;
 
    //The width of each pointer is 5dp by default
    private float mPointWidth;
 
    //The color of the pointer
    private int mPointColor = Color.RED;
 
    //Collection of pointers
    private List<Pointer> mPoints;
 
    //Control start / stop
    private boolean mIsPlaying = false;
 
    //Playback thread
    private Thread mPlayThread;
 
    //Pointer fluctuation speed
    private int mPointSpeed;
 
    //Brush
    private Paint mPaint;
 
    public MusicPlayView(Context context) {
        super(context);
        init();
    }
 
    public MusicPlayView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        //Get custom attributes
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.musicPlayViewAttr);
        mPointNum = ta.getInt(R.styleable.musicPlayViewAttr_point_num, 10);
        mPointWidth = dp2px(getContext(),
                ta.getFloat(R.styleable.musicPlayViewAttr_point_width, 5f));
        mPointColor = ta.getColor(R.styleable.musicPlayViewAttr_point_color, Color.RED);
        mPointSpeed = ta.getInt(R.styleable.musicPlayViewAttr_point_speed, 40);
        init();
    }
 
    public MusicPlayView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.musicPlayViewAttr);
        mPointNum = ta.getInt(R.styleable.musicPlayViewAttr_point_num, 10);
        mPointWidth = dp2px(getContext(), ta.getFloat(R.styleable.musicPlayViewAttr_point_width, 5f));
        mPointColor = ta.getColor(R.styleable.musicPlayViewAttr_point_color, Color.RED);
        mPointSpeed = ta.getInt(R.styleable.musicPlayViewAttr_point_speed, 40);
        init();
    }
 
    /**
     *Initialize brush
     */
    private void init() {
        mPoints = new ArrayList<>();
        //Draw dashed line
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(mPointColor);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(mPointWidth);
        mPaint.setPathEffect(new DashPathEffect(new float[]{25, 15}, 0));// Dotted line interval
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }
 
    /**
     *Set the pointer height and that
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //Gets the y of the logical origin
        mBasePointY = getHeight() - getPaddingBottom();
        Random random = new Random();
        if (mPoints != null)
            mPoints.clear();
        for (int i = 0; i < mPointNum; i++) {
            //Random height
            mPoints.add(new Pointer((float) (0.1 * (random.nextInt(10) + 1) * (getHeight() - getPaddingBottom() - getPaddingTop()))));
        }
        //Calculate the interval width between each pointer - the padding around - the total width of all pointers divided by how many intervals
        mPointSpace = (getWidth() - getPaddingLeft() - getPaddingRight() - mPointWidth * mPointNum) / (mPointNum - 1);
 
    }
 
 
    /**
     *Start drawing dashed lines
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //Pointer x position
        mBasePointX = 0f + getPaddingLeft() + mPointWidth / 2;
        //Draw each pointer.
        for (int i = 0; i < mPoints.size(); i++) {
            //Draw dashed line
            float[] pts = {mBasePointX, getHeight(), mBasePointX, (mBasePointY - mPoints.get(i).getHeight())};// Redo up animation
            canvas.drawLines(pts, mPaint);
            //Update pointer x position
            mBasePointX += (mPointSpace + mPointWidth);
        }
    }
 
    /**
     *Start thread playback
     */
    public void start() {
        setVisibility(VISIBLE);
        if (!mIsPlaying) {
            if (mPlayThread == null) {
                mPlayThread = new Thread(new PlayRunnable());
                mPlayThread.start();
            }
            mIsPlaying = true;// Control loops in child threads
        }
    }
 
    /**
     *Stop thread stop playback
     */
    public void stop() {
        setVisibility(INVISIBLE);
        mIsPlaying = false;
        invalidate();
    }
 
    /**
     *Update UI
     */
    private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            invalidate();
        }
    };
 
    /**
     *Sub thread, loop to change the height of each pointer
     */
    public class PlayRunnable implements Runnable {
 
        @Override
        public void run() {
            for (float i = 0; i < Integer.MAX_VALUE; ) {
                try {
                    for (int j = 0; j < mPoints.size(); j++) {
                        float rate = (float) Math.abs(Math.sin(i + j));// random number
                        mPoints.get(j).setHeight((mBasePointY - getPaddingTop()) * rate); // Height of each pointer
                    }
                    Thread.sleep(mPointSpeed);// Control animation speed
                    //Start / pause
                    if (mIsPlaying) {
                        myHandler.sendEmptyMessage(0);
                        i += 0.1;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
 
    /**
     *Pointer object
     */
    public class Pointer {
        private float height;
 
        public Pointer(float height) {
            this.height = height;
        }
 
        public float getHeight() {
            return height;
        }
 
        public void setHeight(float height) {
            this.height = height;
        }
    }
 
    /**
     *DP to PX
     */
    public static int dp2px(Context context, float dpVal) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources()
                .getDisplayMetrics());
    }
}

3. In activity_ Using musicplayview in main2 layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
 
    <com.hk.testapplication.MusicPlayView
        android:id="@+id/music_play"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:visibility="invisible"
        android:padding="10dp"
        app:point_color="#F44336"
        app:point_num="10"
        app:point_width="14" />
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <Button
            android:id="@+id/bt_play"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            Android: text = "play" / >
        <Button
            android:id="@+id/bt_stop"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginRight="20dp"
            Android: text = "stop" / >
 
    </LinearLayout>
 
</LinearLayout>

4. Used in mainactivity

public class MainActivity2 extends AppCompatActivity implements View.OnClickListener {
    private Button mBtPlay,mBtStop;
    private MusicPlayView mMusicPlayView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        mMusicPlayView = findViewById(R.id.music_play);
        mBtPlay = findViewById(R.id.bt_play);
        mBtStop = findViewById(R.id.bt_stop);
        mBtPlay.setOnClickListener(this);
        mBtStop.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_play:
                //Start playing
                mMusicPlayView.start();
                break;
            case R.id.bt_stop:
                //Stop playing
                mMusicPlayView.stop();
                break;
 
        }
    }
}

Because the comments are very detailed, there is not much introduction. I just provide an idea here. There are many places that can be optimized, such as thread use and loop. If you don’t understand, you can leave a message.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support developpaer.

Recommended Today

OC basis

IOS development interview essential skills chart.png What are objects and what are the objects in OC? An object is an instance of a class; Is an instance created through a class, which is generally called an instance object; Common objects in OC include instance objects, class objects, and metaclass objects; What is a class? What […]