1. 程式人生 > >Android 實現音樂剪下功能 可以選擇起始點和結束點 也可以同時拖動塊級元素

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

上次寫忘記了 有一些問題  還有音樂剪下的程式碼  現在附上

這是在網上看別人寫的方法,不過這種方法只是對檔案進行資料流的擷取,會有稍許誤差 所以我對起始時間和結束時間都做了0.5秒的調整,經測試發現一本一致