安卓编辑剪切音乐控件

如图最近项目要做一个剪切音乐的控件,于是打算手写一个。

先分析一下,就是需要两个首尾的拉杆,开始的不能超过结束的,开始的不能低于起点,结束的不能低于开始的也不能高于终点。

package com.lewanjia.dancelog.views;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.lewanjia.dancelog.R;
import com.lewanjia.dancelog.utils.LogUtils;


/**
 * @autor lzj
 */
public class CutMusicLineSeekBar extends View {

    private Paint circlePaint;//
    private Paint circlePaintOver;//
    private Paint playPaint;


    private float mHeight;
    private float mWidth;
    //x轴的原点坐标
    private int xOri;
    //y轴的原点坐标
    private int yOri;

    private Context mContext;


    private Bitmap dotBitmapStart;
    private Bitmap dotBitmapEnd;


    private Drawable dotDrawableEnd;
    private Drawable dotDrawableStart;
    private float dotRadius;

    private float circleB = 0;//半径


    private final static int VAULE_3 = 3;
    private final static int VAULE_4 = 4;

    private float markPointX = 0;
    private float markPointY = 0;

    private float markPointXEnd = 0;
    private float markPointYEnd = 0;
    private float markPalyX = 0;


    private int maxProgress = 100;


    private float pointWidth;
    private float pointHeight;

    private float startProcess = 0;

    private float endProcess = 100;

    private float palyProcess= 0;

    public CutMusicLineSeekBar(Context context) {
        this(context, null);
    }

    public CutMusicLineSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CutMusicLineSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mContext = context;
        initView(context, attrs, defStyleAttr);
    }


    private void initView(Context context, AttributeSet attrs, int defStyleAttr) {
        TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CutMusicCircleSeekBar, defStyleAttr, 0);
        int count = array.getIndexCount();
        for (int i = 0; i < count; i++) {
            int attr = array.getIndex(i);
            switch (attr) {

            }
        }
        array.recycle();

    }

    /**
     * 初始化画笔
     */
    private void init() {
        circlePaint = new Paint();
        circlePaint.setColor(Color.parseColor("#a4a4a4"));
        circlePaint.setAntiAlias(true);
        circlePaint.setStyle(Paint.Style.STROKE);// 设置中空的样式
        circlePaint.setFlags(Paint.ANTI_ALIAS_FLAG);// 帮助消除锯齿
        circlePaint.setStrokeWidth(dip2px(mContext, VAULE_4));

        circlePaintOver = new Paint();
        circlePaintOver.setColor(Color.parseColor("#33000000"));
        circlePaintOver.setAntiAlias(true);
        circlePaintOver.setStyle(Paint.Style.FILL);// 设置中空的样式
        circlePaintOver.setFlags(Paint.ANTI_ALIAS_FLAG);// 帮助消除锯齿
        circlePaintOver.setStrokeWidth(dip2px(mContext, VAULE_4));


        playPaint = new Paint();
        playPaint.setColor(Color.parseColor("#FFAA00"));
        playPaint.setAntiAlias(true);
        playPaint.setStyle(Paint.Style.FILL);// 设置中空的样式
        playPaint.setFlags(Paint.ANTI_ALIAS_FLAG);// 帮助消除锯齿
        playPaint.setStrokeWidth(dip2px(mContext, 1));


        dotDrawableEnd = mContext.getResources().getDrawable(R.mipmap.image_cut_music_right);
        dotDrawableStart = mContext.getResources().getDrawable(R.mipmap.image_cut_music_left);
        if (dotDrawableStart != null) {
            dotBitmapStart = ((BitmapDrawable) dotDrawableStart).getBitmap();
            dotBitmapEnd = ((BitmapDrawable) dotDrawableEnd).getBitmap();
            dotRadius = Math.max(dotRadius, Math.max(dotBitmapStart.getWidth() / 2, dotBitmapStart.getHeight() / 2));
            circleB = getWidth() / 2 - dip2px(mContext, VAULE_3) - dotBitmapStart.getWidth() / 4;
            pointWidth = (float) dotBitmapEnd.getWidth();
            pointHeight = dotBitmapEnd.getHeight();
        }
        dotRadius = dotBitmapStart.getWidth() / 2;

        markPointXEnd = mWidth - pointWidth;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width;
        int height;
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = widthSize * 1 / 2;
        }
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = heightSize * 1 / 2;
        }

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mHeight = getHeight();
        mWidth = getWidth();
        xOri = getWidth() / 2;
        yOri = getHeight() / 2;
        markPointY = mHeight / 2;
        markPointYEnd = mHeight / 2;

        init();
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawBitmpStart(canvas);

        canvas.save();

    }

    float lastx;
    float lasty;
    boolean isOntouch = false;
    int moveFirst = 0;//0start 1end 2paly

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        isOntouch = true;
        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:
                lastx = event.getX();
                lasty = event.getY();
                double fisrt = distance(lastx, markPointX);
                double second = distance(lastx, markPointXEnd);
                double palyLine = distance(lastx, markPalyX);
                if (fisrt<=second&&fisrt<=palyLine){
                    moveFirst = 0;
                }else if (second<=fisrt&&second<=palyLine) {
                    moveFirst = 1;
                }else if (palyLine<fisrt&&palyLine<=second){
                    moveFirst = 2;
                }

                moved(lastx, lasty, false, event, moveFirst);
                return true;
            case MotionEvent.ACTION_MOVE:
                lastx = event.getX();
                lasty = event.getY();
                moved(lastx, lasty, false, event, moveFirst);
                Log.e("", "");
                return true;
            case MotionEvent.ACTION_UP:
                if (moveFirst==2){
                    if (onProcessChangeLister!=null){
                        onProcessChangeLister.changePaly(getPalyProgress());
                    }
                }
                return true;
