MP3Play项目实战 (3)

1.

歌词显示  自定义控件  LrcView

public class LrcView extends TextView {
    //视图宽度
    private float width;
    //视图高度
    private float high;
    //当前播放歌词的画笔
    private Paint CurrentPaint;
    //非当前播放歌词的画笔
    private Paint NotCurrentPaint;
    //每行文字的高度
    private float TextHigh = 25;
    //非当前播放歌词的制图大小
    private float TextSize = 10;
    //歌词显示位置
    private int Index = 0;
    //歌词语句列表
    private List<LrcProcess.LrcContent> mSentenceEntities = new ArrayList<>();
    //初始化歌词语句列表
    public void setmSentenceEntities(List<LrcProcess.LrcContent> mSentenceEntities){
        this.mSentenceEntities = mSentenceEntities;
    }

    public LrcView(Context context) {
        super(context);
        init();
    }

    public LrcView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public LrcView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        setFocusable(true);
        //高亮部分
        CurrentPaint = new Paint();
        CurrentPaint.setAntiAlias(true);
        CurrentPaint.setTextAlign(Paint.Align.CENTER);
        //非高亮部分
        NotCurrentPaint = new Paint();
        NotCurrentPaint.setAntiAlias(true);
        NotCurrentPaint.setTextAlign(Paint.Align.CENTER);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (canvas == null){
            return;
        }
        CurrentPaint.setColor(Color.argb(210,251,248,29));
        NotCurrentPaint.setColor(Color.argb(140,255,255,255));
        //设置当前歌词字体和大小
        CurrentPaint.setTextSize(24);
        CurrentPaint.setTypeface(Typeface.SERIF);
        //设置非当前歌词字体和大小
        NotCurrentPaint.setTextSize(TextSize);
        NotCurrentPaint.setTypeface(Typeface.DEFAULT);
        try {
            setText("");
            //画出当前播放的歌词
            canvas.drawText(mSentenceEntities.get(Index).getLrc() , width/2 , high/2 , CurrentPaint);
            float tempY = high/2;
            //画出本句之前的歌词
            for (int i = Index - 1 ; i >= 0 ; i--){
                //向上推移一个高度
                tempY = tempY - TextHigh;
                //显示歌词
                canvas.drawText(mSentenceEntities.get(i).getLrc() , width/2 , tempY , NotCurrentPaint);
            }
            tempY = high/2;
            //画出本句之后的歌词
            for (int i  = Index + 1 ; i < mSentenceEntities.size() ; i++){
                tempY = tempY + TextHigh;
                canvas.drawText(mSentenceEntities.get(i).getLrc() , width/2 , tempY , NotCurrentPaint);
            }
        } catch (Exception e){
            setText("未找到歌词文件");
        }
    }

    //视图大小改变时调用
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.width = w;
        this.high = h;
    }

    //设置歌词显示的位置
    public void SetIndex(int index){
        this.Index = index;
    }

    //初始化歌词语句列表
    public void setSentenceEntities(List<LrcProcess.LrcContent> mSentenceEntities) {
        this.mSentenceEntities = mSentenceEntities;
    }
}

2.

歌词进程控制类   LrcProcess  用于加载歌曲对应歌词文件。其中有一个子类 LrcContent,存放每一句歌词的内容和时间信息

public class LrcProcess {
    //歌词列表
    private List<LrcContent> LrcList;
    //每一句歌词
    private LrcContent mLrcContent;

    public LrcProcess(){
        mLrcContent = new LrcContent();
        LrcList = new ArrayList<>();
    }

