diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 46d25f0..18cd5f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,6 +4,10 @@
+
+
+
audioItems = new ArrayList<>();
- // 构造函数
public A_InstrumentAdapter(Context context) {
this.context = context;
}
@@ -42,18 +43,25 @@ public class A_InstrumentAdapter extends RecyclerView.Adapter newAudioItems) {
diff --git a/app/src/main/java/com/hi/music/player/adapter/A_NatureAdapter.java b/app/src/main/java/com/hi/music/player/adapter/A_NatureAdapter.java
index 96385fa..1330492 100644
--- a/app/src/main/java/com/hi/music/player/adapter/A_NatureAdapter.java
+++ b/app/src/main/java/com/hi/music/player/adapter/A_NatureAdapter.java
@@ -1,6 +1,7 @@
package com.hi.music.player.adapter;
import android.content.Context;
+import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -14,6 +15,7 @@ import com.bumptech.glide.Glide;
import com.hi.music.player.R;
import com.hi.music.player.helper.AudioItemDiffCallback;
import com.hi.music.player.javabean.A_data.AudioItem;
+import com.hi.music.player.ui.activity.A_PlayActivity;
import java.util.ArrayList;
import java.util.List;
@@ -38,10 +40,19 @@ public class A_NatureAdapter extends RecyclerView.Adapter {
// 图标数组定义为类成员,避免重复
@@ -96,7 +98,7 @@ public class A_HomeActivity extends BaseActivity {
}
private void updateTabIcon(TabLayout.Tab tab, boolean isSelected) {
- HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(tab.getCustomView());
+ HomeTabCustomBinding tabBinding = HomeTabCustomBinding.bind(Objects.requireNonNull(tab.getCustomView()));
int position = tab.getPosition();
tabBinding.homeIcon.setImageResource(isSelected ? selectedIcons[position] : defaultIcons[position]);
}
diff --git a/app/src/main/java/com/hi/music/player/ui/activity/A_PlayActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/A_PlayActivity.java
index c7ae3b4..77094ce 100644
--- a/app/src/main/java/com/hi/music/player/ui/activity/A_PlayActivity.java
+++ b/app/src/main/java/com/hi/music/player/ui/activity/A_PlayActivity.java
@@ -1,11 +1,23 @@
package com.hi.music.player.ui.activity;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.util.Log;
import android.view.View;
+import android.widget.SeekBar;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.hi.music.player.R;
import com.hi.music.player.databinding.ActivityAplayBinding;
+import com.hi.music.player.javabean.A_data.AudioItem;
+import com.hi.music.player.ui.activity.viewmodel.A_VMPlay;
public class A_PlayActivity extends BaseActivity {
+ private AudioItem audioItem;
+ private MediaPlayer mediaPlayer;
+ private A_VMPlay playViewModel;
@Override
protected ActivityAplayBinding getViewBinding() {
@@ -15,13 +27,68 @@ public class A_PlayActivity extends BaseActivity {
@Override
protected void onCreateInit() {
+ Intent intent = getIntent();
+ audioItem = (AudioItem) intent.getSerializableExtra("Path");
+ if (audioItem == null) {
+ return;
+ }
+
+ String path = audioItem.getFile();
+ Log.d("------", "--------" + path);
+
+ playViewModel = new ViewModelProvider(this).get(A_VMPlay.class);
+ mediaPlayer = new MediaPlayer();
+
+ playViewModel.initializePlayer(path);
+
+ // 观察进度更新
+ playViewModel.getProgress().observe(this, progress -> {
+ vb.songSeekbar.setProgress(progress);
+ });
+
+ // 观察播放状态
+ playViewModel.isPlaying().observe(this, isPlaying -> {
+ vb.playButton.setBackgroundResource(isPlaying ? R.drawable.play : R.drawable.pause);
+ });
+
+ // 观察当前时间
+ playViewModel.getCurrentTime().observe(this, currentTime -> {
+ vb.current.setText(currentTime);
+ });
+
+ // 观察总时间
+ playViewModel.getTotalTime().observe(this, totalTime -> {
+ vb.time.setText(totalTime);
+ });
+
}
@Override
protected void onInitClick() {
+ vb.playButton.setOnClickListener(v -> playViewModel.togglePlay());
+
+ vb.songSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ playViewModel.seekTo(progress); // 拖动进度条时控制音频
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // 暂停更新进度
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // 恢复更新进度
+ }
+ });
}
+
@Override
public boolean isFullScreen() {
return true;
@@ -34,6 +101,6 @@ public class A_PlayActivity extends BaseActivity {
@Override
public void onClick(View v) {
-
+ // 处理其他点击事件
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java b/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java
index 649fc7a..0b78b96 100644
--- a/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java
+++ b/app/src/main/java/com/hi/music/player/ui/activity/BaseActivity.java
@@ -14,6 +14,8 @@ import androidx.viewbinding.ViewBinding;
import com.hi.music.player.helper.ViewModelScope;
+import java.io.IOException;
+
public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener{
private final ViewModelScope mViewModelScope = new ViewModelScope();
diff --git a/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/A_VMPlay.java b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/A_VMPlay.java
new file mode 100644
index 0000000..bd64ae4
--- /dev/null
+++ b/app/src/main/java/com/hi/music/player/ui/activity/viewmodel/A_VMPlay.java
@@ -0,0 +1,105 @@
+package com.hi.music.player.ui.activity.viewmodel;
+
+import android.app.Application;
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaPlayer;
+import android.util.Log;
+
+import androidx.lifecycle.AndroidViewModel;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+
+import java.io.IOException;
+
+public class A_VMPlay extends AndroidViewModel {
+ private MediaPlayer mediaPlayer;
+ private final MutableLiveData currentTime = new MutableLiveData<>();
+ private final MutableLiveData totalTime = new MutableLiveData<>();
+ private final MutableLiveData isPlaying = new MutableLiveData<>(false);
+ private final MutableLiveData progress = new MutableLiveData<>(0); // 添加进度 LiveData
+
+ public A_VMPlay(Application application) {
+ super(application);
+ mediaPlayer = new MediaPlayer();
+ }
+
+ // 获取进度的 LiveData
+ public LiveData getProgress() {
+ return progress;
+ }
+
+ public LiveData getCurrentTime() {
+ return currentTime;
+ }
+
+ public LiveData getTotalTime() {
+ return totalTime;
+ }
+
+ public LiveData isPlaying() {
+ return isPlaying;
+ }
+
+ public void initializePlayer(String path) {
+ try {
+ AssetFileDescriptor afd = getApplication().getAssets().openFd(path);
+ mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ mediaPlayer.prepare();
+ mediaPlayer.setOnPreparedListener(mp -> {
+ totalTime.setValue(formatTime(mediaPlayer.getDuration()));
+ startUpdatingProgress();
+ });
+ } catch (IOException e) {
+ Log.e("MediaPlayerError", "Could not open asset file: " + path, e);
+ }
+ }
+
+ public void togglePlay() {
+ if (mediaPlayer.isPlaying()) {
+ mediaPlayer.pause();
+ isPlaying.setValue(false);
+ } else {
+ mediaPlayer.start();
+ isPlaying.setValue(true);
+ }
+ }
+
+ private void startUpdatingProgress() {
+ new Thread(() -> {
+ while (mediaPlayer != null) {
+ if (mediaPlayer.isPlaying()) {
+ int currentPosition = mediaPlayer.getCurrentPosition();
+ currentTime.postValue(formatTime(currentPosition));
+ progress.postValue((int) ((currentPosition / (float) mediaPlayer.getDuration()) * 100)); // 更新进度
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ }).start();
+ }
+
+ public void seekTo(int progress) {
+ if (mediaPlayer != null) {
+ int duration = mediaPlayer.getDuration();
+ mediaPlayer.seekTo((int) (duration * progress / 100.0));
+ }
+ }
+
+ private String formatTime(int milliseconds) {
+ int minutes = (milliseconds / 1000) / 60;
+ int seconds = (milliseconds / 1000) % 60;
+ return String.format("%02d:%02d", minutes, seconds);
+ }
+
+ @Override
+ protected void onCleared() {
+ super.onCleared();
+ if (mediaPlayer != null) {
+ mediaPlayer.release();
+ mediaPlayer = null;
+ }
+ }
+}
diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/A_ImportFragment.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/A_ImportFragment.java
index 02f6ff3..4e39bb1 100644
--- a/app/src/main/java/com/hi/music/player/ui/fragmnt/A_ImportFragment.java
+++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/A_ImportFragment.java
@@ -1,13 +1,25 @@
package com.hi.music.player.ui.fragmnt;
+import static android.app.Activity.RESULT_OK;
+
+import android.Manifest;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
import com.hi.music.player.databinding.FragmentAImportBinding;
import com.hi.music.player.ui.activity.A_SettingActivity;
-
public class A_ImportFragment extends BaseFragment {
+ private static final int REQUEST_CODE_READ_MEDIA_AUDIO = 1001;
+ private static final int REQUEST_CODE_PICK_AUDIO = 1002;
@Override
protected FragmentAImportBinding getFragmentVb() {
@@ -28,10 +40,72 @@ public class A_ImportFragment extends BaseFragment {
}
public void initEvent() {
+
Vb.setting.setOnClickListener(v -> {
Intent intent = new Intent(getContext(), A_SettingActivity.class);
startActivity(intent);
});
+
+ Vb.add.setOnClickListener(v -> {
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_MEDIA_AUDIO) != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(requireActivity(),
+ new String[]{Manifest.permission.READ_MEDIA_AUDIO},
+ REQUEST_CODE_READ_MEDIA_AUDIO);
+ } else {
+ openAudioPicker();
+ }
+ } else {
+ if (ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(requireActivity(),
+ new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+ REQUEST_CODE_READ_MEDIA_AUDIO);
+ } else {
+ openAudioPicker();
+ }
+ }
+
+
+ });
+
}
-}
\ No newline at end of file
+ // 处理权限请求结果
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (requestCode == REQUEST_CODE_READ_MEDIA_AUDIO) {
+ if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+ openAudioPicker();
+ } else {
+ Toast.makeText(requireContext(), "Permission denied", Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ // 打开音频选择器
+ private void openAudioPicker() {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("audio/*"); // 设置 MIME 类型为音频
+ intent.addCategory(Intent.CATEGORY_OPENABLE); // 限制为可打开的文件
+ startActivityForResult(intent, REQUEST_CODE_PICK_AUDIO);
+ }
+
+
+ // 处理 Activity 结果
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_CODE_PICK_AUDIO && resultCode == RESULT_OK) {
+ if (data != null) {
+ Uri audioUri = data.getData();
+ // 处理音频文件,例如播放或显示在列表中
+ Toast.makeText(requireContext(), "Audio Selected: " + audioUri.toString(), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+
+}
+
diff --git a/app/src/main/java/com/hi/music/player/ui/fragmnt/viewmodel/A_VMImport.java b/app/src/main/java/com/hi/music/player/ui/fragmnt/viewmodel/A_VMImport.java
new file mode 100644
index 0000000..cd90a5d
--- /dev/null
+++ b/app/src/main/java/com/hi/music/player/ui/fragmnt/viewmodel/A_VMImport.java
@@ -0,0 +1,9 @@
+package com.hi.music.player.ui.fragmnt.viewmodel;
+
+import androidx.lifecycle.ViewModel;
+
+public class A_VMImport extends ViewModel {
+
+
+
+}
diff --git a/app/src/main/res/drawable/round_rectangle.xml b/app/src/main/res/drawable/round_rectangle.xml
index 29c732b..eed6052 100644
--- a/app/src/main/res/drawable/round_rectangle.xml
+++ b/app/src/main/res/drawable/round_rectangle.xml
@@ -1,8 +1,5 @@
-
-
-
-
-
+
+
+
diff --git a/app/src/main/res/layout/activity_ahome.xml b/app/src/main/res/layout/activity_ahome.xml
index 96b46e5..b097461 100644
--- a/app/src/main/res/layout/activity_ahome.xml
+++ b/app/src/main/res/layout/activity_ahome.xml
@@ -5,6 +5,7 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@drawable/home_background"
tools:context=".ui.activity.A_HomeActivity">
diff --git a/app/src/main/res/layout/fragment_a_home.xml b/app/src/main/res/layout/fragment_a_home.xml
index bfaefc8..6fc32db 100644
--- a/app/src/main/res/layout/fragment_a_home.xml
+++ b/app/src/main/res/layout/fragment_a_home.xml
@@ -21,6 +21,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ready_to_sleep"
+ android:textColor="@color/white"
android:textSize="44sp"
android:textStyle="italic|bold" />
@@ -29,6 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/we_ve_carefully_prepared_sounds_for_you"
+ android:textColor="@color/white"
android:textSize="14sp" />
+ tools:listitem="@layout/item_a_home_1" />
+ android:orientation="horizontal"
+ tools:itemCount="1"
+ tools:listitem="@layout/item_a_home_2" />
+ android:orientation="horizontal"
+ tools:itemCount="1"
+ tools:listitem="@layout/item_a_home_3" />
-
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_a_home_1.xml b/app/src/main/res/layout/item_a_home_1.xml
index 3093763..83f2070 100644
--- a/app/src/main/res/layout/item_a_home_1.xml
+++ b/app/src/main/res/layout/item_a_home_1.xml
@@ -1,55 +1,64 @@
+ android:layout_height="wrap_content">
-
-
-
-
-
-
-
-
-
-
+ app:cardCornerRadius="18dp"
+ app:cardElevation="0dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
-
+ android:id="@+id/background_image"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:src="@mipmap/cover" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_a_home_2.xml b/app/src/main/res/layout/item_a_home_2.xml
index ccdea02..85abb15 100644
--- a/app/src/main/res/layout/item_a_home_2.xml
+++ b/app/src/main/res/layout/item_a_home_2.xml
@@ -4,13 +4,23 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
-
+ app:cardCornerRadius="18dp"
+ app:cardElevation="0dp"
+ app:layout_constraintBottom_toTopOf="@id/title">
+
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/card_view" />
diff --git a/app/src/main/res/layout/item_a_home_3.xml b/app/src/main/res/layout/item_a_home_3.xml
index c74a477..395777d 100644
--- a/app/src/main/res/layout/item_a_home_3.xml
+++ b/app/src/main/res/layout/item_a_home_3.xml
@@ -5,17 +5,26 @@
android:layout_height="wrap_content"
android:padding="8dp">
-
+ app:layout_constraintTop_toTopOf="parent">
+
+
+
+
+