//            case MotionEvent.ACTION_CANCEL:
//                f (moveFirst==2){
//                if (onProcessChangeLister!=null){
//                    onProcessChangeLister.changePaly(getPalyProgress());
//                }
//            }
//            return true;
        }
        return false;
    }


    private float distance(float x1, float x2) {
        return (float) Math.abs(x1 - x2);
    }

    public int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }


    /**
     * @param canvas
     */
    private void drawBitmpStart(Canvas canvas) {


        canvas.drawBitmap(dotBitmapStart, markPointX, 0, circlePaint);
        canvas.drawBitmap(dotBitmapEnd, markPointXEnd, 0, circlePaint);
//        circlePaintOver
        RectF rectF1 = new RectF();
        rectF1.left = 0;
        rectF1.right = markPointX;
        rectF1.top = dip2px(mContext, VAULE_4);
        rectF1.bottom = mHeight - dip2px(mContext, VAULE_4);

        RectF rectF2 = new RectF();

        rectF2.left = markPointXEnd + pointWidth;
        rectF2.right = mWidth;
        rectF2.top = dip2px(mContext, VAULE_4);
        rectF2.bottom = mHeight - dip2px(mContext, VAULE_4);


        RectF rectF3 = new RectF();
        rectF3.left = markPalyX + pointWidth;
        rectF3.right = markPalyX + pointWidth + dip2px(mContext, 2);
        rectF3.top = dip2px(mContext, VAULE_4);
        rectF3.bottom = mHeight - dip2px(mContext, VAULE_4);

        canvas.drawRect(rectF1, circlePaintOver);
        canvas.drawRect(rectF2, circlePaintOver);
        canvas.drawRect(rectF3, playPaint);

    }
    public void setPalyProgress(float progress){
        this.palyProcess = progress;
        markPalyX = (mWidth-pointWidth*2f)* progress/100f;
        invalidate();
    }

    public float getPalyProgress(){
        palyProcess =markPalyX/(mWidth-pointWidth*2f)*100f;
        LogUtils.E("456","palyProcess=="+palyProcess);
       return palyProcess>99.6?100:palyProcess;
    }
    public float getStartProgress(){
      startProcess = markPointX/(mWidth-pointWidth*2f)*100f;
      return startProcess>99.6?100:startProcess;

    }
    public float getEndProgress(){

        endProcess = (( markPointXEnd - pointWidth)/(mWidth-pointWidth*2f)*100f);
        return endProcess>99.6?100:endProcess;

    }

    public void setStartProgress(float progress){
        this.startProcess = progress;
        markPointX = (mWidth-pointWidth*2f)* progress/100f;
        invalidate();
        LogUtils.E("456","startProcess=="+startProcess);
        if (onProcessChangeLister != null) {
            onProcessChangeLister.changeStart(startProcess);
            onProcessChangeLister.changeEnd(endProcess);

        }
    }
    public void setEndProgress(float progress){
        this.endProcess = progress;
        markPointXEnd = (mWidth-pointWidth*2f)* progress/100f+pointWidth;
        invalidate();
        LogUtils.E("456","endProcess=="+endProcess);
        if (onProcessChangeLister != null) {
            onProcessChangeLister.changeStart(startProcess);
            onProcessChangeLister.changeEnd(endProcess);

        }
    }



    private void moved(float x, float y, boolean up, MotionEvent event, int moveFirst) {
        if (x < 0 || x > mWidth - pointWidth)
            return;

        if (moveFirst==0) {
            if (x >= markPointXEnd - pointWidth)
                return;
            markPointX = x;
            if (markPalyX < markPointX) {
                markPalyX = markPointX;
            }


        } else if (moveFirst==1){
            if (x <= markPointX + pointWidth)
                return;
            markPointXEnd = x;
//            if (markPalyX > markPointXEnd-pointWidth) {
//                markPalyX = markPointXEnd-pointWidth;
//            }

        }else {
            if (x >= mWidth - pointWidth*2)
                return;
            markPalyX= x;
        }

        if (onProcessChangeLister != null) {
            onProcessChangeLister.changeStart(getStartProgress());
            onProcessChangeLister.changeEnd(getEndProgress());

        }

        invalidate();
    }



    private OnProcessChangeLister onProcessChangeLister;

    public interface OnProcessChangeLister {
        void changeStart(float process);

        void changeEnd(float preocess);

        void changePaly(float preocess);
    }

    public void setOnProcessChangeLister(OnProcessChangeLister onProcessChangeLister) {
        this.onProcessChangeLister = onProcessChangeLister;

    }


    public int getMaxProgress() {
        return maxProgress;
    }


}

代码看起来也不复杂,只要理清逻辑就很简单。如果还需要音乐轨道的波浪图,可以评论

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值