    //读取歌词文件内容
    public String readLrc(String song_path) {
        StringBuilder stringBuilder = new StringBuilder();
        //歌词文件与mp3文件要在同一个目录,且名字要相同
        File f = new File(song_path.replace(".mp3" , ".lrc"));
        try{
            FileInputStream fls = new FileInputStream(f);
            InputStreamReader isr = new InputStreamReader(fls,"UTF-8");
            BufferedReader br = new BufferedReader(isr);
            String s = "";
            //至于为什么歌词文件读取解析出来有[ ],去试一下就知道了,在下面有解释
            while((s=br.readLine()) != null){
                s = s.replace("[" , "");
                s = s.replace("]" , "@");
                //分离@字符
                String splitLrc_data[] = s.split("@");
                if (splitLrc_data.length > 1){
                    mLrcContent.setLrc(splitLrc_data[1]);
                    int LrcTime = TimeStr(splitLrc_data[0]);
                    mLrcContent.setLrc_time(LrcTime);
                    LrcList.add(mLrcContent);
                    mLrcContent = new LrcContent();
                }
            }
            br.close();
            isr.close();
            fls.close();
        } catch (IOException e) {
            e.printStackTrace();
            stringBuilder.append("未找到歌词!");
        }
        return stringBuilder.toString();
    }

    //与歌词解析一样,下面有解释
    private int TimeStr(String timeStr) {
        timeStr = timeStr.replace(":" , ".");
        timeStr = timeStr.replace("." , "@");
        String timeData[] = timeStr.split("@");
        int minute = Integer.parseInt(timeData[0]);
        int second = Integer.parseInt(timeData[1]);
        int millisecond = Integer.parseInt(timeData[2]);
        //计算上一行与下一行的时间,转化成 [毫秒]
        int currentTime = (minute*60+second)*1000 + millisecond*10;
        return currentTime;
    }

    public List<LrcContent> getLrcContent(){
        return LrcList;
    }

    public class LrcContent {
        private String Lrc;
        private int Lrc_time;

        public String getLrc() {
            return Lrc;
        }

        public void setLrc(String lrc) {
            Lrc = lrc;
        }

        public int getLrc_time() {
            return Lrc_time;
        }

        public void setLrc_time(int lrc_time) {
            Lrc_time = lrc_time;
        }
    }


}

解析歌词 lrc文件测试代码  及打印如下:

public class Test7 {

