歌單頁面 (MusicViewActivity)
1. Music類
package com.example.free.Classes;
public class Music {
private String name="";//歌曲名
private String path="";//歌曲在存儲中的路徑
private long size=0;//歌曲大小
private long time=0;//歌曲時長
public Music(String _name,String _path,long _size,long _time){
name=_name;
path=_path;
size=_size;
time=_time;
}
public String getName(){
return name;
}
public String getPath(){
return path;
}
public long getSize(){
return size;
}
public long getTime(){
return time;
}
}
2. activity_music_view.xml
RecyclerView的樣式,後面活動頁面通過訪問它的id,適配adapter來傳遞子項item的樣式和數據。比ListView更靈活,具體區別不做贅述。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MusicViewActivity">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/recyclerView">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
3. music_item.xml
RecyclerView的每一個item的具體樣式,在MusicAdapter向ViewHolder傳該樣式。
<?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"
><!--注意這裏的height是不是match_parent,不然會是一個子項佔了一整個頁面-->
<ImageView
android:id="@+id/imageLeft"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_marginTop="5dp"
android:src="@drawable/_note"
/><!--這裏是一個音符符號的圖片-->
<TextView
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/textView"
android:textColor="@color/colorBlack"
android:gravity="center_vertical"
android:textIsSelectable="false"
android:layout_margin="5dp"
android:padding="5dp"
android:textSize="18dp">
</TextView>
</LinearLayout>
4. MusicAdapter
爲RecyclerView分配每一個子項。
package com.example.free.Classes;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.free.OriginChoiceActivity;
import com.example.free.R;
import java.util.List;
//以下都是沿襲了RecyclerView.Adapter的結構,具體原理不做贅述
public class MusicAdapter extends RecyclerView.Adapter<MusicAdapter.ViewHolder> {
private List<Music> musicList;
//傳入Music音樂列表,方面後面ViewHolder更新當前頁面數據
public MusicAdapter(List<Music> _musicList) {
musicList=_musicList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//得到每一項的樣式view,不繼承parent
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.music_item,parent,false);
//只在adapter創建的時候向ViewHolder傳一次子項樣式
final ViewHolder viewHolder=new ViewHolder(view);
final Context context=parent.getContext();//得到當前上下文活動,方便後面intent傳會話
//實現每個子項的點擊效果(點擊完把音樂信息傳給下一個界面)
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int position=viewHolder.getAdapterPosition();//得到當前音樂index
Music music=musicList.get(position);//得到音樂信息
String musicPath=music.getPath();
long musicSize=music.getSize();
long musicTime=music.getTime();
Intent intent=new Intent(context, OriginChoiceActivity.class);//轉入模式選擇界面
intent.putExtra("musicPath",musicPath);//會話同時傳遞歌曲信息,下個活動選完模式後再把信息繼續傳給遊戲界面
intent.putExtra("musicSize", musicSize);
intent.putExtra("musicTime",musicTime);
context.startActivity(intent);
}
});
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
Music music=musicList.get(position);
viewHolder.textView.setText(music.getName());
}
@Override
public int getItemCount() {
return musicList.size();
}
//內部類ViewHolder,就是實現了一層封裝
class ViewHolder extends RecyclerView.ViewHolder{
//ViewHolder在adapter新建時儲存控件實例/樣式,這樣在後面就不用一直findViewById查找子樣式
TextView textView;//子項文本內容,對應onBindViewHolder裏的setText,adapter及時更新當前頁面子項信息
ViewHolder(View view){
super(view);
textView=view.findViewById(R.id.textView);
}
}
}
5. MusicViewActivity
具體歌單頁面,適配MusicAdapter,初始化musicList,將音樂信息傳給adapter。
通過調用本地數據庫MediaStore.Audio.Media.EXTERNAL_CONTENT_URI來查找所有音樂文件,不用自己寫代碼過濾全部的目錄。
package com.example.free;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import com.example.free.Classes.BaseActivity;
import com.example.free.Classes.Music;
import com.example.free.Classes.MusicAdapter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MusicViewActivity extends BaseActivity {
//該項目的所有活動(除首頁)都繼承自BaseActivity,方便調試及實現廣播,避免一個活動點擊多次出現重複頁面的情況
List<Music> musicList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_music_view);//通過啊id加載進來activity_music_view.xml的視圖
setTitle("選擇歌曲");//當前頁面bar的標題,就是頁面最上方的位置
initMusics();//調用後面初始化音樂列表的方法
RecyclerView recyclerView=findViewById(R.id.recyclerView);//找到裏面的瀑布流視圖
LinearLayoutManager layoutManager=new LinearLayoutManager(this);//線性佈局管理器,可自行設置佈局
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);//設置垂直分佈佈局
recyclerView.setLayoutManager(layoutManager);//將佈局管理器配給該瀑布流
MusicAdapter musicAdapter=new MusicAdapter(musicList);//新建adapter,將音樂列表參數傳進去
recyclerView.setAdapter(musicAdapter);//瀑布流運用該適配器
}
//初始化音樂列表方法
public void initMusics() {
Cursor cursor = null;//初始化遊標,(同訪問數據庫的query用法)
try {
//這裏是利用了自帶的數據庫,不用從sd卡里過濾目錄
cursor = getApplicationContext().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_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 path=cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
//得到音樂文件大小
long size=cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
//得到音樂時長
long time=cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DURATION));
if(name!=null)//這裏一定要先判斷是否爲空,否則後面的.contains方法會報錯
if(name.contains(".wav")||name.contains(".mp3"))
musicList.add(new Music(name,path,size,time));
//本項目只實現了wav和mp3格式音樂文件的自動識別節奏
}
}
Collections.reverse(musicList);//倒置按時間順序排序,使最新下載的音樂在最上方
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();//這裏記得finally關閉遊標
}
}
}