Android 实现音乐剪切功能 可以选择起始点和结束点 也可以同时拖动块级元素

时间:2021-09-28 16:22:32

先看一下最终的效果

Android 实现音乐剪切功能 可以选择起始点和结束点 也可以同时拖动块级元素

用户可以拖动两边来改变要截取音乐的长度,也可以直接拖红线来改变要截取音乐的位置


唯一的难点就是要计算出当前选择了多少秒,还有拖动时候的操作,我是直接创建的布局元素,通过onlayout()方法来改变控件的位置,废话不多说,直接上部分源代码

之前上传的代码有一些问题  现在重新上传 而且我们需求也跟着变了,因为之前写的代码 是按照歌曲的时间来百分比剪切,这样会造成如果大的文件剪切出来的文件会很大,现在我们限制一下最大最小的值    代码逻辑,   中间的进度条 我们按照默认1分钟来实现,每次进来的时候最小值为0.3 最大值为0.4 这样在宽度上会对用户的体验提高,这次直接附上所有源代码



//=========代码=====



/**  * Created by mazhuang on 10/8/17.  */  public class MusicIntercept extends RelativeLayout {

    private ImageView leftView;
    private LinearLayout lineLayout;
    private View view;
    private ImageView rightView;
    private RelativeLayout sliderLayout;

    private double minX;//最小值
    private double maxX;//最大值

    private int duration;//音乐时长  秒

    private int leftMargin;//左边距
    private int rightMargin;//右边距

    private double totalWidth;//总宽度

    private TextView tvStartView;
    private TextView tvEndView;

    private OnMusicInterceptListener listener;

    public void setListener(OnMusicInterceptListener listener) {
        this.listener = listener;
    }

    public interface OnMusicInterceptListener {
        void onTimeChange(int lTime, int rTime);

        void onStartChange(int lTime, int time);
    }

    public int setDuration(int duration) {
        this.duration = (duration / 1000);

        tvStartView.setText("00:00");
        tvEndView.setText(formatTime(duration));

        leftMargin = tvStartView.getWidth();
        rightMargin = tvEndView.getWidth();

        totalWidth = AndroidUtilities.getRealScreenSize().x - leftMargin - rightMargin;

        RelativeLayout.LayoutParams sliderLP = (LayoutParams) sliderLayout.getLayoutParams();

        //最大值
        maxX = totalWidth * 0.4;

        //最小值
        minX = totalWidth * 0.3;

        sliderLP.width = (int) (totalWidth * 0.3);

        sliderLayout.setLayoutParams(sliderLP);

        //计算初始长度

        double rPercent = div((totalWidth * 0.3), totalWidth, 2);

        int rTime = (int) ((rPercent) * 40);

        return rTime;
    }

    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            return 0.0;
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    private String formatTime(int second) {
        SimpleDateFormat formatter = new SimpleDateFormat("mm:ss");//初始化Formatter的转换格式。
        return formatter.format((long) second);
    }

    public MusicIntercept(Context context) {
        super(context);

        setBackgroundColor(0xFFFFFFF);

        tvStartView = new TextView(context);
        tvStartView.setId(R.id.music_intercept_start);
        tvStartView.setPadding(AndroidUtilities.dp(15), 0, AndroidUtilities.dp(12), 0);
        tvStartView.setTextColor(Theme.TEXT_COLOR_SUBTITLE);
        tvStartView.setTextSize(12);
        tvStartView.setTypeface(Theme.font);
        tvStartView.setText("00:00");
        RelativeLayout.LayoutParams startLP = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
        startLP.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        startLP.addRule(RelativeLayout.CENTER_VERTICAL);
        addView(tvStartView, startLP);

        tvEndView = new TextView(context);
        tvEndView.setTextColor(Theme.TEXT_COLOR_SUBTITLE);
        tvEndView.setTextSize(12);
        tvEndView.setTypeface(Theme.font);
        tvEndView.setId(R.id.music_intercept_end);
        tvEndView.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(15), 0);
        tvEndView.setText("00:00");
        RelativeLayout.LayoutParams endLP = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
        endLP.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        endLP.addRule(RelativeLayout.CENTER_VERTICAL);
        addView(tvEndView, endLP);

        RelativeLayout container = new RelativeLayout(context);
        RelativeLayout.LayoutParams containerLP = LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT);
        containerLP.addRule(RelativeLayout.LEFT_OF, tvEndView.getId());
        containerLP.addRule(RelativeLayout.RIGHT_OF, tvStartView.getId());
        addView(container, containerLP);

        LinearLayout bgView = new LinearLayout(context);
        bgView.setBackgroundColor(0xFFE5E5E5);
        container.addView(bgView, LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, 2, RelativeLayout.CENTER_VERTICAL));

        sliderLayout = new RelativeLayout(context);
        RelativeLayout.LayoutParams sliderLP = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT);
        sliderLP.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        container.addView(sliderLayout, sliderLP);

        leftView = new ImageView(context);
        leftView.setId(R.id.music_intercept_left);
        leftView.setScaleType(ImageView.ScaleType.CENTER);
        leftView.setImageResource(R.mipmap.ic_up_local_music_slider_left);
        leftView.setOnTouchListener(leftTouchListener);
        RelativeLayout.LayoutParams leftLP = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
        leftLP.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
        leftLP.addRule(RelativeLayout.CENTER_VERTICAL);
        sliderLayout.addView(leftView, leftLP);

        rightView = new ImageView(context);
        rightView.setId(R.id.music_intercepte_right);
        rightView.setOnTouchListener(rightTouchListener);
        rightView.setScaleType(ImageView.ScaleType.CENTER);
        rightView.setImageResource(R.mipmap.ic_up_local_music_slider_right);
        RelativeLayout.LayoutParams rightLP = LayoutHelper.createRelative(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
        rightLP.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
        rightLP.addRule(RelativeLayout.CENTER_VERTICAL);
        sliderLayout.addView(rightView, rightLP);

        lineLayout = new LinearLayout(context);
        lineLayout.setGravity(Gravity.CENTER_VERTICAL);
        lineLayout.setOnTouchListener(lineTouchListener);
        RelativeLayout.LayoutParams lineLP = LayoutHelper.createRelative(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT);
        lineLP.addRule(RelativeLayout.RIGHT_OF, leftView.getId());
        lineLP.addRule(RelativeLayout.LEFT_OF, rightView.getId());
        sliderLayout.addView(lineLayout, lineLP);

        view = new View(context);
        view.setBackgroundResource(R.mipmap.ic_up_local_music_slider_bg);
        lineLayout.addView(view, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 22));
    }

    private void silderMethod() {
        int emptyLeft = sliderLayout.getRight() - sliderLayout.getWidth();

        double r = (rightView.getRight() + emptyLeft);//当前控件在父容器所在的位置

        double l = (leftView.getLeft() + emptyLeft);//当前控件在父容器所在的位置

        double rPercent = div(r, totalWidth, 2);
        double lPercent = div(l, totalWidth, 2);


        int lTime = (int) (duration * lPercent);
        int rTime = (int) (lTime + (rPercent - lPercent) * 40);

        if (listener != null) {
            listener.onTimeChange(lTime, rTime);
        }

        tvStartView.setText(formatTime((lTime * 1000)));
    }

    private void changeStart() {

        int emptyLeft = sliderLayout.getRight() - sliderLayout.getWidth();

        double r = (rightView.getRight() + emptyLeft);//当前控件在父容器所在的位置

        double l = (leftView.getLeft() + emptyLeft);//当前控件在父容器所在的位置

        double rPercent = div(r, totalWidth, 2);
        double lPercent = div(l, totalWidth, 2);

        int lTime = (int) (duration * lPercent);
        int rTime = (int) (lTime + (rPercent - lPercent) * 40);

        if (listener != null) {
            listener.onStartChange(lTime, rTime);
        }
    }

    private int leftLeft;
    private int leftRight;

    private int rightLeft;
    private int rightRight;

    private int centerLeft;
    private int centerRight;

    private int viewLeft;
    private int viewRight;

    public void resetPosition() {
        leftLeft = 0;
        leftRight = 0;

        rightLeft = 0;
        rightRight = 0;

        centerLeft = 0;
        centerRight = 0;

        viewLeft = 0;
        viewRight = 0;
    }

    private OnTouchListener rightTouchListener = new OnTouchListener() {

        private int lastX;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastX = (int) event.getRawX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int dx = (int) event.getRawX() - lastX;

                    int right = sliderLayout.getRight() + dx;

                    if ((right + leftMargin) < (AndroidUtilities.getRealScreenSize().x - rightMargin) && (right - sliderLayout.getLeft()) <= maxX && (right - sliderLayout.getLeft()) >= minX) {
                        leftLeft = leftView.getLeft();
                        leftRight = leftView.getRight();

                        rightLeft = rightView.getLeft() + dx;
                        rightRight = rightView.getRight() + dx;

                        centerLeft = lineLayout.getLeft();
                        centerRight = lineLayout.getRight() + dx;

                        viewLeft = view.getLeft();
                        viewRight = view.getRight() + dx;

                        if (rightRight >= right) {
                            rightRight = right;
                        }

                        sliderLayout.layout(sliderLayout.getLeft(), sliderLayout.getTop(), right, sliderLayout.getBottom());
                        rightView.layout(rightLeft, rightView.getTop(), rightRight, rightView.getBottom());
                        lineLayout.layout(lineLayout.getLeft(), lineLayout.getTop(), centerRight, lineLayout.getBottom());

                        view.layout(view.getLeft(), view.getTop(), viewRight, view.getBottom());

                        silderMethod();
                    }

                    lastX = (int) event.getRawX();
                    break;
                case MotionEvent.ACTION_UP:
                    changeStart();
                    break;
            }
            return true;
        }
    };

    private OnTouchListener leftTouchListener = new OnTouchListener() {

        private int lastX;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastX = (int) event.getRawX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int dx = (int) event.getRawX() - lastX;

                    int left = sliderLayout.getLeft() + dx;

                    if (left >= 0 && (left + minX) <= sliderLayout.getRight() && (sliderLayout.getRight() - left) <= maxX) {
                        leftLeft = leftView.getLeft();
                        leftRight = leftView.getRight();

                        rightLeft = rightView.getLeft() + -dx;
                        rightRight = rightView.getRight() + -dx;

                        centerLeft = lineLayout.getLeft();
                        centerRight = lineLayout.getRight() + -dx;

                        viewLeft = view.getLeft();
                        viewRight = view.getRight() + -dx;

                        sliderLayout.layout(left, sliderLayout.getTop(), sliderLayout.getRight(), sliderLayout.getBottom());
                        rightView.layout(rightLeft, rightView.getTop(), rightRight, rightView.getBottom());
                        leftView.layout(leftLeft, leftView.getTop(), leftRight, leftView.getBottom());
                        lineLayout.layout(centerLeft, lineLayout.getTop(), centerRight, lineLayout.getBottom());
                        view.layout(viewLeft, view.getTop(), viewRight, view.getBottom());

                        silderMethod();
                    }

                    lastX = (int) event.getRawX();
                    break;
                case MotionEvent.ACTION_UP:
                    changeStart();
                    break;
            }
            return true;
        }
    };

    private OnTouchListener lineTouchListener = new OnTouchListener() {

        private int lastX;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    lastX = (int) event.getRawX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int dx = (int) event.getRawX() - lastX;

                    int left = sliderLayout.getLeft() + dx;
                    int right = sliderLayout.getRight() + dx;

                    if (left <= 0) {
                        left = 0;
                        right = sliderLayout.getWidth();
                    }

                    if ((right + leftMargin) >= (AndroidUtilities.getRealScreenSize().x - rightMargin)) {
                        right = (AndroidUtilities.getRealScreenSize().x - leftMargin - rightMargin);
                        left = (AndroidUtilities.getRealScreenSize().x - leftMargin - rightMargin - sliderLayout.getWidth());
                    }

                    sliderLayout.layout(left, sliderLayout.getTop(), right, sliderLayout.getBottom());

                    if (rightLeft != 0 || rightRight != 0) {
                        rightView.layout(rightLeft, rightView.getTop(), rightRight, rightView.getBottom());
                    }

                    if (centerLeft != 0 || centerRight != 0) {
                        lineLayout.layout(centerLeft, lineLayout.getTop(), centerRight, lineLayout.getBottom());
                    }

                    if (viewLeft != 0 || viewRight != 0) {
                        view.layout(viewLeft, view.getTop(), viewRight, view.getBottom());
                    }

                    silderMethod();

                    lastX = (int) event.getRawX();
                    break;
                case MotionEvent.ACTION_UP:
                    changeStart();
                    break;
            }
            return true;
        }
    };
}