	public static void main(String[] args) {
		try {
			String f = "D:\\QQ音乐\\下载的歌曲\\朴树\\朴树 - 平凡之路 (Live).lrc";
			FileInputStream fls = new FileInputStream(f);
			InputStreamReader isr = new InputStreamReader(fls);
			BufferedReader br = new BufferedReader(isr);
			String s = "";
			while ((s = br.readLine()) != null) {
				System.out.println("1:  " + s);
				s = s.replace("[", "");
				System.out.println("2:  " + s);
				s = s.replace("]", "@");
				System.out.println("3:  " + s);
				// 分离@字符
				String splitLrc_data[] = s.split("@");
				if (splitLrc_data.length > 1) {
					/*splitLrc_data[1];
					splitLrc_data[0];*/
					System.out.println("4:  " + splitLrc_data[1]);
					System.out.println("5:  " + splitLrc_data[0]);
				}
			}
			br.close();
			isr.close();
			fls.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
1:  [02:10.05]我曾经堕入无边黑暗
2:  02:10.05]我曾经堕入无边黑暗
3:  02:10.05@我曾经堕入无边黑暗
4:  我曾经堕入无边黑暗
5:  02:10.05


看了测试代码,应该能理解LrcProcess类中的函数作用


3.

MainActivity.java  主逻辑代码

在写主逻辑代码之前,先解释下  三个要用到的类

第一个  MusicListView.javas  给音乐列表界面配置适配器 ,适配器类在之后会讲到

public class MusicListView {
    ListView lv_1;
    public static Music_infoAdapter m_info_1;

    public void disPlayList(ListView lv, Context context) {
        m_info_1 = new Music_infoAdapter(context);
        this.lv_1 = lv;
        this.lv_1.setAdapter(m_info_1);
    }

}

第二个   MusicSpecialView.java   自身继承BaseAdapter   给专辑列表界面GridView配置

public class MusicSpecialView extends BaseAdapter{
    public Context context;
    public static MusicSpecialView msv;
    GridView gv_1;

    public void disPlatSpecial(GridView gv, Context context) {
        this.context = context;
        //初始化视图
        msv = new MusicSpecialView();
        this.gv_1 = gv;
        this.gv_1.setAdapter(msv);
    }


    @Override
    public int getCount() {
        return Music_infoAdapter.musicList.size();
    }

    @Override
    public Object getItem(int position) {
        return Music_infoAdapter.musicList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater lif = LayoutInflater.from(MainActivity.context);
        View v = lif.inflate(R.layout.gridspecial_item , null);
        //每一行元素包括一个图片视图和两个文本视图
        ImageView iv;
        TextView tv1;
        TextView tv2;
        //初始化界面
        iv = v.findViewById(R.id.gridspecial_view1);
        tv1 = v.findViewById(R.id.album_xxx); //专辑名字
        tv2 = v.findViewById(R.id.artist_xxx); //歌手

        //获取专辑图片路径
        //下面这句代码的解释:根据音乐id得到专辑id然后[根据专辑id得到专辑图片(用getalbumArt方法)]
        String url = MainActivity.music_info.getAlbumArt( Music_infoAdapter.musicList.get(position).get_id() );
        if (url != null){
            //显示图片
            iv.setImageURI(Uri.parse(url));
        } else{
            //设置默认图片
            iv.setImageResource(R.drawable.default_album);
        }
        //动画显示图片
        iv.setAnimation(AnimationUtils.loadAnimation(MainActivity.context , R.anim.alpha_z));
        //带动画显示专辑名
        tv1.setText(Music_infoAdapter.musicList.get(position).getMusicAlbum());
        tv1.setAnimation(AnimationUtils.loadAnimation(MainActivity.context , R.anim.alpha_y));
        //带动画显示歌手名字
        tv2.setText(Music_infoAdapter.musicList.get(position).getMusicSinger());
        tv2.setAnimation(AnimationUtils.loadAnimation(MainActivity.context , R.anim.alpha_y));

        return v;
    }


}


第三个  Music_infoAdapter.java   自身继承BaseAdapter   里面有个全局变量保存全部的歌曲信息,为其他界面提供数据

其中还包含一个子类 MusicInfomation  用于存放音乐的信息,包含歌曲名字,时间,专辑id,音乐路径等

public class Music_infoAdapter extends BaseAdapter{
    //共享数据库
    public ContentResolver cr;
    //用来装载查询到的音乐文件数据
    public Cursor mCursor;
    //歌曲列表信息
    public static List<MusicInfomation> musicList;
    public MusicInfomation mi;
    public Context context;


    public Music_infoAdapter(Context context) {
        this.context = context;
        //取得数据库对象
        cr = context.getContentResolver();
        //初始化音乐列表数组
        musicList = new ArrayList<>();
        String[] s1 = new String[]{
                //歌曲名
                MediaStore.Audio.Media.DISPLAY_NAME,
                //专辑名
                MediaStore.Audio.Media.ALBUM,
                //歌手名
                MediaStore.Audio.Media.ARTIST,
                //歌曲时间
                MediaStore.Audio.Media.DURATION,
                //歌曲大小
                MediaStore.Audio.Media.SIZE,
                //歌曲id
                MediaStore.Audio.Media._ID,
                //歌曲路径
                MediaStore.Audio.Media.DATA
        };
        //查询所有音乐信息
        mCursor = cr.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI , s1 , null , null , null);
        if (mCursor != null){
            //移动到第一个
            mCursor.moveToFirst();
            //获得歌曲的各种属性
            for (int i = 0 ; i < mCursor.getCount() ; i++){
                //过滤mp3文件
                if (mCursor.getString(0).endsWith(".mp3")){
                    mi = new MusicInfomation();
                    mi.setMusicName(mCursor.getString(0));
                    mi.setMusicAlbum(mCursor.getString(1));
                    mi.setMusicSinger(mCursor.getString(2));
                    mi.setNusicTime(mCursor.getInt(3));
                    mi.setMusicSize(mCursor.getInt(4));
                    mi.set_id(mCursor.getInt(5));
                    mi.setMusicPath(mCursor.getString(6));
                    //装载到歌曲列表中
                    musicList.add(mi);
                }
                mCursor.moveToNext();
            }
        }
    }

    @Override
    public int getCount() {
        return musicList.size();
    }

    @Override
    public Object getItem(int position) {
        return musicList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater li = LayoutInflater.from(context);
        View v = li.inflate(R.layout.musiclist_item , null);
        TextView tv1;
        TextView tv2;
        TextView tv3;
        TextView tv4;
        //初始化界面元素
        tv1 = v.findViewById(R.id.tv1);
        tv2 = v.findViewById(R.id.tv2);
        tv3 = v.findViewById(R.id.tv3);
        tv4 = v.findViewById(R.id.tv4);
        //为界面元素设置内容
        tv1.setText(musicList.get(position).getMusicName());
        tv2.setText(toTime(musicList.get(position).getNusicTime()));
        tv3.setText(musicList.get(position).getMusicPath());
        tv4.setText(toMB(musicList.get(position).getMusicSize()) + "MB");

        return v;
    }

    //将b转化为mb
    public String toMB(int size) {
        float a = (float)size/(float)(1024*1024);
        String b = Float.toString(a);
        int c = b.indexOf(".");
        String filesize = "";
        filesize += b.substring(0 , c+2);
        return filesize;
    }

    public static String toTime(int time) {
        time /= 1000; //秒
        int minute = time/60;
        int second = time%60;
        minute %= 60;
        //格式化时间
        return String.format(" %02d:%02d " , minute , second);
    }

    public String getAlbumArt(int trackId) {
        //根据音乐id获取专辑图片的id
        String mUriTrack = "content://media/external/audio/media/#";
        String[] projection = new String[]{ "album_id" }; //MediaStore.Audio.Media.ALBUM_ID
        String selection = "_id = ?";
        String[] selectionArgs = new String[]{ Integer.toString(trackId) };
        Cursor mcCursor = context.getContentResolver().query(Uri.parse(mUriTrack) , projection , selection , selectionArgs , null);
        int album_id = 0;
        if (mcCursor.getCount() > 0  &&  mcCursor.getColumnCount() > 0){
            mcCursor.moveToNext();
            album_id = mcCursor.getInt(0); //专辑图片的Id
        }
        mcCursor.close();
        mcCursor = null;
        if (album_id < 0){
            return null;
        }
        //根据专辑图片id获取专辑图片的uri地址
        String mUriAlbum = "content://media/external/audio/albums";
        projection = new String[]{"album_art"}; //要搜索的东西
        mcCursor = context.getContentResolver().query(Uri.parse(mUriAlbum+"/"+Integer.toString(album_id)) , projection , null , null , null );
        String album_art = null;
        if (mcCursor.getCount() > 0  &&  mcCursor.getColumnCount() > 0){
            mcCursor.moveToNext();
            album_art = mcCursor.getString(0);
        }
        mcCursor.close();
        mcCursor = null;

        return album_art;
    }


    public static class MusicInfomation {

        private String musicName;
        private String musicAlbum;
        private String musicSinger;
        private int nusicTime;
        private String musicPath;
        private int _id;
        private int musicSize;

        public int get_id() {
            return _id;
        }

        public String getMusicAlbum() {
            return musicAlbum;
        }

        public String getMusicName() {
            return musicName;
        }

        public String getMusicPath() {
            return musicPath;
        }

        public String getMusicSinger() {
            return musicSinger;
        }

        public int getMusicSize() {
            return musicSize;
        }

        public int getNusicTime() {
            return nusicTime;
        }

        public void setMusicName(String musicName) {
            this.musicName = musicName;
        }

        public void setMusicAlbum(String musicAlbum) {
            this.musicAlbum = musicAlbum;
        }

        public void setMusicSinger(String musicSinger) {
            this.musicSinger = musicSinger;
        }

        public void setNusicTime(int nusicTime) {
            this.nusicTime = nusicTime;
        }

        public void setMusicSize(int musicSize) {
            this.musicSize = musicSize;
        }

        public void set_id(int _id) {
            this._id = _id;
        }

        public void setMusicPath(String musicPath) {
            this.musicPath = musicPath;
        }
    }


}

4.

接下来才是真正的   MainActivity.java  主逻辑代码


public class MainActivity extends Activity {
    ImageButton left_ImageButton;
    public static ImageButton play_ImageButton;
    ImageButton right_ImageButton;
    //音乐列表
    ListView musicListView;
    //专辑列表
    GridView musicGridView;
    //上下文
    public static Context context;
    //初始化歌词检索值
    public int Index = 0;
    //为后台播放通知创建对象
    public static NotificationManager mNotificationManager;
    //绑定seekbar和各种属性textview
    public static SeekBar seekBar;
    public static TextView time_left;
    public static TextView time_right;
    public static LrcView lrc_view;
    public static TextView music_Name;
    public static TextView music_Album;
    public static TextView music_Artist;
    public static ImageView music_AlbumArt;
    public static TextView music_number;

