手机影音项目笔记(三)---音乐播放的处理
2016-11-03 17:45
411 查看
音乐列表的适配器
public class AudioListAdapter extends CursorAdapter { public AudioListAdapter(Context context, Cursor c) { super(context, c); } public AudioListAdapter(Context context, Cursor c, boolean autoRequery) { super(context, c, autoRequery); } public AudioListAdapter(Context context, Cursor c, int flags) { super(context, c, flags); } @Override // 创建新的View,并初始化ViewHolder public View newView(Context context, Cursor cursor, ViewGroup parent) { View view = View.inflate(context, R.layout.audio_item,null); ViewHolder holder = new ViewHolder(); holder.tv_title = (TextView) view.findViewById(R.id.audio_item_tv_title); holder.tv_artist = (TextView) view.findViewById(R.id.audio_item_tv_artist); view.setTag(holder); return view; } @Override // 填充界面。cursor已经被移动到要获取数据的行 public void bindView(View view, Context context, Cursor cursor) { ViewHolder holder = (ViewHolder) view.getTag(); // 获取数据 String title = cursor.getString(cursor.getColumnIndex(Media.DISPLAY_NAME)); title = StringUtils.formatTitle(title); String artist = cursor.getString(cursor.getColumnIndex(Media.ARTIST)); // 填充内容 holder.tv_title.setText(title); holder.tv_artist.setText(artist); } private class ViewHolder{ TextView tv_title,tv_artist; } }
音乐列表的fragment
public class AudioListFragment extends BaseFragment { private ListView listView; private AudioListAdapter mAdapter; @Override protected int getLayoutId() { return R.layout.fragment_audio_list; } @Override protected void initView() { listView = (ListView) findViewById(R.id.listview); } @Override protected void initListener() { mAdapter = new AudioListAdapter(getActivity(), null); listView.setAdapter(mAdapter); listView.setOnItemClickListener(new OnAudioItemClickListener()); } @Override protected void initData() { // 获取音频数据 ContentResolver resolver = getActivity().getContentResolver(); // Cursor cursor = resolver.query(Media.EXTERNAL_CONTENT_URI, new String[]{Media.DATA, Media.DISPLAY_NAME, Media.ARTIST, Media._ID}, null, null, null); // CursorUtils.printCursor(cursor); // mAdapter.swapCursor(cursor); // 子线程查询数据库 AsyncQueryHandler asyncQueryHandler = new MyAsyncQueryHandler(resolver); asyncQueryHandler.startQuery(0, mAdapter,Media.EXTERNAL_CONTENT_URI, new String[]{Media.DATA, Media.DISPLAY_NAME, Media.ARTIST, Media._ID}, null, null, null); } @Override protected void processClick(View v) { } private class OnAudioItemClickListener implements AdapterView.OnItemClickListener { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 获取数据 Cursor cursor = (Cursor) mAdapter.getItem(position); ArrayList<AudioItem> audioItems = AudioItem.parserListFromCursor(cursor); // 跳转到播放界面 Intent intent = new Intent(getActivity(), AudioPlayerActivity.class); intent.putExtra("audioItems",audioItems); intent.putExtra("position",position); startActivity(intent); } } }AudioPlayeractivity
public class AudioPlayerActivity extends BaseActivity { private static final int MSG_UPDATE_POSITION = 0; private static final int MSG_ROLLING_LYRICS = 1; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case MSG_UPDATE_POSITION: startUpdatePosition(); break; case MSG_ROLLING_LYRICS: startRollingLyrics(); break; } } }; private AudioServiceConnection conn; private AudioService.AudioBinder mAudioBinder; private ImageView iv_pause; private AudioReceiver audioReceiver; private TextView tv_title; private TextView tv_artist; private ImageView iv_wave; private TextView tv_position; private SeekBar sk_position; private ImageView iv_pre; private ImageView iv_next; private ImageView iv_playmode; private LyricsView lyricsView; @Override protected int getLayoutId() { return R.layout.activity_audio_player; } @Override protected void initView() { // 顶部面板 tv_title = (TextView) findViewById(R.id.audio_tv_title); // 中间部分 tv_artist = (TextView) findViewById(R.id.audio_tv_artist); iv_wave = (ImageView) findViewById(R.id.audio_iv_wave); lyricsView = (LyricsView) findViewById(R.id.audio_lyricsview); // 底部部分 tv_position = (TextView) findViewById(R.id.audio_tv_position); sk_position = (SeekBar) findViewById(R.id.audio_sk_position); iv_pause = (ImageView) findViewById(R.id.audio_iv_pause); iv_pre = (ImageView) findViewById(R.id.audio_iv_pre); iv_next = (ImageView) findViewById(R.id.audio_iv_next); iv_playmode = (ImageView) findViewById(R.id.audio_iv_playmode); } @Override protected void initListener() { iv_pause.setOnClickListener(this); iv_pre.setOnClickListener(this); iv_next.setOnClickListener(this); iv_playmode.setOnClickListener(this); sk_position.setOnSeekBarChangeListener(new OnAudioSeekBarChangeListener()); // 注册广播 IntentFilter filter = new IntentFilter("com.itheima.onPrepared"); audioReceiver = new AudioReceiver(); registerReceiver(audioReceiver, filter); } @Override protected void initData() { // 将数据转交给后台服务 Intent intent = new Intent(getIntent()); intent.setClass(this, AudioService.class); startService(intent); conn = new AudioServiceConnection(); bindService(intent, conn, BIND_AUTO_CREATE); // 开启示波器动画 AnimationDrawable wave_anim = (AnimationDrawable) iv_wave.getDrawable(); wave_anim.start(); } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); unregisterReceiver(audioReceiver); mHandler.removeCallbacksAndMessages(null); } @Override protected void processClick(View v) { switch (v.getId()){ case R.id.audio_iv_pause: switchPauseStatus(); break; case R.id.audio_iv_pre: playPre(); break; case R.id.audio_iv_next: playNext(); break; case R.id.audio_iv_playmode: switchPlayMode(); break; } } // 依次切换播放模式 private void switchPlayMode() { mAudioBinder.switchPlayMode(); updatePlayModeBtn(); } // 根据当前的播放模式,切换使用的图片 private void updatePlayModeBtn() { switch (mAudioBinder.getPlayMode()){ case AudioService.PLAYMODE_ALLREPEAT: iv_playmode.setImageResource(R.drawable.audio_playmode_allrepeat_selector); break; case AudioService.PLAYMODE_SINGLEREPEAT: iv_playmode.setImageResource(R.drawable.audio_playmode_singlerepeat_selector); break; case AudioService.PLAYMODE_RANDOM: iv_playmode.setImageResource(R.drawable.audio_playmode_random_selector); break; } } // 播放上一曲 private void playPre() { mAudioBinder.playPre(); } // 播放下一曲 private void playNext() { mAudioBinder.playNext(); } // 切换播放状态 private void switchPauseStatus() { mAudioBinder.switchPasueStatus(); updatePauseBtn(); } // 更新暂停按钮的图片 private void updatePauseBtn() { if (mAudioBinder.isPlaying()){ // 正在播放 iv_pause.setImageResource(R.drawable.audio_pause_selector); }else{ // 暂停状态 iv_pause.setImageResource(R.drawable.audio_play_selector); } } // 更新播放进度,并稍后再次更新 private void startUpdatePosition() { int duration = mAudioBinder.getDuration(); int position = mAudioBinder.getCurrentPosition(); CharSequence duraionStr = StringUtils.formatTime(duration); CharSequence positionStr = StringUtils.formatTime(position); tv_position.setText(positionStr +" / "+duraionStr); sk_position.setMax(duration); sk_position.setProgress(position); // 发送延迟消息 mHandler.sendEmptyMessageDelayed(MSG_UPDATE_POSITION,500); } // 使用当前播放进度更新歌词高亮行,并稍后再次更新 private void startRollingLyrics() { lyricsView.computeCenterIndex(mAudioBinder.getCurrentPosition(),mAudioBinder.getDuration()); // 发送消息,再次滚动歌词 mHandler.sendEmptyMessage(MSG_ROLLING_LYRICS); } //这个广播是用来接收 从服务返回的数据的 private class AudioReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ("com.itheima.onPrepared".equals(action)){ // 音乐准备完毕,开始播放 updatePauseBtn(); // 获取正在播放的歌曲 AudioItem audioItem = (AudioItem) intent.getSerializableExtra("audioItem"); logE("AudioReceiver.onReceive,item="+audioItem); // 更新歌曲信息 tv_title.setText(audioItem.getTitle()); tv_artist.setText(audioItem.getArtist()); // 开启进度更新 startUpdatePosition(); // 更新播放模式 updatePlayModeBtn(); // 开始滚动歌词 // File lyricsFile = new File(Environment.getExternalStorageDirectory(),"Download/audio/"+audioItem.getTitle()+".lrc"); File lyricsFile = LyricsLoader.loadFile(audioItem.getTitle()); lyricsView.setLyricsFile(lyricsFile); startRollingLyrics(); } } } private class AudioServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { mAudioBinder = (AudioService.AudioBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { } } private class OnAudioSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // 不是用户发起的变化,则不处理 if (!fromUser){ return; } // 跳转播放进度 mAudioBinder.seekTo(progress); } @Override public void onSt f7f9 artTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } } }
音乐播放 需要开启服务
public class AudioService extends Service { private static final String TAG = "AudioService"; public static final int PLAYMODE_ALLREPEAT = 0; public static final int PLAYMODE_SINGLEREPEAT = 1; public static final int PLAYMODE_RANDOM = 2; private int mPlayMode = PLAYMODE_ALLREPEAT; private static final int NOTIFY_PRE = 0; private static final int NOTIFY_NEXT = 1; private static final int NOTIFY_CONTENT = 2; private static final String NOTIFY_KEY = "notify_type"; private AudioBinder mAudioBinder; private ArrayList<AudioItem> audioItems; private int position = -1; @Override public void onCreate() { super.onCreate(); mAudioBinder = new AudioBinder(); //获取播放模式 SharedPreferences preferences = getSharedPreferences("config", MODE_PRIVATE); mPlayMode = preferences.getInt("playmode", PLAYMODE_ALLREPEAT); } @Nullable @Override public IBinder onBind(Intent intent) { return mAudioBinder; } @Override public int onStartCommand(Intent intent, int flags, int startId) { int notifyType = intent.getIntExtra(NOTIFY_KEY, -1); if (notifyType!=-1){ // 从通知栏打开的 switch (notifyType){ case NOTIFY_PRE: mAudioBinder.playPre(); break; case NOTIFY_NEXT: mAudioBinder.playNext(); break; case NOTIFY_CONTENT: notifyUI(); break; } }else{ // 从播放界面打开服务 int position = intent.getIntExtra("position", -1); if (position != this.position){ // 不同的歌曲 this.position = position; audioItems = (ArrayList<AudioItem>) intent.getSerializableExtra("audioItems"); // 播放选中的音乐 mAudioBinder.playItem(); }else{ // 重复的歌曲 notifyUI(); } } return super.onStartCommand(intent, flags, startId); } public class AudioBinder extends Binder { private class OnAudioPreparedListener implements MediaPlayer.OnPreparedListener { @Override // 资源准备完毕 public void onPrepared(MediaPlayer mp) { // 开始播放 mediaPlayer.start(); // 显示通知 showNotification(); // 通知界面更新 通过发送广播的形式 notifyUI(); } } private class OnAudioCompletionListener implements MediaPlayer.OnCompletionListener { @Override // 播放结束 public void onCompletion(MediaPlayer mp) { autoPlayNext(); } } private MediaPlayer mediaPlayer; // 播放当前 position 指定的歌曲 public void playItem(){ // 验证数据可用性 if (audioItems.size() == 0 || position == -1) { return ; } AudioItem audioItem = audioItems.get(position); LogUtils.e(TAG, "AudioService.onStartCommand,item=" + audioItem); // 播放音乐 try { if (mediaPlayer!=null){ mediaPlayer.reset(); }else { mediaPlayer = new MediaPlayer(); } mediaPlayer.setDataSource(audioItem.getPath()); mediaPlayer.prepareAsync(); mediaPlayer.setOnCompletionListener(new OnAudioCompletionListener()); mediaPlayer.setOnPreparedListener(new OnAudioPreparedListener()); } catch (IOException e) { e.printStackTrace(); } } // 切换播放状态 public void switchPasueStatus() { if (mediaPlayer.isPlaying()){ // 正在播放 mediaPlayer.pause(); cancelNotification(); }else{ // 暂停状态 mediaPlayer.start(); showNotification(); } } // 如果返回 true 则说明歌曲正在播放 public boolean isPlaying(){ return mediaPlayer.isPlaying(); } // 返回当前歌曲的总时长 public int getDuration(){ return mediaPlayer.getDuration(); } // 返回当前歌曲的播放位置 public int getCurrentPosition(){ return mediaPlayer.getCurrentPosition(); } // 跳转到指定毫秒值处播放 public void seekTo(int msec){ mediaPlayer.seekTo(msec); } // 播放上一曲 public void playPre(){ if (position!=0){ position--; playItem(); }else{ Toast.makeText(AudioService.this, "已经是第一首了", Toast.LENGTH_SHORT).show(); } } // 播放下一曲 public void playNext(){ if (position!=audioItems.size()-1){ position++; playItem(); }else{ Toast.makeText(AudioService.this, "已经是最后一首了", Toast.LENGTH_SHORT).show(); } } // 依次切换 列表循环、单曲循环、随机播放 public void switchPlayMode(){ switch (mPlayMode){ case PLAYMODE_ALLREPEAT://循环播放 ---->单曲循环 mPlayMode = PLAYMODE_SINGLEREPEAT; break; case PLAYMODE_SINGLEREPEAT://单曲循环 --->随机播放 mPlayMode = PLAYMODE_RANDOM; break; case PLAYMODE_RANDOM:// 随机播放-----> 循环播放 mPlayMode = PLAYMODE_ALLREPEAT; break; } LogUtils.e(TAG,"AudioBinder.switchPlayMode,playmode="+mPlayMode); // 保存播放模式到配置文件 SharedPreferences preferences = getSharedPreferences("config", MODE_PRIVATE); preferences.edit().putInt("playmode",mPlayMode).commit(); } /** 返回当前使用的播放模式。 */ public int getPlayMode(){ return mPlayMode; } /**根据当前的播放模式,自动切换下一首歌*/ private void autoPlayNext() { switch (mPlayMode){ case PLAYMODE_ALLREPEAT: // 列表循环,自动查找下一首歌播放。如果已经是最后一首歌,则回到第一首歌 if (position!=audioItems.size()-1){ position++; }else{ position = 0; } break; case PLAYMODE_SINGLEREPEAT: // 保持当前位置,重新播放即可 break; case PLAYMODE_RANDOM: position = new Random().nextInt(audioItems.size()); break; } playItem(); } } // 通知界面更新 private void notifyUI() { // 获取当前播放的歌曲 AudioItem audioItem = audioItems.get(position); // 通知界面更新 Intent intent = new Intent("com.itheima.onPrepared"); intent.putExtra("audioItem",audioItem); sendBroadcast(intent); } // 取消通知 private void cancelNotification() { NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); manager.cancel(0); } // 显示通知 private void showNotification() { // 创建通知对象 Notification notification; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // 小于Android 3.0的版本 notification = getNotificationByOldApi(); } else { // Notification notification = getNotificationByNewApi(); notification = getCustomNotificationByNewApi(); } // 显示通知 NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); manager.notify(0, notification); } // 使用新API来生成一个自定义布局的通知 @TargetApi(Build.VERSION_CODES.HONEYCOMB) private Notification getCustomNotificationByNewApi() { Notification.Builder builder = new Notification.Builder(this);// 在 Android 3.0 以后才可用 builder.setSmallIcon(R.mipmap.icon) .setTicker("正在播放:"+getCurrentItem().getTitle()) .setContent(getRemoteViews()) .setOngoing(true); return builder.getNotification(); } // 使用新 API 来生成通知对象 @TargetApi(Build.VERSION_CODES.HONEYCOMB) private Notification getNotificationByNewApi() { Notification.Builder builder = new Notification.Builder(this);// 在 Android 3.0 以后才可用 builder.setSmallIcon(R.mipmap.icon) .setTicker("正在播放:"+getCurrentItem().getTitle()) .setWhen(System.currentTimeMillis()) .setContentTitle(getCurrentItem().getTitle()) .setContentText(getCurrentItem().getArtist()) .setContentIntent(getContentIntent()) .setAutoCancel(true)// 点击后自动隐藏通知 .setOngoing(true); return builder.getNotification(); } @NonNull // 使用旧的API生成一个通知对象 private Notification getNotificationByOldApi() { Notification notification = new Notification(R.mipmap.icon,"正在播放:"+getCurrentItem().getTitle(),System.currentTimeMillis()); // notification.setLatestEventInfo(this,getCurrentItem().getTitle(),getCurrentItem().getArtist(),getContentIntent());// 该方法在 Android6.0 被删除 notification.flags = Notification.FLAG_ONGOING_EVENT; return notification; } // 返回自定义通知使用的布局 private RemoteViews getRemoteViews() { RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.audio_notify); // 设置文本 remoteViews.setTextViewText(R.id.audio_notify_tv_title,getCurrentItem().getTitle()); remoteViews.setTextViewText(R.id.audio_notify_tv_artist,getCurrentItem().getArtist()); // 设置点击监听 remoteViews.setOnClickPendingIntent(R.id.audio_notify_iv_pre,getPreIntent()); remoteViews.setOnClickPendingIntent(R.id.audio_notify_iv_next,getNextIntent()); remoteViews.setOnClickPendingIntent(R.id.audio_notify_layout,getContentIntent()); return remoteViews; } // 返回上一曲的点击响应 private PendingIntent getPreIntent() { Intent intent = new Intent(this,AudioService.class); intent.putExtra(NOTIFY_KEY, NOTIFY_PRE); return PendingIntent.getService(this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT); } // 返回下一曲的点击响应 private PendingIntent getNextIntent() { Intent intent = new Intent(this,AudioService.class); intent.putExtra(NOTIFY_KEY, NOTIFY_NEXT); return PendingIntent.getService(this,1,intent,PendingIntent.FLAG_UPDATE_CURRENT); } // 返回正文被点击时的响应intent private PendingIntent getContentIntent() { Intent intent = new Intent(this,AudioPlayerActivity.class); intent.putExtra(NOTIFY_KEY,NOTIFY_CONTENT); return PendingIntent.getActivity(this,2,intent,PendingIntent.FLAG_UPDATE_CURRENT); } private AudioItem getCurrentItem(){ return audioItems.get(position); } }音乐数据的bean
public class AudioItem implements Serializable { private String title; private String artist; private String path; // 解析 cursor 当前行的数据 public static AudioItem parserCursor(Cursor cursor) { AudioItem item = new AudioItem(); // 健壮性检查 if (cursor == null || cursor.getCount() == 0) { return item; } item.title = cursor.getString(cursor.getColumnIndex(Media.DISPLAY_NAME)); item.title = StringUtils.formatTitle(item.title); item.artist = cursor.getString(cursor.getColumnIndex(Media.ARTIST)); item.path = cursor.getString(cursor.getColumnIndex(Media.DATA)); return item; } public static ArrayList<AudioItem> parserListFromCursor(Cursor cursor) { ArrayList<AudioItem> audioItems = new ArrayList<>(); // 健壮性检查 if (cursor == null || cursor.getCount() == 0) { return audioItems; } cursor.moveToPosition(-1);// 移动到列表最前面再解析 while (cursor.moveToNext()) { AudioItem videoItem = parserCursor(cursor); audioItems.add(videoItem); } return audioItems; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getArtist() { return artist; } public void setArtist(String artist) { this.artist = artist; } public String getPath() { return path; } public void setPath(String path) { this.path = path; } @Override public String toString() { return "AudioItem{" + "title='" + title + '\'' + ", artist='" + artist + '\'' + ", path='" + path + '\'' + '}'; } }
布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@mipmap/base_bg" android:orientation="vertical" tools:context="com.itcast.mobileplayer91.ui.activity.AudioPlayerActivity"> <include layout="@layout/activity_audio_player_top" /> <include layout="@layout/activity_audio_player_middle" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <include layout="@layout/activity_audio_player_bottom" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@mipmap/base_titlebar_bg" android:orientation="vertical"> <!--返回按钮--> <ImageView android:id="@id/back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/audio_back_selector" /> <!--歌曲名--> <TextView android:id="@+id/audio_tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="歌曲名" android:textColor="@color/white" android:textSize="20sp" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!--示波器--> <ImageView android:id="@+id/audio_iv_wave" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:src="@drawable/audio_wave_anim" /> <!--歌手名--> <TextView android:id="@+id/audio_tv_artist" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@id/audio_iv_wave" android:layout_centerHorizontal="true" android:text="歌手名" android:textColor="@color/white" android:textSize="16sp" /> <!--歌词--> <com.itcast.mobileplayer91.lyrics.LyricsView android:id="@+id/audio_lyricsview" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/audio_iv_wave" /> </RelativeLayout>
<?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="vertical" android:padding="6dp"> <!--播放进度--> <TextView android:id="@+id/audio_tv_position" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="right" android:text="00:00/00:00" android:textColor="@color/white" android:textSize="16sp" /> <!--时间进度条--> <SeekBar android:id="@+id/audio_sk_position" style="@android:style/Widget.SeekBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="6dp" android:layout_marginTop="6dp" android:progress="40" android:progressDrawable="@drawable/audio_seekbar_drawable" android:thumb="@mipmap/audio_seek_thumb" android:thumbOffset="0dp" /> <!--控制按钮栏--> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <!--播放顺序--> <ImageView android:id="@+id/audio_iv_playmode" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@drawable/audio_playmode_random_selector" /> <!--上一曲--> <ImageView android:id="@+id/audio_iv_pre" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@drawable/audio_pre_selector" /> <!--播放/暂停--> <ImageView android:id="@+id/audio_iv_pause" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@drawable/audio_play_selector" /> <!--下一曲--> <ImageView android:id="@+id/audio_iv_next" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@drawable/audio_next_selector" /> <!--播放列表--> <ImageView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@drawable/audio_playlist_selector" /> </LinearLayout> </LinearLayout>
相关文章推荐
- 手机影音项目笔记(四)---音乐播放歌词的控件的自定义
- 手机影音项目笔记(二)-----视频播放处理
- Cocos2d-x 3.x学习笔记:猩先生带你打飞机(五)敌我碰撞处理、分数计算、音乐播放
- 手机影音项目笔记(一)
- 手机影音第十五天,利用service实现后台播放音乐,在通知栏显示当前音乐信息等
- 手机影音第十四天,本地音乐列表的展示与播放(利用视频播放的布局)
- 后台播放音乐时播放视频,音乐暂停播放的处理方法
- 问题:Flex4的手机项目里面不支持VideoDisplay组件,视频怎样播放?
- 手机同时播放两个音乐之探讨一[JavaME]
- J2me Game开发技巧:手机游戏中声音播放及处理
- 手机游戏中声音的播放及处理
- libzplay开发【播放音乐】笔记1
- 手机同时播放两个音乐之探讨一[JavaME]
- 没头没尾--项目开发笔记:异常处理与日志记录代码自动生成(工具能生成多少代码!?续一)
- 手机游戏中声音的播放及处理
- Unparsed aapt error(s)错误的处理方法 以及 音乐播放
- 手机同时播放两个音乐 探讨二
- 一个创建手机音乐播放列表的小程序
- 手机同时播放两个音乐之探讨一[JavaME]
- 简单CMS项目笔记之二:前台页面处理流程