Android使用MediaPlayer实现mp3音频剪辑和播放试听

810 阅读9分钟

需求分析:

1.读取本地里所有的音频文件

2.使用MediaPlayer进行音频播放

3.对音频文件进行剪辑,截取想要的音频片段,支持试听

做出来的效果图如下:

2.gif

一、先在AndroidManifest.xml清单文件里添加需要的权限

   <!-- 允许程序设置内置sd卡的写权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 这个权限用于读取音频 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />

 

首先提供一些重要xml布局文件的代码给大家:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainActivity_root"  
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="10dp"
            android:paddingBottom="10dp"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:textSize="16dp"
            android:text="本地音乐" />
    </RelativeLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:alpha="0.3"
        android:background="#666" />
    <ListView
        android:id="@+id/music_listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
         >
    </ListView>

</LinearLayout>

music_cut_dialog.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/shape_circle_dialog_bg"
    android:orientation="vertical"
    android:paddingTop="30dp"
    android:paddingBottom="10dp"
     >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/popupWindow_music_cut_tv_musicName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:text="歌手 - 歌名.mp3"
            android:textSize="20sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/popupWindow_music_cut_tv_musicName"
            android:layout_centerHorizontal="true"
            android:paddingTop="15dp"
            android:text="拖动滑块来剪辑音乐"
            android:textColor="#999"
            android:textSize="12sp" />
    </RelativeLayout>
 	<TextView
            android:id="@+id/popupWindow_music_cut_tv_delta_rule"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_horizontal"
            android:text="已截取0秒"
            android:visibility="gone"
            android:textSize="12sp"
            android:textColor="#999" />
    <com.t20.audiodemo.view.DoubleSlideSeekBar
        android:id="@+id/popupWindow_music_cut_doubleSlideSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        custom:equal="1"
        custom:hasRule="false"
        custom:imageBig="@drawable/green_ball"
        custom:imageLow="@drawable/grey_ball"
        custom:imageheight="20dp"
        custom:imagewidth="20dp"
        custom:inColor="#B7D54E"
        custom:lineHeight="3dp"
        custom:outColor="#C3CBC9"
        custom:ruleColor="#0e0e0e"
        custom:ruleLineHeight="10dp"
        custom:ruleTextColor="#f74104"
        custom:ruleTextSize="6sp"
        custom:textColor="#DE5B78"
        custom:textSize="12sp" />
	<RelativeLayout 
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    >
	    
        <TextView
            android:id="@+id/popupWindow_music_cut_tv_musicTest"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_centerHorizontal="true"
            android:paddingBottom="15dp"
            android:textSize="10sp"
            android:textColor="#3D91FE"
            android:drawableLeft="@drawable/music_audio_test"
            android:drawablePadding="2dp"
            android:text="点击试听一下" />
	</RelativeLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/popupWindow_music_cut_tv_line"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:alpha="0.7"
            android:text="|"
            android:textColor="#C3CBC9"
            android:textSize="18sp"
            android:typeface="serif" />

        <Button
            android:id="@+id/popupWindow_music_cut_btn_cancel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginRight="20dp"
            android:layout_toLeftOf="@id/popupWindow_music_cut_tv_line"
            android:background="@null"
            android:text="取消"
            android:textColor="#666"
            android:textSize="16sp" />

        <Button
            android:id="@+id/popupWindow_music_cut_btn_sure"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_marginLeft="20dp"
            android:layout_toRightOf="@id/popupWindow_music_cut_tv_line"
            android:background="@null"
            android:text="确定"
            android:textColor="#DE5B78"
            android:textSize="16sp" />

    </RelativeLayout>

</LinearLayout>

music_listview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp" >

    <FrameLayout
        android:layout_width="60dp"
        android:layout_height="60dp" >

        <ImageView
            android:id="@+id/music_iv_pic"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/selector_music_play_pic" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <ImageView
                android:id="@+id/music_iv_play"
                android:layout_width="25dp"
                android:layout_height="25dp"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:alpha="0.7"
                android:background="@drawable/shape_play_button_background"
                android:src="@drawable/music_play" />
        </RelativeLayout>
    </FrameLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical"
        android:paddingLeft="5dp" >

        <TextView
            android:id="@+id/music_tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="歌曲"
            android:textColor="#666"
            android:textSize="13sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/music_tv_singer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="3dp"
            android:text="歌手"
            android:textColor="#999"
            android:textSize="12sp" />

        <TextView
            android:id="@+id/music_tv_duration"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingTop="3dp"
            android:text="00:00"
            android:textColor="#999"
            android:textSize="12sp" />
    </LinearLayout>

    <ImageView
        android:id="@+id/music_iv_cut"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_gravity="center"
        android:src="@drawable/music_cut" />

</LinearLayout>

二、重写View ,实现一个可以双向滑动的SeekBar控件

DoubleSlideSeekBar.java

package com.t20.audiodemo.view;

import com.t20.audiodemo.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
/**
 * 双向滑动SeekBar
 * @author admin
 *
 */
/**
 * @author admin
 *
 */