    //左侧动画
    public static RunGif runEql;
    //为倒影创建对象
    public RelativeLayout relativeflac;
    public static ImageView reflaction;
    //为歌曲时间和播放时间定义静态变量
    public static int song_time = 0;
    public static int play_time = 0;
    //为music_infoadapter声明静态变量
    public static Music_infoAdapter music_info;
    //声明两个页面对象
    private BigDragableLuncher bigPage;
    private DragableLuncher smallPage;
    //声明按钮及对应的图片
    private ImageButton[] blind_bnt = new ImageButton[3];
    private int[] btn_id = new int[]{R.id.imageButton1 , R.id.imageButton2 , R.id.imageButton3};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        bigPage = findViewById(R.id.all_space);
        //中间滑动模块
        smallPage = findViewById(R.id.space);
        //绑定gif动画界面
        runEql = findViewById(R.id.runGif1);
        //倒影布局
        relativeflac = findViewById(R.id.reltive1);
        //倒影
        reflaction = findViewById(R.id.inverted_view);
        //创建对象获取系统服务
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //绑定歌曲列表界面
        musicListView = findViewById(R.id.listview1);
        new MusicListView().disPlayList(musicListView , this);
        //将获取的歌曲属性放到当前适配器中
        music_info = new Music_infoAdapter(this);
        //绑定专辑列表界面
        musicGridView = findViewById(R.id.gridview1);
        new MusicSpecialView().disPlatSpecial(musicGridView , this);

