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>