public class DoubleSlideSeekBar extends View {
    /**
     * 线条(进度条)的宽度
     */
    private int lineWidth;
    /**
     * 线条(进度条)的长度
     */
    private int lineLength=getWidth();
    /**
     * 字所在的高度 
     */
    private int textHeight;
    /**
     * 游标 图片宽度
     */
    private int imageWidth;
    /**
     * 游标 图片高度
     */
    private int imageHeight;
    /**
     * 是否有刻度线
     */
    private boolean hasRule;
    /**
     * 左边的游标是否在动
     */
    private boolean isLowerMoving;
    /**
     * 右边的游标是否在动
     */
    private boolean isUpperMoving;
    /**
     * 字的大小
     */
    private int textSize;
    /**
     * 字的颜色 
     */
    private int textColor;
    /**
     * 两个游标内部 线(进度条)的颜色
     */
    private int inColor = Color.BLUE;
    /**
     * 两个游标外部 线(进度条)的颜色
     */
    private int outColor = Color.BLUE;
    /**
     * 刻度的颜色
     */
    private int ruleColor = Color.BLUE;
    /**
     * 刻度上边的字 的颜色
     */
    private int ruleTextColor = Color.BLUE;
    /**
     * 左边图标的图片
     */
    private Bitmap bitmapLow;
    /**
     * 右边图标 的图片
     */
    private Bitmap bitmapBig;
    /**
     * 左边图标所在X轴的位置
     */
    private int slideLowX;
    /**
     * 右边图标所在X轴的位置
     */
    private int slideBigX;
    /**
     * 图标(游标) 高度
     */
    private int bitmapHeight;
    /**
     * 图标(游标) 宽度
     */
    private int bitmapWidth;
    /**
     * 加一些padding 大小酌情考虑 为了我们的自定义view可以显示完整
     */
    private int paddingLeft = 30;
    private int paddingRight = 30;
    private int paddingTop = 10;
    private int paddingBottom = 10;
    /**
     * 线(进度条) 开始的位置
     */
    private int lineStart = paddingLeft;
    /**
     * 线的Y轴位置
     */
    private int lineY;
    /**
     * 线(进度条)的结束位置
     */
    private int lineEnd = lineLength + paddingLeft;
    /**
     * 选择器的最大值
     */
    private int bigValue = 100;
    /**
     * 选择器的最小值
     */
    private int smallValue = 0;
    /**
     * 选择器的当前最小值
     */
    private float smallRange;
    /**
     * 选择器的当前最大值
     */
    private float bigRange;
    /**
     * 单位 元
     */
    private String unit = " ";
    /**
     * 单位份数
     */
    private int equal = 20;
    /**
     * 刻度单位 $
     */
    private String ruleUnit = " ";
    /**
     * 刻度上边文字的size
     */
    private int ruleTextSize = 20;
    /**
     * 刻度线的高度
     */
    private int ruleLineHeight = 20;
    private Paint linePaint;
    private Paint bitmapPaint;
    private Paint textPaint;
    private Paint paintRule;

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

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