        //音乐列表界面单击事件
        musicListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent play_1 = new Intent(MainActivity.this , ControlPlay.class);
                play_1.putExtra("control" , "listClick");
                play_1.putExtra("musicId_1" , position);
                //打开音乐播放服务
                startService(play_1);
                //在音乐列表里点了一首歌,要跳转到音乐播放界面
                bigPage.setAnimation(AnimationUtils.loadAnimation(MainActivity.this , R.anim.alpha_x));
                bigPage.setToscreen(1);
                blind_bnt[1].setBackgroundResource(R.drawable.big_button_pressed);
                blind_bnt[0].setBackgroundResource(R.drawable.big_button_style);

            }
        });

        //专辑列表单击事件
        musicGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent play_2 = new Intent(MainActivity.this , ControlPlay.class);
                play_2.putExtra("control" , "gridClick");
                play_2.putExtra("musicId_2" , position);
                startService(play_2);
                //单击后跳转到播放界面
                bigPage.setAnimation(AnimationUtils.loadAnimation(MainActivity.this , R.anim.alpha_x));
                bigPage.setToscreen(1);
                blind_bnt[1].setBackgroundResource(R.drawable.big_button_pressed);
                blind_bnt[0].setBackgroundResource(R.drawable.big_button_style);

            }
        });

        smallPage.isOpenTouchAnima(true);
        //绑定imageButton
        for (int k = 0 ; k < blind_bnt.length ; k++) {
            blind_bnt[k] = findViewById(btn_id[k]);
        }

        //设置按钮被选中颜色和默认颜色
        bigPage.setBottombarBg(blind_bnt , Color.GREEN , Color.YELLOW);
        //判断单击了那个按钮,跳转页面
        View.OnClickListener ocl = new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                switch(v.getId()){
                    //音乐列表
                    case R.id.imageButton1:
                        bigPage.setAnimation(AnimationUtils.loadAnimation(MainActivity.this ,R.anim.alpha_x));
                        bigPage.setToscreen(0);
                        v.setPressed(true);
                        blind_bnt[0].setBackgroundResource(R.drawable.big_button_pressed);
                        blind_bnt[1].setBackgroundResource(R.drawable.big_button_style);
                        blind_bnt[2].setBackgroundResource(R.drawable.big_button_style);
                        break;
                    //播放界面
                    case R.id.imageButton2:
                        bigPage.setAnimation(AnimationUtils.loadAnimation(MainActivity.this , R.anim.alpha_x));
                        bigPage.setToscreen(1);
                        v.setPressed(true);
                        blind_bnt[1].setBackgroundResource(R.drawable.big_button_pressed);
                        blind_bnt[0].setBackgroundResource(R.drawable.big_button_style);
                        blind_bnt[2].setBackgroundResource(R.drawable.big_button_style);
                        break;
                    //专辑界面
                    case R.id.imageButton3:
                        bigPage.setAnimation(AnimationUtils.loadAnimation(MainActivity.this , R.anim.alpha_x));
                        bigPage.setToscreen(2);
                        v.setPressed(true);
                        blind_bnt[2].setBackgroundResource(R.drawable.big_button_pressed);
                        blind_bnt[0].setBackgroundResource(R.drawable.big_button_style);
                        blind_bnt[1].setBackgroundResource(R.drawable.big_button_style);
                        break;
                }
            }
        };

        //初始化设置
        blind_bnt[1].setBackgroundResource(R.drawable.big_button_pressed);
        blind_bnt[0].setOnClickListener(ocl);
        blind_bnt[1].setOnClickListener(ocl);
        blind_bnt[2].setOnClickListener(ocl);
        //初始化按钮
        left_ImageButton = findViewById(R.id.ib1);
        play_ImageButton = findViewById(R.id.ib2);
        right_ImageButton = findViewById(R.id.ib3);
        //初始化界面其它元素
        time_left = findViewById(R.id.time_tv1);
        time_right = findViewById(R.id.time_tv2);
        music_Name = findViewById(R.id.music_name);
        music_Album = findViewById(R.id.music_album);
        music_Artist = findViewById(R.id.music_artist);
        seekBar = findViewById(R.id.player_seekbar);
        lrc_view = findViewById(R.id.LrcShow);
        music_number = findViewById(R.id.music_number);
        music_AlbumArt = (ImageView)findViewById(R.id.music_AlbumArt);

        //判断歌曲数量不能为空 且后缀为 .mp3
        if (music_info.getCount() > 0 && Music_infoAdapter.musicList.get(ControlPlay.playing_id)
                .getMusicName().endsWith(".mp3")
                ) {
            //显示获取的歌曲时间
            time_right.setText(Music_infoAdapter.toTime(Music_infoAdapter.musicList.get(ControlPlay.playing_id).getNusicTime()));
            //截取.mp3字符串
            String a = Music_infoAdapter.musicList.get(ControlPlay.playing_id).getMusicName();
            int b = a.indexOf(".mp3");
            String c = a.substring(0 , b);
            //显示歌曲名字
            music_Name.setText(c);
            music_Name.setAnimation(AnimationUtils.loadAnimation(MainActivity.this , R.anim.alpha_z));

            //显示当前播放第几首歌和歌曲总数
            int x = ControlPlay.playing_id + 1;
            music_number.setText("" + x + "/" + Music_infoAdapter.musicList.size());
            //显示获取的艺术家
            music_Artist.setText(Music_infoAdapter.musicList.get(ControlPlay.playing_id).getMusicSinger());
            //获取专辑图片的路径
            String url = MainActivity.music_info.getAlbumArt(Music_infoAdapter.musicList.get(ControlPlay.playing_id).get_id());
            if (url != null) {
                //显示获取的专辑图片
                music_AlbumArt.setImageURI(Uri.parse(url));
                music_AlbumArt.setAnimation(AnimationUtils.loadAnimation(context,R.anim.alpha_z));
                try{
                    //为倒影创建位图
                    Bitmap mBitmap = BitmapFactory.decodeFile(url);
                    reflaction.setImageBitmap(createReflectedImage(mBitmap));
                    reflaction.setAnimation(AnimationUtils.loadAnimation(context,R.anim.alpha_z));
                } catch (Exception e){
                    e.printStackTrace();
                }
            } else {
                //设置默认图片
                music_AlbumArt.setImageResource(R.drawable.album);
                music_AlbumArt.setAnimation(AnimationUtils.loadAnimation(context , R.anim.alpha_z));
                //为倒影创建位图
                try{
                    Bitmap mBitmap = ((BitmapDrawable)(getResources().getDrawable(R.drawable.album))).getBitmap();
                    reflaction.setImageBitmap(createReflectedImage(mBitmap));
                    reflaction.setAnimation(AnimationUtils.loadAnimation(context , R.anim.alpha_z));
                } catch (Exception e){
                    e.printStackTrace();
                }
            }
        } else {
            Toast.makeText(context, "手机里未找到歌曲哦", Toast.LENGTH_SHORT).show();
        }

        //监听seekbar事件
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //判断用户是否触摸seekbar并且不为空
                if (fromUser && ControlPlay.myMediaPlayer != null){
                    ControlPlay.myMediaPlayer.seekTo(progress);
                }
                time_left.setText(Music_infoAdapter.toTime(progress));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        //上一首按钮监听
        left_ImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //打开音乐服务
                Intent play_left = new Intent(MainActivity.this , ControlPlay.class);
                play_left.putExtra("control" , "front");
                startService(play_left);
            }
        });

        //播放按钮监听
        play_ImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent play_center = new Intent(MainActivity.this , ControlPlay.class);
                play_center.putExtra("control" , "play");
                startService(play_center);
            }
        });

        //下一首功能实现
        right_ImageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent play_right = new Intent(MainActivity.this , ControlPlay.class);
                play_right.putExtra("control" , "next");
                startService(play_right);
            }
        });
    }

    static Bitmap createReflectedImage(Bitmap originalBitmap){
        //图片与倒影间距
        final int reflectionGap = 4;
        //图片宽度
        int width = originalBitmap.getWidth();
        int height = originalBitmap.getHeight();
        Matrix matrix = new Matrix();
        matrix.preScale(1,-1);
        //创建倒影图片,高度为原图的一半
        Bitmap reflectionBitmap = Bitmap.createBitmap(originalBitmap , 0 , height/2 , width , height/2 , matrix , false);
        //创建标准标准的Bitmaop对象,宽度和原图一致,,高度为原图1.5倍
/*      ARGB指的是一种 色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue.
        其实所有的可见色都是右红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值
        ALPHA_8就是Alpha由8位组成
        ARGB_4444就是由4个4位组成即16位
        ARGB_8888就是由4个8位组成即32位
        RGB_565就是R为5位,G为6位,B为5位共16位
        ALPHA_8——代表8位Alpha位图
        ARGB_4444——代表16位ARGB位图
        ARGB_8888——代表32位ARGB位图
        RGB_565——代表8位RGB位图
        位图位数越高代表其可以存储的颜色信息越多,图像也就越逼真*/
        Bitmap widthReflectionBitmap = Bitmap.createBitmap(width , (height+height/2+reflectionGap) , Bitmap.Config.ARGB_8888);
        //传入bitmap对象,在空图上画图
        Canvas canvas = new Canvas(widthReflectionBitmap);
        //画原始图片
        canvas.drawBitmap(originalBitmap , 0 , 0 , null);
        //画间隔矩形
        Paint defaultPain = new Paint();
        canvas.drawRect(0,height,width,height+reflectionGap,defaultPain);
        //画倒影图片
        canvas.drawBitmap(reflectionBitmap , 0 , height+reflectionGap , null);
        //实现倒影效果
        Paint paint = new Paint();
        LinearGradient shader = new LinearGradient(0 , originalBitmap.getHeight() , 0 ,
                widthReflectionBitmap.getHeight() , 0x70ffffff ,
                0x00ffffff , Shader.TileMode.MIRROR
        );
        paint.setShader(shader);
        //过渡模式讲解:https://www.cnblogs.com/libertycode/p/6290497.html
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //覆盖效果
        canvas.drawRect(0,height,width,widthReflectionBitmap.getHeight() , paint);
        return widthReflectionBitmap;
    }

    //按下返回键后,提示用户是否退出程序
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            Dialog dialog = new MyDialog(MainActivity.this, R.style.MyDialog);
            dialog.setCanceledOnTouchOutside(true);
            dialog.show();
        }

        return super.onKeyDown(keyCode, event);
    }

    //后台提示播放通知的方法
    public static void setNotice(String tickerText , String title , String content , int drawable) {
        //创建一个通知对象,传入相应的参数
        //Notification notification = new Notification(drawable , tickerText , System.currentTimeMillis());
        //设置通知不能被清除
        //notification.flags = Notification.FLAG_NO_CLEAR;
        PendingIntent contentIntent = PendingIntent.getActivity(context , 0 ,
                new Intent(context , MainActivity.class) , 0
                );
        Notification notification = new NotificationCompat.Builder(context)
                .setSmallIcon(drawable)
                .setTicker(tickerText)
                .setWhen(System.currentTimeMillis())
                .setContentTitle(title)
                .setContentText(content)
                .setContentIntent(contentIntent)
                .build();
        notification.flags = Notification.FLAG_NO_CLEAR;
        mNotificationManager.notify(1 , notification);
    }

    //自定义对话框的类
    class MyDialog extends Dialog{
        Context context;

        public MyDialog(Context context) {
            super(context);
            this.context = context;
        }

        public MyDialog(Context context, int themeResId) {
            super(context, themeResId);
            this.context = context;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.setContentView(R.layout.dialog);
            Button exit_button , return_button;
            exit_button = findViewById(R.id.exit_button2);
            return_button = findViewById(R.id.return_button3);

            exit_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //关掉音乐服务
                    stopService(new Intent(MainActivity.this , ControlPlay.class));
                    mNotificationManager.cancel(1);
                    //退出程序
                    System.exit(0);
                }
            });

            return_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //关闭对话框
                    dismiss();
                }
            });
        }
    }


}

dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="#00000000"
    android:gravity="center_vertical|center_horizontal"
    >
    <RelativeLayout
        android:layout_width="280dip"
        android:layout_height="152dip"
        android:background="#eeffffff"
        >
        <!--对话框顶部背景-->
        <ImageView
            android:id="@+id/dlg_top"
            android:background="@drawable/dlg_top_background"
            android:layout_width="fill_parent"
            android:layout_height="40dip" />
        <!--对话框旁边icon-->
        <ImageView
            android:id="@+id/imageView1"
            android:layout_marginLeft="10dip"
            android:layout_marginTop="2dip"
            android:src="@drawable/dlg_untitled"
            android:layout_width="37.6dip"
            android:layout_height="37.6dip" />
        <!--对话框标题-->
        <TextView
            android:layout_marginLeft="60dip"
            android:layout_marginTop="7dip"
            android:text="MP3播放器"
            android:textColor="#ffffff"
            android:textSize="20sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <!--对话框消息-->
        <TextView
            android:id="@+id/tv1"
            android:layout_below="@+id/dlg_top"
            android:layout_marginLeft="30dip"
            android:layout_marginTop="10dip"
            android:text="确定要退出?"
            android:textColor="#333399"
            android:textSize="22dp"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <!--分割线-->
        <View
            android:layout_below="@+id/tv1"
            android:layout_marginTop="12dip"
            android:background="#6f999999"
            android:layout_width="fill_parent"
            android:layout_height="1px"/>
        <Button
            android:id="@+id/exit_button2"
            android:layout_alignLeft="@+id/imageView1"
            android:layout_below="@+id/tv1"
            android:layout_marginTop="20dp"
            android:background="@drawable/dlg_button_style"
            android:text="退出"
            android:textColor="#b1ffffff"
            android:textSize="18sp"
            android:layout_width="70dip"
            android:layout_height="32dip" />

        <Button
            android:id="@+id/return_button3"
            android:layout_width="70dip"
            android:layout_height="32dip"
            android:layout_alignTop="@+id/exit_button2"
            android:layout_toRightOf="@+id/tv1"
            android:background="@drawable/dlg_button_style"
            android:text="返回"
            android:textColor="#b1ffffff"
            android:textSize="18sp"
            />

    </RelativeLayout>

</LinearLayout>




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值