用法很简单


musicIntercept = new MusicIntercept(context);
musicIntercept.setListener(new MusicIntercept.OnMusicInterceptListener() {
    @Override
    public void onTimeChange(int lTime, int rTime) {//移动的时候改变
        startTime = lTime;
        endTime = rTime;

        int second = rTime - lTime;

        mSubTitleView.setText(LocaleController.getString(R.string.music_intercept_tip, second));
    }

    @Override
    public void onStartChange(int lTime, int rTime) {//抬起
        startTime = lTime;
        endTime = rTime;

        if (mData != null) {
            mData.setStart((lTime * 1000));
            playMethod(mData);
        }

        startRunnable();
    }
});
mPlayerView.addView(musicIntercept, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 42, 0, 0, 0, 20));

有一点需要强调的是 因为在setDuration()方法时要计算宽高还有左右边距,这个时候我们最好是在post方法中执行


musicIntercept.post(new Runnable() {
    @Override
    public void run() {
        int min = musicIntercept.setDuration(data.duration);

        endTime = min;

        mSubTitleView.setText(LocaleController.getString(R.string.music_intercept_tip, min));

        startRunnable();

    }
});


//======End 代码


就简单的写了下,如果有问题,可以随时沟通


QQ179228838


上次写忘记了 有一些问题  还有音乐剪切的代码  现在附上Android 实现音乐剪切功能 可以选择起始点和结束点 也可以同时拖动块级元素


这是在网上看别人写的方法,不过这种方法只是对文件进行数据流的截取,会有稍许误差 所以我对起始时间和结束时间都做了0.5秒的调整,经测试发现一本一致