    public DoubleSlideSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DoubleSlideSeekBar, defStyleAttr, 0);
        int size = typedArray.getIndexCount();
        for (int i = 0; i < size; i++) {
            int type = typedArray.getIndex(i);
            switch (type) {
                case R.styleable.DoubleSlideSeekBar_inColor:
                    inColor = typedArray.getColor(type, Color.BLACK);
                    break;
                case R.styleable.DoubleSlideSeekBar_lineHeight:
                    lineWidth = (int) typedArray.getDimension(type, dip2px(getContext(), 10));
                    break;
                case R.styleable.DoubleSlideSeekBar_outColor:
                    outColor = typedArray.getColor(type, Color.YELLOW);
                    break;
                case R.styleable.DoubleSlideSeekBar_textColor:
                    textColor = typedArray.getColor(type, Color.BLUE);
                    break;
                case R.styleable.DoubleSlideSeekBar_textSize:
                    textSize = typedArray.getDimensionPixelSize(type, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.DoubleSlideSeekBar_imageLow:
                    bitmapLow = BitmapFactory.decodeResource(getResources(), typedArray.getResourceId(type, 0));
                    break;
                case R.styleable.DoubleSlideSeekBar_imageBig:
                    bitmapBig = BitmapFactory.decodeResource(getResources(), typedArray.getResourceId(type, 0));
                    break;
                case R.styleable.DoubleSlideSeekBar_imageheight:
                    imageHeight = (int) typedArray.getDimension(type, dip2px(getContext(), 20));
                    break;
                case R.styleable.DoubleSlideSeekBar_imagewidth:
                    imageWidth = (int) typedArray.getDimension(type, dip2px(getContext(), 20));
                    break;
                case R.styleable.DoubleSlideSeekBar_hasRule:
                    hasRule = typedArray.getBoolean(type, false);
                    break;
                case R.styleable.DoubleSlideSeekBar_ruleColor:
                    ruleColor = typedArray.getColor(type, Color.BLUE);
                    break;
                case R.styleable.DoubleSlideSeekBar_ruleTextColor:
                    ruleTextColor = typedArray.getColor(type, Color.BLUE);
                    break;
                case R.styleable.DoubleSlideSeekBar_unit:
                    unit = typedArray.getString(type);
                    break;
                case R.styleable.DoubleSlideSeekBar_equal:
                    equal = typedArray.getInt(type, 10);
                    break;
                case R.styleable.DoubleSlideSeekBar_ruleUnit:
                    ruleUnit = typedArray.getString(type);
                    break;
                case R.styleable.DoubleSlideSeekBar_ruleTextSize:
                    ruleTextSize = typedArray.getDimensionPixelSize(type, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.DoubleSlideSeekBar_ruleLineHeight:
                    ruleLineHeight = (int) typedArray.getDimension(type, dip2px(getContext(), 10));
                    break;
                case R.styleable.DoubleSlideSeekBar_bigValue:
                    bigValue = typedArray.getInteger(type, 100);
                    break;
                case R.styleable.DoubleSlideSeekBar_smallValue:
                    smallValue = typedArray.getInteger(type, 100);
                    break;


                default:
                    break;
            }
        }
        typedArray.recycle();
        init();
    }

    private void init() {
        /**游标的默认图*/
        if (bitmapLow == null) {
            bitmapLow = BitmapFactory.decodeResource(getResources(), R.drawable.grey_ball);
        }
        if (bitmapBig == null) {
            bitmapBig = BitmapFactory.decodeResource(getResources(), R.drawable.green_ball);
        }
        /**游标图片的真实高度 之后通过缩放比例可以把图片设置成想要的大小*/
        bitmapHeight = bitmapLow.getHeight();
        bitmapWidth = bitmapLow.getWidth();
        // 设置想要的大小
        int newWidth = imageWidth;
        int newHeight = imageHeight;
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / bitmapWidth;
        float scaleHeight = ((float) newHeight) / bitmapHeight;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        /**缩放图片*/
        bitmapLow = Bitmap.createBitmap(bitmapLow, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
        bitmapBig = Bitmap.createBitmap(bitmapBig, 0, 0, bitmapWidth, bitmapHeight, matrix, true);
        /**重新获取游标图片的宽高*/
        bitmapHeight = bitmapLow.getHeight();
        bitmapWidth = bitmapLow.getWidth();
        /**初始化两个游标的位置*/
        slideLowX = lineStart;
        slideBigX = lineEnd;
        smallRange = smallValue;
        bigRange = bigValue;
        if (hasRule) {
            //有刻度时 paddingTop 要加上(text高度)和(刻度线高度加刻度线上边文字的高度和) 之间的最大值
            paddingTop = paddingTop + Math.max(textSize, ruleLineHeight + ruleTextSize);
        } else {
            //没有刻度时 paddingTop 加上 text的高度
            paddingTop = paddingTop + textSize;
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = getMyMeasureWidth(widthMeasureSpec);
        int height = getMyMeasureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int getMyMeasureHeight(int heightMeasureSpec) {
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        int size = MeasureSpec.getSize(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            // matchparent 或者 固定大小 view最小应为 paddingBottom + paddingTop + bitmapHeight + 10 否则显示不全
            size = Math.max(size, paddingBottom + paddingTop + bitmapHeight + 10);
        } else {
            //wrap content
            int height = paddingBottom + paddingTop + bitmapHeight + 10;
            size = Math.min(size, height);
        }
        return size;
    }

    private int getMyMeasureWidth(int widthMeasureSpec) {
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        int size = MeasureSpec.getSize(widthMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {

            size = Math.max(size, paddingLeft + paddingRight + bitmapWidth * 2);

        } else {
            //wrap content
            int width = paddingLeft + paddingRight + bitmapWidth * 2;
            size = Math.min(size, width);
        }
        // match parent 或者 固定大小 此时可以获取线(进度条)的长度
        lineLength = size - paddingLeft - paddingRight - bitmapWidth;
        //线(进度条)的结束位置
        lineEnd = lineLength + paddingLeft + bitmapWidth / 2;
        //线(进度条)的开始位置
        lineStart = paddingLeft + bitmapWidth / 2;
        //初始化 游标位置
        slideBigX = lineEnd;
        slideLowX = lineStart;
        return size;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // Y轴 坐标
        lineY = getHeight() - paddingBottom - bitmapHeight / 2;
        // 字所在高度 100$
        textHeight = lineY - bitmapHeight / 2 - 10;
        //是否画刻度
        if (hasRule) {
            drawRule(canvas);
        }
        if (linePaint == null) {
            linePaint = new Paint();
        }
        //画内部线
        linePaint.setAntiAlias(true);
        linePaint.setStrokeWidth(lineWidth);
        linePaint.setColor(inColor);
        linePaint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawLine(slideLowX, lineY, slideBigX, lineY, linePaint);
        linePaint.setColor(outColor);
        linePaint.setStrokeCap(Paint.Cap.ROUND);
        //画 外部线
        canvas.drawLine(lineStart, lineY, slideLowX, lineY, linePaint);
        canvas.drawLine(slideBigX, lineY, lineEnd, lineY, linePaint);
        //画游标
        if (bitmapPaint == null) {
            bitmapPaint = new Paint();
        }
        canvas.drawBitmap(bitmapLow, slideLowX - bitmapWidth / 2, lineY - bitmapHeight / 2, bitmapPaint);
        canvas.drawBitmap(bitmapBig, slideBigX - bitmapWidth / 2, lineY - bitmapHeight / 2, bitmapPaint);
        //画 游标上边的字
        if (textPaint == null) {
            textPaint = new Paint();
        }
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
        textPaint.setAntiAlias(true);
        canvas.drawText(String.format("%.0f" + unit, smallRange), slideLowX - bitmapWidth / 2, textHeight, textPaint);
        canvas.drawText(String.format("%.0f" + unit, bigRange), slideBigX - bitmapWidth / 2, textHeight, textPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //事件机制
        super.onTouchEvent(event);
        float nowX = event.getX();
        float nowY = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //按下 在游标范围上
                boolean rightY = Math.abs(nowY - lineY) < bitmapHeight / 2;
                //按下 在左边游标上
                boolean lowSlide = Math.abs(nowX - slideLowX) < bitmapWidth / 2;
                //按下 在右边游标上
                boolean bigSlide = Math.abs(nowX - slideBigX) < bitmapWidth / 2;
                if (rightY && lowSlide) {
                    isLowerMoving = true;
                } else if (rightY && bigSlide) {
                    isUpperMoving = true;
                    //点击了游标外部 的线上
                } else if (nowX >= lineStart && nowX <= slideLowX - bitmapWidth / 2 && rightY) {
                    slideLowX = (int) nowX;
                    updateRange();
                    postInvalidate();
                } else if (nowX <= lineEnd && nowX >= slideBigX + bitmapWidth / 2 && rightY) {
                    slideBigX = (int) nowX;
                    updateRange();
                    postInvalidate();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                //左边游标是运动状态
                if (isLowerMoving) {
                    //当前 X坐标在线上 且在右边游标的左边
                    if (nowX <= slideBigX - bitmapWidth && nowX >= lineStart - bitmapWidth / 2) {
                        slideLowX = (int) nowX;
                        if (slideLowX < lineStart) {
                            slideLowX = lineStart;
                        }
                        //更新进度
                        updateRange();
                        postInvalidate();
                    }

                } else if (isUpperMoving) {
                    //当前 X坐标在线上 且在左边游标的右边
                    if (nowX >= slideLowX + bitmapWidth && nowX <= lineEnd + bitmapWidth / 2) {
                        slideBigX = (int) nowX;
                        if (slideBigX > lineEnd) {
                            slideBigX = lineEnd;
                        }
                        //更新进度
                        updateRange();
                        postInvalidate();

                    }
                }
                break;
            //手指抬起
            case MotionEvent.ACTION_UP:
                isUpperMoving = false;
                isLowerMoving = false;
                break;
            default:
                break;
        }

        return true;
    }

    private void updateRange() {
        //当前 左边游标数值
        smallRange = computRange(slideLowX);
        //当前 右边游标数值
        bigRange = computRange(slideBigX);
        //接口 实现值的传递
        if (onRangeListener != null) {
            onRangeListener.onRange(smallRange, bigRange);
        }
    }

    /**
     * 获取当前值
     */
    private float computRange(float range) {
        return (range - lineStart) * (bigValue - smallValue) / lineLength + smallValue;
    }

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

    /**
     * 画刻度
     */
    protected void drawRule(Canvas canvas) {
        if (paintRule == null) {
            paintRule = new Paint();
        }
        paintRule.setStrokeWidth(1);
        paintRule.setTextSize(ruleTextSize);
        paintRule.setTextAlign(Paint.Align.CENTER);
        paintRule.setAntiAlias(true);
        //遍历 equal份,画刻度
        for (int i = smallValue; i <= bigValue; i += (bigValue - smallValue) / equal) {
            float degX = lineStart + i * lineLength / (bigValue - smallValue);
            int degY = lineY - ruleLineHeight;
            paintRule.setColor(ruleColor);
            canvas.drawLine(degX, lineY, degX, degY, paintRule);
            paintRule.setColor(ruleTextColor);
            canvas.drawText(String.valueOf(i) + ruleUnit, degX, degY, paintRule);
        }
    }

    /**
     * 写个接口 用来传递最大最小值
     */
    public interface onRangeListener {
        void onRange(float low, float big);
    }

    private onRangeListener onRangeListener;

    public void setOnRangeListener(DoubleSlideSeekBar.onRangeListener onRangeListener) {
        this.onRangeListener = onRangeListener;
    }
    //设置选择器的最大值 

	public void setBigValue(int bigValue) {
		this.bigValue = bigValue;
	}
	//设置选择器的最当最大值

	public void setBigRange(float bigRange) {
		this.bigRange = bigRange;
	}
    
}

上面的DoubleSlideSeekBar需要在res/values/下新建一个attrs.xml ,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <!--线(进度条)宽度-->
    <attr name="lineHeight" format="dimension" />
    <!--字的大小-->
    <attr name="textSize" format="dimension" />
    <!--字的颜色-->
    <attr name="textColor" format="color" />
    <!--两个游标内部 线(进度条)的颜色-->
    <attr name="inColor" format="color" />
    <!--两个游标外部 线(进度条)的颜色-->
    <attr name="outColor" format="color" />
    <!--左边图标的图片-->
    <attr name="imageLow" format="reference"/>
    <!--右边图标 的图片-->
    <attr name="imageBig" format="reference"/>
    <!--游标 图片宽度-->
    <attr name="imagewidth" format="dimension" />
    <!--游标 图片高度-->
    <attr name="imageheight" format="dimension" />
    <!--是否有刻度线-->
    <attr name="hasRule" format="boolean" />
    <!--刻度的颜色-->
    <attr name="ruleColor" format="color" />
    <!--刻度上边的字 的颜色-->
    <attr name="ruleTextColor" format="color" />
    <!--单位 元-->
    <attr name="unit" format="string"/>
    <!--单位份数-->
    <attr name="equal" format="integer"/>
    <!--刻度单位 $-->
    <attr name="ruleUnit" format="string"/>
    <!--刻度上边文字的size-->
    <attr name="ruleTextSize" format="dimension" />
    <!--刻度线的高度-->
    <attr name="ruleLineHeight" format="dimension" />
    <!--选择器的最大值-->
    <attr name="bigValue" format="integer"/>
    <!--选择器的最小值-->
    <attr name="smallValue" format="integer"/>

    <declare-styleable name="DoubleSlideSeekBar">
        <attr name="lineHeight" />
        <attr name="textSize" />
        <attr name="textColor" />
        <attr name="inColor" />
        <attr name="outColor" />
        <attr name="imageLow"/>
        <attr name="imageBig"/>
        <attr name="imagewidth" />
        <attr name="imageheight" />
        <attr name="hasRule" />
        <attr name="ruleColor" />
        <attr name="ruleTextColor" />
        <attr name="unit" />
        <attr name="equal" />
        <attr name="ruleUnit" />
        <attr name="ruleTextSize" />
        <attr name="ruleLineHeight" />
        <attr name="bigValue" />
        <attr name="smallValue" />
    </declare-styleable>
    <!-- 
	xml属性			值			解释
	lineHeight		dimension	控制我们线(进度条)的宽(高)度(例20dp)
	textSize		dimension	游标上边字的大小(例16sp)
	textColor		color		游标上边字的颜色 (例#e40627)
	inColor			color		两个游标之间进度条的颜色 (例#e40627)
	outColor		color		两个游标外部(游标到进度条两端)进度条的颜色 (例#e40627)
	imageLow		reference	左边游标的图片 (例@mipmap/imgv_slide)
	imageBig		reference	右边游标的图片 (例@mipmap/imgv_slide)
	imagewidth		dimension	游标图片的宽度 (例20dp)
	imagewidth		dimension	游标图片的高度 (例20dp)
	hasRule			boolean		是否有刻度线(例 true or false)
	ruleColor		color		刻度线的颜色 (例#e40627)
	ruleTextColor	color		刻度线上边的字的颜色 (例#e40627)
	unit			string		单位 (例 元)
	equal			integer		单位份数,把全部数据分成equal份(例smallValue是0,bigValue是100,equal是10,则每个刻度大小为(100-0)/10 =10)
	ruleUnit		string		刻度上边文字的单位 (例 $)
	ruleTextSize	dimension	刻度上边文字的大小 (例20sp)
	ruleLineHeight	dimension	刻度线高度(例16dp)
	bigValue		integer		选择器的最大值 (例 100)
	smallValue		integer		选择器的最小值 (例 0)
	 -->
</resources>

三、剪辑窗口使用的是PopupWindow弹出窗,因此需要自定义一个MusicCutPopupWindow.java

package com.t20.audiodemo.view;

import com.t20.audiodemo.R;

import android.app.ActionBar.LayoutParams;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.PopupWindow;
import android.widget.TextView;

public class MusicCutPopupWindow extends PopupWindow {
	private Button mButtonCancel; //取消按钮 
	private Button mButtonSure;   //确定按钮
	private DoubleSlideSeekBar mDoubleSlideSeekBar; //自定义的双向滑杆进度条
	private TextView mTextViewName;    //音乐名称
	private TextView mTextViewDeltaRule;//差值
	private TextView mTextViewMusicTest;//试听按钮
	private View mMenuView; 

	private float minRule=0;
	private float maxRule=0;
	
	public float getMinRule() {
		return minRule;
	}
	public void setMinRule(float minRule) {
		this.minRule = minRule;
	}
	public float getMaxRule() {
		return maxRule;
	}
	public void setMaxRule(float maxRule) {
		this.maxRule = maxRule;
	}
	
	public MusicCutPopupWindow(Context context,OnClickListener itemsOnClick) {  
        super(context);  
        LayoutInflater inflater = (LayoutInflater) context  
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
        mMenuView = inflater.inflate(R.layout.music_cut_dialog, null);  
        mButtonCancel = (Button) mMenuView.findViewById(R.id.popupWindow_music_cut_btn_cancel);  
        mButtonSure = (Button) mMenuView.findViewById(R.id.popupWindow_music_cut_btn_sure);  
        mDoubleSlideSeekBar=(DoubleSlideSeekBar) mMenuView.findViewById(R.id.popupWindow_music_cut_doubleSlideSeekBar);
        mTextViewDeltaRule= (TextView) mMenuView.findViewById(R.id.popupWindow_music_cut_tv_delta_rule);
        mTextViewName=(TextView) mMenuView.findViewById(R.id.popupWindow_music_cut_tv_musicName);
        mTextViewMusicTest=(TextView) mMenuView.findViewById(R.id.popupWindow_music_cut_tv_musicTest);
/*        //取消按钮  
        mButtonCancel.setOnClickListener(new OnClickListener() {  
  
            public void onClick(View v) {  
                //销毁弹出框  
                dismiss();  
            }  
        });*/
        //滑动控件
        mDoubleSlideSeekBar.setOnRangeListener(new DoubleSlideSeekBar.onRangeListener() {
            @Override
            public void onRange(float low, float big) {
            	minRule=low;
            	maxRule=big;
            	float delta=big-low;
            	mTextViewDeltaRule.setVisibility(View.VISIBLE);
            	mTextViewDeltaRule.setText("已截取" + String.format("%.0f" , delta)+"秒");
            }
        });
        //设置按钮监听  
        mButtonCancel.setOnClickListener(itemsOnClick);
        mButtonSure.setOnClickListener(itemsOnClick);
        mTextViewMusicTest.setOnClickListener(itemsOnClick);
        //设置SelectPicPopupWindow的View  
        this.setContentView(mMenuView);  
        //设置SelectPicPopupWindow弹出窗体的宽  
        this.setWidth(LayoutParams.FILL_PARENT);  
        //设置SelectPicPopupWindow弹出窗体的高  
        this.setHeight(LayoutParams.WRAP_CONTENT);  
        //设置SelectPicPopupWindow弹出窗体可点击  
        this.setFocusable(true); 
		//设置窗口外也能点击(点击外面时,窗口可以关闭)
        this.setOutsideTouchable(true);
        //设置SelectPicPopupWindow弹出窗体动画效果  
        this.setAnimationStyle(R.style.circleDialog);  
        //实例化一个ColorDrawable颜色为半透明  
        ColorDrawable dw = new ColorDrawable(0x00000000);  
        //设置SelectPicPopupWindow弹出窗体的背景  
        this.setBackgroundDrawable(dw);  
    }  
	/**
	 * 设置音乐信息
	 * @param name
	 * @param duration
	 */
	public void setMusicInfo(String name,long duration){
		mTextViewName.setText(name);
		int big=Integer.parseInt(String.valueOf(duration/1000));
		mDoubleSlideSeekBar.setBigValue(big);
		mDoubleSlideSeekBar.setBigRange(big);
		maxRule=big;
	}
}

四、另外要写2个工具类:MusicPlayer用来播放音乐,MusicUtil用来剪辑音乐

MusicPlayer.java

package com.t20.audiodemo.util;

import android.content.Context;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Handler;

/**
 * 音乐播放器
 * @author admin
 *
 */
public class MusicPlayer {
	//多媒体播放器
	private static MediaPlayer mediaPlayer;
	
	public static MediaPlayer getMediaPlayer() {
		return mediaPlayer;
	}
	public static void setMediaPlayer(MediaPlayer mediaPlayer) {
		MusicPlayer.mediaPlayer = mediaPlayer;
	}
	
	
	//当歌曲播放到结束位置时,使用Handler来停止播放
	public static long endProgress=0;//结束进度
	public static Handler handler = new Handler();
	public static Runnable run = new Runnable() {

			public void run() {
				if(endProgress!=0){
					if(MusicPlayer.getMediaPlayer().isPlaying()&&MusicPlayer.getMediaPlayer().getCurrentPosition()>=endProgress){
						MusicPlayer.reset();
						handler.removeCallbacks(run);
					}
					handler.postDelayed(run, 1000);
				}

			}
	};
	/**
	 * 播放
	 */
	public static void play(Context context,String path,final int progress){	
		if(mediaPlayer==null){
			//初始化
			mediaPlayer=new MediaPlayer();
		}
		//重置音乐
		if(mediaPlayer.isPlaying()){
			mediaPlayer.reset();
		}
		try {
			mediaPlayer.setDataSource(path);
			//让MediaPlayer进入到准备状态
			mediaPlayer.prepareAsync();
			//播放音乐
			mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
				
				@Override
				public void onPrepared(MediaPlayer mp) {
					// TODO Auto-generated method stub
					if(progress!=0){
						mediaPlayer.seekTo(progress);
					}
					mediaPlayer.start();
					//循环播放
					mediaPlayer.setLooping(true);
				}
			});
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
	/**
	 * 播放(一般用于暂停后重新播放)
	 */
	public static void reStart(){
		if(mediaPlayer!=null){
			mediaPlayer.start();
		}
	}
	/**
	 * 暂停
	 */
	public static void pause(){
		if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
			mediaPlayer.pause();
		}
	}
	/**
	 * 停止
	 */
	public static void stop(){
		if(handler!=null){
			handler.removeCallbacks(run);
		}
		if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
			mediaPlayer.stop();
			mediaPlayer.release();
			mediaPlayer=null;
		}
	}
	/**
	 * 重置
	 */
	public static void reset(){
		if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
			mediaPlayer.reset();
		}
	}
}

MusicUtil.java

package com.t20.audiodemo.util;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import android.annotation.SuppressLint;
import android.media.MediaExtractor;
import android.media.MediaFormat;

/**
 * 剪切mp3音乐的工具类
 * @author admin
 *
 */
public class MusicUtil {
	//适当的调整SAMPLE_SIZE可以更加精确的裁剪音乐
	private static final int SAMPLE_SIZE = 1024*200;
	
	  @SuppressLint("InlinedApi")
	public static boolean clipMp3(String inputPath, String outputPath, int start, int end){
	      MediaExtractor extractor = null;
	      BufferedOutputStream outputStream = null;
	      try {
	          extractor = new MediaExtractor();
	          extractor.setDataSource(inputPath);
	          int track = getAudioTrack(extractor);
	          if(track < 0){
	              return false;
	          }
	          //选择音频轨道
	          extractor.selectTrack(track);
	          outputStream = new BufferedOutputStream(
	          new FileOutputStream(outputPath), SAMPLE_SIZE);
	          start = start * 1000;
	          end = end * 1000;
	          //跳至开始裁剪位置
	          extractor.seekTo(start, MediaExtractor.SEEK_TO_PREVIOUS_SYNC);
	          while (true){
	              ByteBuffer buffer = ByteBuffer.allocate(SAMPLE_SIZE);
	              int sampleSize = extractor.readSampleData(buffer, 0);
	              long timeStamp = extractor.getSampleTime();
	              // >= 1000000是要裁剪停止和指定的裁剪结尾不小于1秒,否则可能产生需要9秒音频
	              //裁剪到只有8.6秒,大多数音乐播放器是向下取整,这样对于播放器变成了8秒,
	              // 所以要裁剪比9秒多一秒的边界
	              if(timeStamp > end && timeStamp - end >= 1000000){
	                  break;
	              }
	              if(sampleSize <= 0){
	                  break;
	              }
	              byte[] buf = new byte[sampleSize];
	              buffer.get(buf, 0, sampleSize);
	              //写入文件
	              outputStream.write(buf);
	              //音轨数据往前读
	              extractor.advance();
	          }

	      } catch (IOException e) {
	          e.printStackTrace();
	      }finally {
	          if(extractor != null){
	              extractor.release();
	          }
	          if(outputStream != null){
	              try {
	                  outputStream.close();
	              } catch (IOException e) {
	                  e.printStackTrace();
	              }
	          }
	      }
	      return true;
	  }

	  /**
	   * 获取音频数据轨道
	   * @param extractor
	   * @return
	   */
	  @SuppressLint("InlinedApi")
	private static int getAudioTrack(MediaExtractor extractor) {
	      for(int i = 0; i < extractor.getTrackCount(); i++){
	          MediaFormat format = extractor.getTrackFormat(i);
	          String mime = format.getString(MediaFormat.KEY_MIME);
	          if(mime.startsWith("audio")){
	              return i;
	          }
	      }
	      return -1;
	  }
}

 五、定义一个实体类Music.java

package com.t20.audiodemo.entity;

import java.io.Serializable;

public class Music implements Serializable {
	private String name;   //歌曲名称
	private String singer; //歌手
	private long duration; //歌曲时长
	private String path;   //歌曲路径
	
	public Music() {
		super();
	}
	public Music(String name, String singer, long duration, String path) {
		super();
		this.name = name;
		this.singer = singer;
		this.duration = duration;
		this.path = path;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSinger() {
		return singer;
	}
	public void setSinger(String singer) {
		this.singer = singer;
	}
	public long getDuration() {
		return duration;
	}
	public void setDuration(long duration) {
		this.duration = duration;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
}

六、下面开始去活动MainActivity.java实现方法

package com.t20.audiodemo;

import java.util.ArrayList;
import java.util.List;

import com.t20.audiodemo.adapter.MusicListViewAdapter;
import com.t20.audiodemo.adapter.MusicListViewAdapter.OnplayMusicListener;
import com.t20.audiodemo.entity.Music;
import com.t20.audiodemo.util.MusicPlayer;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Toast;

public class MainActivity extends Activity {

	private static final String TAG = "MainActivity";
	//音乐ListView视图
	private ListView mListViewMusic;
	//音乐集合
	private List<Music> mMusicList;
	//ListView的适配器
	private MusicListViewAdapter musicListViewAdapter;
	//开始播放的进度
	private long startProgress=0;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// 1、隐藏标题栏,在加载布局之前设置(兼容Android2.3.3版本)
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		// 2、隐藏状态栏
		// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
		setContentView(R.layout.activity_main);
		//获取控件
		mListViewMusic=(ListView) findViewById(R.id.music_listView);
		initData();
		//设置适配器
		musicListViewAdapter=new MusicListViewAdapter(this, mMusicList);
		mListViewMusic.setAdapter(musicListViewAdapter);
		//监听事件
		initEvent();
	}

	private void initData() {
		// TODO Auto-generated method stub
		// 读取手机中的音乐文件
		mMusicList = new ArrayList<Music>();
		/*
		 * Uri:指明要查询的数据库名称加上表的名称,从MediaStore中我们可以找到相应信息的参数。 Projection:
		 * 指定查询数据库表中的哪几列,返回的游标中将包括相应的信息。Null则返回所有信息。 selection: 指定查询条件
		 * selectionArgs:参数selection里有
		 * ?这个符号是,这里可以以实际值代替这个问号。如果selection这个没有?的话,那么这个String数组可以为null。
		 * SortOrder:指定查询结果的排列顺序
		 */
		Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
		ContentResolver contentResolver = getContentResolver();
		String selection = MediaStore.Audio.Media.MIME_TYPE + "=? ";
		String[] selectionArgs = new String[] { "audio/mpeg" };
		// 游标
		Cursor cursor = contentResolver.query(uri, null, null, null,
				MediaStore.Audio.AudioColumns.IS_MUSIC);
		if (cursor != null) {
			while (cursor.moveToNext()) {
				String name = cursor
						.getString(cursor
								.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME));
				String singer = cursor.getString(cursor
						.getColumnIndexOrThrow(MediaStore.Audio.Media.ARTIST));
				String path = cursor.getString(cursor
						.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
				long duration = cursor
						.getLong(cursor
								.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
				long size = cursor.getLong(cursor
						.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));

				// 把歌曲名字和歌手切割开
				// if (size > 1000 * 800) {
				if (name.contains("-")) {
					String[] str = name.split("-");
					singer = str[0];
					if (str[1].contains(".")) {
						name = str[1].substring(0, str[1].indexOf('.'));
					} else {
						name = str[1];
					}
				} else if (name.contains(".")) {
					name = name.substring(0, name.indexOf('.'));
				}
				Music music = new Music(name, singer, duration, path);
				mMusicList.add(music);
				// }
			}
		}
		cursor.close();
	}

	private void initEvent() {
		// TODO Auto-generated method stub
		/**
		 * 监听ListView中音乐的播放事件
		 */
		musicListViewAdapter.setOnplayMusicListener(new OnplayMusicListener() {
			//播放完整歌曲
			@Override
			public void playForFull() {
				// TODO Auto-generated method stub
				if(musicListViewAdapter!=null){
					musicListViewAdapter.setSelectItem(musicListViewAdapter.getSelectItem());
					musicListViewAdapter.setHidePlayBtn(true);
					musicListViewAdapter.notifyDataSetChanged();
				}
				Music music=musicListViewAdapter.getCurrentMusic();
				MusicPlayer.play(MainActivity.this,music.getPath(), 0);			
			}
			//播放片段歌曲
			@Override
			public void playforPart() {
				// TODO Auto-generated method stub
				startProgress=musicListViewAdapter.getCutMusicStartProgress();
				MusicPlayer.endProgress=musicListViewAdapter.getCutMusicEndProgress();
				String path=musicListViewAdapter.getCutMusicPath();
				MusicPlayer.play(MainActivity.this, path,(int)startProgress);
				MusicPlayer.handler.post(MusicPlayer.run);
			}
			

		});
		/**
		 * 监听ListView子项的点击事件
		 */
		mListViewMusic.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position,
					long id) {
				// TODO Auto-generated method stub
				
				if(musicListViewAdapter!=null){
					musicListViewAdapter.setHidePlayBtn(false);
					musicListViewAdapter.setSelectItem(position);
					musicListViewAdapter.notifyDataSetChanged();
				}
				MusicPlayer.reset();
			}
		});
	}

}

七、ListView的适配器 MusicListViewAdapter.java

package com.t20.audiodemo.adapter;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.t20.audiodemo.MainActivity;
import com.t20.audiodemo.R;
import com.t20.audiodemo.entity.Music;
import com.t20.audiodemo.util.MusicPlayer;
import com.t20.audiodemo.util.MusicUtil;
import com.t20.audiodemo.view.MusicCutPopupWindow;

import android.content.Context;
import android.os.Environment;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MusicListViewAdapter extends BaseAdapter {

	private Context context;
	private List<Music> mMusicList;
	private MusicCutPopupWindow musicCutPopupWindow;
	private Music currentMusic;

	public Music getCurrentMusic() {
		return currentMusic;
	}

	public void setCurrentMusic(Music currentMusic) {
		this.currentMusic = currentMusic;
	}

	public MusicListViewAdapter(Context context, List<Music> mMusicList) {
		super();
		this.context = context;
		this.mMusicList = mMusicList;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return mMusicList.size();
	}

	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		final Music music = mMusicList.get(position);
		final int currentId=position;
		// 加载布局
		View view;
		final ViewHolder viewHolder;
		if (convertView == null) {
			view = LayoutInflater.from(context).inflate(
					R.layout.music_listview_item, null);
			viewHolder = new ViewHolder();
			// 获取控件
			viewHolder.textViewName = (TextView) view
					.findViewById(R.id.music_tv_name);
			viewHolder.textViewSinger = (TextView) view
					.findViewById(R.id.music_tv_singer);
			viewHolder.textViewDuration = (TextView) view
					.findViewById(R.id.music_tv_duration);
			viewHolder.imageViewPlay = (ImageView) view
					.findViewById(R.id.music_iv_play);
			viewHolder.imageViewPic = (ImageView) view
					.findViewById(R.id.music_iv_pic);
			viewHolder.imageViewCut = (ImageView) view
					.findViewById(R.id.music_iv_cut);
			view.setTag(viewHolder);
		} else {
			view = convertView;
			// 重新获取ViewHolder
			viewHolder = (ViewHolder) view.getTag();
		}
		// 设置控件
		viewHolder.textViewName.setText(music.getName());
		viewHolder.textViewSinger.setText(music.getSinger());
		viewHolder.textViewDuration.setText(formatTime(music.getDuration()));

		if (selectItem != -1 && selectItem == position) {
			viewHolder.imageViewPic.setEnabled(false);
			if (hidePlayBtn) {
				viewHolder.imageViewPlay.setVisibility(View.GONE);
			} else {
				viewHolder.imageViewPlay.setVisibility(View.VISIBLE);
			}
		} else {
			viewHolder.imageViewPic.setEnabled(true);
			viewHolder.imageViewPlay.setVisibility(View.VISIBLE);
		}
		// 判断播放图标是否显示
		/*
		 * if(viewHolder.imageViewPlay.getVisibility()==View.GONE){
		 * viewHolder.imageViewPic.setEnabled(false); }else{
		 * viewHolder.imageViewPic.setEnabled(true); }
		 */
		// 播放音乐按钮
		viewHolder.imageViewPlay.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View view) {
				// TODO Auto-generated method stub
				if (onplayMusicListener != null) {
					currentMusic = music;
					onplayMusicListener.playForFull();
					selectItem = currentId;
				}
			}
		});
		// 音乐剪辑
		viewHolder.imageViewCut.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View view) {
				// TODO Auto-generated method stub
				currentMusic = music;
				musicCutPopupWindow = new MusicCutPopupWindow(context,
						itemsOnClick);
				// 设置音乐信息
				musicCutPopupWindow.setMusicInfo(currentMusic.getSinger()
						+ " - " + currentMusic.getName(),
						currentMusic.getDuration());
				// 显示窗口
				musicCutPopupWindow.showAtLocation(((MainActivity) context)
						.findViewById(R.id.mainActivity_root), Gravity.BOTTOM,
						0, 0);
			}
		});

		return view;

	}
		
    //为弹出窗口实现监听类  
    private OnClickListener  itemsOnClick = new OnClickListener(){  
  
        public void onClick(View v) {  
        	
            switch (v.getId()) { 
            //确定按钮
            case R.id.popupWindow_music_cut_btn_sure:  
            	//获取最小值
            	float min=musicCutPopupWindow.getMinRule();
            	//获取最大值
            	float max=musicCutPopupWindow.getMaxRule();
            	//开始剪切音乐
            	if(currentMusic==null){
            		return;
            	}
            	//要剪切的音乐路径
            	String inputPath=currentMusic.getPath();
            	Date date=Calendar.getInstance().getTime();
            	SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddHHmmss");
            	String str=sdf.format(date);
            	//剪切后音乐文件路径
            	File sdDir = null;
        		boolean sdCardExist = Environment.getExternalStorageState().equals(
        				android.os.Environment.MEDIA_MOUNTED);// 判断sd卡是否存在
        		if (!sdCardExist) {
        			Toast.makeText(context, "SD卡不存在,保存失败", Toast.LENGTH_SHORT).show();
        			return;
        			
        		}else{
        			sdDir = Environment.getExternalStorageDirectory();// 获取根目录
        		}
            	File flie=new File(sdDir +"/audio");
            	//目录不存在就自动创建
	            if(!flie.exists()){
	            	flie.mkdirs();
	            }
            	String outputPath=flie.getPath()+"/new"+"_"+currentMusic.getName()+".mp3"; 
            	File audioPath=new File(outputPath);
            	//文件存在就先删除
            	if(audioPath.exists()){          		
            		try {
            			audioPath.delete();
						audioPath.createNewFile();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
            	}
	            
            	boolean flag=MusicUtil.clipMp3(inputPath, outputPath, (int)min*1000, (int)max*1000);
            	if(flag){
            		Toast.makeText(context, "剪辑成功,保存路径:"+outputPath, Toast.LENGTH_SHORT).show();
            		musicCutPopupWindow.dismiss();
            	}else{
            		Toast.makeText(context, "剪辑失败", Toast.LENGTH_SHORT).show();
            	}
            	break; 
            //取消按钮
             case R.id.popupWindow_music_cut_btn_cancel:
            	//关闭弹窗
         		musicCutPopupWindow.dismiss();
         		//重置音乐
         		MusicPlayer.reset();
            	break;
             //试听按钮
             case R.id.popupWindow_music_cut_tv_musicTest:
            	 cutMusicStartProgress=(long)((int)musicCutPopupWindow.getMinRule()*1000);
            	 cutMusicEndProgress=(long)((int)musicCutPopupWindow.getMaxRule()*1000);
            	 cutMusicPath=currentMusic.getPath();
            	 if(onplayMusicListener!=null){
            		 onplayMusicListener.playforPart();
            	 }
            	break; 
            }  
                  
        }  
          
    }; 
   
	class ViewHolder{
		TextView textViewName;
		TextView textViewSinger;
		TextView textViewDuration;
		ImageView imageViewPlay;
		ImageView imageViewPic;
		ImageView imageViewCut;
	}
	
	private Integer selectItem=-1;

	public Integer getSelectItem() {
		return selectItem;
	}

	public void setSelectItem(Integer selectItem) {
		this.selectItem = selectItem;
	}
	//标识是否隐藏播放按钮
	private boolean hidePlayBtn;

	public void setHidePlayBtn(boolean hidePlayBtn) {
		this.hidePlayBtn = hidePlayBtn;
	}
	/**
	 * 转换歌曲时间的格式
	 * @param time
	 * @return
	 */
	  public static String formatTime(long time) {
	      if (time / 1000 % 60 < 10) {
	          String t = time / 1000 / 60 + ":0" + time / 1000 % 60;
	          return t;
	      } else {
	          String t = time / 1000 / 60 + ":" + time / 1000 % 60;
	          return t;
	      }
	  }

	// 剪辑歌曲路径
	private String cutMusicPath;
	// 剪辑歌曲开始进度
	private long cutMusicStartProgress;
	// 剪辑歌曲结束进度
	private long cutMusicEndProgress;
	public String getCutMusicPath() {
		return cutMusicPath;
	}
	public void setCutMusicPath(String cutMusicPath) {
		this.cutMusicPath = cutMusicPath;
	}			
	public long getCutMusicStartProgress() {
		return cutMusicStartProgress;
	}
	public void setCutMusicStartProgress(long cutMusicStartProgress) {
		this.cutMusicStartProgress = cutMusicStartProgress;
	}
	public long getCutMusicEndProgress() {
		return cutMusicEndProgress;
	}
	public void setCutMusicEndProgress(long cutMusicEndProgress) {
		this.cutMusicEndProgress = cutMusicEndProgress;
	}
	/**
	 * 自定义用于播放音乐的接口
	 * @author admin
	 *
	 */
	private OnplayMusicListener onplayMusicListener;
	
	public void setOnplayMusicListener(
			OnplayMusicListener onplayMusicListener) {
		this.onplayMusicListener = onplayMusicListener;
	}

	public interface OnplayMusicListener{
		//播放完整歌曲
		void playForFull();
		//播放片段歌曲
		void playforPart();
	}
}