diff --git a/app/src/module_music/java/com/chwl/app/music/activity/AddLocalMusicListActivity.java b/app/src/module_music/java/com/chwl/app/music/activity/AddLocalMusicListActivity.java new file mode 100644 index 0000000..8c26bde --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/activity/AddLocalMusicListActivity.java @@ -0,0 +1,311 @@ +package com.chwl.app.music.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.LinearInterpolator; +import android.view.animation.RotateAnimation; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.appcompat.widget.AppCompatCheckBox; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpActivity; +import com.chwl.app.music.adapter.AddLocalMusicListAdapter; +import com.chwl.app.music.presenter.AddLocalMusicListPresenter; +import com.chwl.core.auth.event.KickOutEvent; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.view.IAddLocalMusicListView; +import com.chwl.core.room.IRoomCoreClient; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.coremanager.CoreEvent; +import com.chwl.library.utils.ListUtils; +import com.chwl.library.utils.ResUtil; +import com.netease.nim.uikit.StatusBarUtil; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomKickOutEvent; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +@CreatePresenter(AddLocalMusicListPresenter.class) +public class AddLocalMusicListActivity extends BaseMvpActivity + implements IAddLocalMusicListView, View.OnClickListener { + + private RecyclerView recyclerView; + private ImageView backBtn; + private ImageView ivOptionRight; + private TextView shareOption; + private View emptyBg; + private View animationView; + private ImageView pic; + private Button actionBtn; + private AppCompatCheckBox selectAllBtn; + private View musicBoxLayout; + + private AddLocalMusicListAdapter adapter; + + private boolean isFirstLoad = true; + private boolean isSpecial = false; + + + public static void start(Context context) { + Intent intent = new Intent(context, AddLocalMusicListActivity.class); + context.startActivity(intent); + } + + public static void startForResult(Object contextOrFragment, int requestCode) { + if (contextOrFragment instanceof Activity) { + Activity activity = (Activity) contextOrFragment; + Intent intent = new Intent(activity, AddLocalMusicListActivity.class); + activity.startActivityForResult(intent, requestCode); + } else if (contextOrFragment instanceof Fragment) { + Fragment fragment = (Fragment) contextOrFragment; + + Intent intent = new Intent(fragment.getContext(), AddLocalMusicListActivity.class); + if (!(fragment.getContext() instanceof Activity)) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + fragment.startActivityForResult(intent, requestCode); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + isSpecial = (28 < Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 33); + + setContentView(R.layout.activity_add_music_list); + findView(); + initView(); + + initData(); + + StatusBarUtil.StatusBarLightMode(this); + + + EventBus.getDefault().register(this); + } + + private void findView() { + recyclerView = findViewById(R.id.recycler_view); + backBtn = findViewById(R.id.back_btn); + ivOptionRight = findViewById(R.id.iv_option_right); + shareOption = findViewById(R.id.tv_share_music_option); + emptyBg = findViewById(R.id.empty_bg); + animationView = findViewById(R.id.animation_view); + pic = findViewById(R.id.iv_animation); + actionBtn = findViewById(R.id.btn_action); + selectAllBtn = findViewById(R.id.cb_select_all); + musicBoxLayout = findViewById(R.id.music_box_layout); + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + protected void onResume() { + super.onResume(); + if (isFirstLoad) { + isFirstLoad = false; + scanningMusicInLocal(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected void onPause() { + super.onPause(); + getMvpPresenter().stopScanLocalMusic(); + } + + private void initView() { + backBtn.setOnClickListener(this); + ivOptionRight.setImageResource(R.drawable.icon_music_refresh); + ivOptionRight.setOnClickListener(this); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + shareOption.setOnClickListener(this); + actionBtn.setOnClickListener(this); + selectAllBtn.setOnClickListener(v -> adapter.selectAll(selectAllBtn.isChecked())); + } + + private void initData() { + List localMusicInfoList = new ArrayList<>(); + adapter = new AddLocalMusicListAdapter(this); + adapter.setLocalMusicInfo(localMusicInfoList); + recyclerView.setAdapter(adapter); + adapter.setOnCallBack(new AddLocalMusicListAdapter.OnCallBack() { + @Override + public void onSelected(Boolean isSelectedAll) { + actionBtn.setEnabled(isSelectedAll != null); + if (isSelectedAll == null) { + isSelectedAll = false; + } + selectAllBtn.setChecked(isSelectedAll); + } + }); + } + + private void setUI(boolean isEmpty) { + recyclerView.setVisibility(isEmpty ? View.GONE : View.VISIBLE); + animationView.setVisibility(getMvpPresenter().isScanning() ? View.VISIBLE : View.GONE); + if (getMvpPresenter().isScanning()) { + emptyBg.setVisibility(View.GONE); + musicBoxLayout.setVisibility(View.GONE); + } else { + emptyBg.setVisibility(isEmpty ? View.VISIBLE : View.GONE); + musicBoxLayout.setVisibility(isEmpty ? View.GONE : View.VISIBLE); + } + } + + private void playFlagRotateAnim() { + Animation operatingAnim = AnimationUtils.loadAnimation(this, R.anim.rotate_fast_anim); + LinearInterpolator lin = new LinearInterpolator(); + operatingAnim.setInterpolator(lin); + ivOptionRight.startAnimation(operatingAnim); + RotateAnimation rotateAnimation = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f); + rotateAnimation.setDuration(1000); + rotateAnimation.setFillAfter(true); + rotateAnimation.setRepeatMode(Animation.RESTART); + //让旋转动画一直转,不停顿的重点 + rotateAnimation.setInterpolator(new LinearInterpolator()); + rotateAnimation.setRepeatCount(-1); + pic.startAnimation(rotateAnimation); + } + + private void stopFlagRotateAnim() { + ivOptionRight.clearAnimation(); + pic.clearAnimation(); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.tv_share_music_option: + setResult(Activity.RESULT_FIRST_USER); + finish(); + break; + + case R.id.iv_option_right: + scanningMusicInLocal(); + break; + + case R.id.back_btn: + finish(); + break; + + case R.id.btn_action: + getDialogManager().showProgressDialog(this); + getMvpPresenter().batchAddToPlayerList(adapter.getNeedAddList()); + break; + + default: + } + } + + private void scanningMusicInLocal() { + + if (!getMvpPresenter().isScanning()) { + playFlagRotateAnim(); + toast(ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_01)); + selectAllBtn.setChecked(false); + adapter.getNeedAddList().clear(); + actionBtn.setEnabled(false); + getMvpPresenter().scanningLocalMusicBeans(); + } else { + toast(ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_03)); + } + } + + + @CoreEvent(coreClientClass = IRoomCoreClient.class) + public void onBeKickOut(ChatRoomKickOutEvent.ChatRoomKickOutReason reason) { + finish(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onKickedOutEvent(KickOutEvent event) { + finish(); + } + + @Override + public void startAnimation() { + playFlagRotateAnim(); + toast(ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_04)); + } + + @Override + public void toastMessage(String msg) { + toast(msg); + } + + @Override + public void onScanningLocalMusicSuccess(List localMusicBeans) { + + toast(ListUtils.isListEmpty(localMusicBeans) ? ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_05) : ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_06)); + + boolean isEmpty = localMusicBeans == null || localMusicBeans.size() == 0; + setUI(isEmpty); + adapter.setLocalMusicInfo(isEmpty ? null : localMusicBeans); + adapter.notifyDataSetChanged(); + } + + @Override + public void onScanningLocalMusicFail(Throwable throwable) { + setUI(true); + } + + @Override + public void onScanningComplete() { + stopFlagRotateAnim(); + } + + @Override + public void addAllSuccess(List ids) { + cancelLoading(); + setResult(Activity.RESULT_OK); + finish(); + } + + @Override + public void addAllFail(Throwable throwable) { + cancelLoading(); + toast(ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_07)); + finish(); + } + + private void cancelLoading() { + if (getDialogManager().isDialogShowing()) { + getDialogManager().dismissDialog(); + } + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/activity/AddLocalMusicListSpecialActivity.java b/app/src/module_music/java/com/chwl/app/music/activity/AddLocalMusicListSpecialActivity.java new file mode 100644 index 0000000..d15d959 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/activity/AddLocalMusicListSpecialActivity.java @@ -0,0 +1,199 @@ +package com.chwl.app.music.activity; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.media.MediaMetadataRetriever; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpActivity; +import com.chwl.app.music.presenter.AddLocalMusicListPresenter; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.view.IAddLocalMusicListView; +import com.chwl.core.utils.myutil.MyUriUtils; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.utils.ResUtil; +import com.hjq.toast.ToastUtils; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +@CreatePresenter(AddLocalMusicListPresenter.class) +public class AddLocalMusicListSpecialActivity extends BaseMvpActivity + implements IAddLocalMusicListView { + + + ActivityResultLauncher mMusicPick; + + public static void start(Context context) { + Intent intent = new Intent(context, AddLocalMusicListSpecialActivity.class); + context.startActivity(intent); + } + + public static void startForResult(Object contextOrFragment, int requestCode) { + if (contextOrFragment instanceof Activity) { + Activity activity = (Activity) contextOrFragment; + Intent intent = new Intent(activity, AddLocalMusicListSpecialActivity.class); + activity.startActivityForResult(intent, requestCode); + } else if (contextOrFragment instanceof Fragment) { + Fragment fragment = (Fragment) contextOrFragment; + + Intent intent = new Intent(fragment.getContext(), AddLocalMusicListSpecialActivity.class); + if (!(fragment.getContext() instanceof Activity)) { + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + fragment.startActivityForResult(intent, requestCode); + } + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View view = new View(context); + view.setBackgroundResource(R.color.white); + setContentView(view); + + mMusicPick = registerForActivityResult(new ActivityResultContracts.OpenDocument(), uri -> { + try { + if (uri != null) { + if (MyUriUtils.INSTANCE.needCopy(context,uri)){ + File file = MyUriUtils.INSTANCE.copyMp3File(this, uri); + if (file != null) { + LocalMusicBean localMusicBean = getLocalMusicBean(file); + ArrayList beans = new ArrayList<>(); + beans.add(localMusicBean); + getMvpPresenter().batchAddToPlayerListSpecial(beans); + } else { + ToastUtils.show(R.string.exception_try_again); + finish(); + } + }else { + addAllFail(new Throwable()); + } + } else { + finish(); + } + }catch (Exception e){ + addAllFail(e); + } + }); + mMusicPick.launch(new String[]{"audio/mpeg"}); + } + + @Override + public void startAnimation() { + + } + + @Override + public void toastMessage(String msg) { + toast(msg); + } + + @Override + public void onScanningComplete() { + + } + + @Override + public void onScanningLocalMusicSuccess(List localMusicBeans) { + + } + + @Override + public void onScanningLocalMusicFail(Throwable throwable) { + + } + + @Override + public void addAllSuccess(List ids) { + setResult(Activity.RESULT_OK); + finish(); + } + + @Override + public void addAllFail(Throwable throwable) { + toast(ResUtil.getString(R.string.music_activity_addlocalmusiclistactivity_07)); + finish(); + } + + @Override + public void onPointerCaptureChanged(boolean hasCapture) { + super.onPointerCaptureChanged(hasCapture); + } + + + private LocalMusicBean getLocalMusicBean(File file) { + MediaMetadataRetriever retriever; + try { + LocalMusicBean song = new LocalMusicBean(); + retriever = new MediaMetadataRetriever(); + retriever.setDataSource(file.getAbsolutePath()); + + + String name = file.getName(); + if (name == null || TextUtils.isEmpty(name)) { + name = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE); + } + song.setSongName(name); + song.setYear(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR)); + song.setAlbumName(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM)); + //与服务端统一精度 精确到毫秒 + song.setDuration(Long.parseLong(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION))); + String artist = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); + if (artist == null) { + artist = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_AUTHOR); + } + song.setArtistName(artist); + String data = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE); + if (data == null || TextUtils.isEmpty(data)) { + data = file.getPath(); + } + song.setLocalUri(data); + +// song.setLocalId(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR)); +// song.setSongId(SongUtils.generateThirdPartyId()); +// +// int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));// 歌曲的id +// Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id); +// song.setUri(uri.toString()); + + return song; + }catch (Exception e){ + addAllFail(e); + } + return null; + } + + + + /** + * 检查 + * + * @param duration + * @return + */ + public static final long DURATION_MIN = 1000; + private boolean checkDuration(long duration) { + return duration > DURATION_MIN; + } + + /** + * 判断是否是音乐 + * + * @param isMusic + * @return + */ + private boolean checkMusic(int isMusic) { + return isMusic == 1; + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/activity/MusicListActivity.java b/app/src/module_music/java/com/chwl/app/music/activity/MusicListActivity.java new file mode 100644 index 0000000..fb9a6b9 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/activity/MusicListActivity.java @@ -0,0 +1,223 @@ +package com.chwl.app.music.activity; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; + +import androidx.fragment.app.Fragment; +import androidx.viewpager.widget.ViewPager; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpActivity; +import com.chwl.app.music.fragment.LocalMusicListFragment; +import com.chwl.app.music.fragment.ShareMusicListFragment; +import com.chwl.app.music.presenter.MusicListPresenter; +import com.chwl.core.auth.event.KickOutEvent; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.event.JumpToShareMusicListFragmentEvent; +import com.chwl.core.music.view.IMusicListView; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.utils.ResUtil; +import com.flyco.tablayout.SlidingTabLayout; +import com.netease.nim.uikit.StatusBarUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.ArrayList; +import java.util.List; + +@CreatePresenter(MusicListPresenter.class) +public class MusicListActivity extends BaseMvpActivity + implements IMusicListView, View.OnClickListener { + + public static final String KEY_PAGE = "key_page"; + public static final int POS_LOCAL_MUSIC_LIST = 0; + public static final int POS_SHARE_MUSIC_LIST = 1; + + private SlidingTabLayout slidingTabLayout; + private ViewPager viewPager; + private ImageView addMusicIcon; + private ImageView backIcon; + + private final String[] titles = {ResUtil.getString(R.string.music_activity_musiclistactivity_01)}; + private int page = 0; + private List fragments = new ArrayList<>(); + private PagerDataAdapter adapter = new PagerDataAdapter(getSupportFragmentManager()); + + private boolean isSpecial = false; + + public static void openLocalMusicList(Context context) { + Intent intent = new Intent(context, MusicListActivity.class); + intent.putExtra(KEY_PAGE, POS_LOCAL_MUSIC_LIST); + context.startActivity(intent); + } + + public static void openShareMusicList(Context context) { + Intent intent = new Intent(context, MusicListActivity.class); + intent.putExtra(KEY_PAGE, POS_SHARE_MUSIC_LIST); + context.startActivity(intent); + } + + public static void start(Context context, int page) { + Intent intent = new Intent(context, MusicListActivity.class); + intent.putExtra(KEY_PAGE, page); + context.startActivity(intent); + } + + @SuppressLint("CheckResult") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + isSpecial = (28 < Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 33); + + setContentView(R.layout.activity_music_list); + findView(); + fragments.add(LocalMusicListFragment.newInstance()); + adapter.setData(fragments); + viewPager.setAdapter(adapter); + slidingTabLayout.setViewPager(viewPager, titles); + backIcon.setOnClickListener(this); + addMusicIcon.setOnClickListener(this); + EventBus.getDefault().register(this); + page = getIntent().getIntExtra(KEY_PAGE, page); + viewPager.setCurrentItem(page); + + if (isSpecial){ + + }else { + checkPermission(Build.VERSION.SDK_INT >= 33 ? Manifest.permission.READ_MEDIA_AUDIO : Manifest.permission.READ_EXTERNAL_STORAGE) + .compose(bindToLifecycle()) + .subscribe(aBoolean -> { + if (!aBoolean) { + toast(ResUtil.getString(R.string.music_activity_musiclistactivity_03)); + } + }); + } + + } + + private void findView() { + slidingTabLayout = findViewById(R.id.stl_music_list); + viewPager = findViewById(R.id.vp_music_list); + addMusicIcon = findViewById(R.id.iv_more); + backIcon = findViewById(R.id.iv_back); + + + } + + @Override + protected void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + protected boolean needSteepStateBar() { + return true; + } + + @Override + protected void setStatusBar() { + super.setStatusBar(); + StatusBarUtil.transparencyBar(this); + StatusBarUtil.StatusBarLightMode(this); + StatusBarUtil.StatusBarLightMode(this); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.iv_back: + finish(); + break; + + case R.id.iv_more: + if (isSpecial) { + if (fragments != null && !fragments.isEmpty()) { + AddLocalMusicListSpecialActivity.startForResult(fragments.get(0), LocalMusicListFragment.REQUEST_CODE); + } + }else { + if (fragments != null && !fragments.isEmpty()) { + AddLocalMusicListActivity.startForResult(fragments.get(0), LocalMusicListFragment.REQUEST_CODE); + } + } + break; + default: + break; + } + } + + public void onJumpToShareListFragment(JumpToShareMusicListFragmentEvent event) { + viewPager.setCurrentItem(POS_SHARE_MUSIC_LIST); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onKickedOutEvent(KickOutEvent event) { + finish(); + } + + + /** + * 共享中状态移除 + * + * @param localMusicBean + */ + public void delete(LocalMusicBean localMusicBean) { + if (fragments == null) { + return; + } + if (fragments.size() < 2) { + return; + } + Fragment fragment = fragments.get(1); + if (fragment instanceof ShareMusicListFragment) { + ShareMusicListFragment smf = (ShareMusicListFragment) fragment; + smf.delete(localMusicBean); + + } + } + + /** + * 添加到本地列表 + * + * @param localMusicBean + */ + public void add(LocalMusicBean localMusicBean) { + if (fragments == null) { + return; + } + if (fragments.size() < 2) { + return; + } + Fragment fragment = fragments.get(0); + if (fragment instanceof LocalMusicListFragment) { + LocalMusicListFragment smf = (LocalMusicListFragment) fragment; + smf.add(localMusicBean); + } + } + + /** + * 切换fragment显示 + * + * @param page + */ + public void changePage(int page) { + if (viewPager.getCurrentItem() == page) { + return; + } + viewPager.setCurrentItem(page); + } + + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/activity/PagerDataAdapter.java b/app/src/module_music/java/com/chwl/app/music/activity/PagerDataAdapter.java new file mode 100644 index 0000000..9127fee --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/activity/PagerDataAdapter.java @@ -0,0 +1,31 @@ +package com.chwl.app.music.activity; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; + +import java.util.ArrayList; +import java.util.List; + +public class PagerDataAdapter extends FragmentStatePagerAdapter { + + private List data = new ArrayList<>(); + + public PagerDataAdapter(FragmentManager fm) { + super(fm); + } + + @Override + public Fragment getItem(int position) { + return data.get(position); + } + + @Override + public int getCount() { + return data.size(); + } + + public void setData(List data) { + this.data = data; + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/adapter/AddLocalMusicListAdapter.java b/app/src/module_music/java/com/chwl/app/music/adapter/AddLocalMusicListAdapter.java new file mode 100644 index 0000000..45aaaaf --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/adapter/AddLocalMusicListAdapter.java @@ -0,0 +1,180 @@ +package com.chwl.app.music.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.R; +import com.chwl.core.music.db.bean.LocalMusicBean; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by chenran on 2017/11/1. + */ + +public class AddLocalMusicListAdapter extends RecyclerView.Adapter + implements View.OnClickListener { + private Context context; + private List mLocalMusicInfo; + private List needAddList = new ArrayList<>(); + private OnCallBack onCallBack; + + public AddLocalMusicListAdapter(Context context) { + this.context = context; + } + + public void setLocalMusicInfo(List localMusicInfo) { + this.mLocalMusicInfo = localMusicInfo; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View root = LayoutInflater.from(context).inflate(R.layout.list_item_add_music, parent, false); + return new ViewHolder(root); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + LocalMusicBean localMusicInfo = mLocalMusicInfo.get(position); + if (localMusicInfo == null) { + return; + } + holder.musicName.setText(localMusicInfo.getSongName()); + holder.artistName.setText(localMusicInfo.getArtistName()); + + holder.addBtn.setSelected(localMusicInfo.isSelected()); + + holder.addBtn.setTag(position); + holder.addBtn.setOnClickListener(this); + holder.container.setTag(position); + holder.container.setOnClickListener(this); + } + + @Override + public int getItemCount() { + return mLocalMusicInfo == null ? 0 : mLocalMusicInfo.size(); + } + + @Override + public void onClick(View v) { + int position = (int) v.getTag(); + LocalMusicBean localMusicInfo = mLocalMusicInfo.get(position); + localMusicInfo.setSelected(!localMusicInfo.isSelected()); + // 刷新 UI + notifyItemChanged(position); + // 缓存选中的 item + if (localMusicInfo.isSelected()) { + needAddList.add(localMusicInfo); + } else { + needAddList.remove(localMusicInfo); + } + checkSelected(); + } + + /** + * 检查选择状态, + * 全选 3 + * 选中 2 + * 全不选 1 + */ + private void checkSelected() { + if (needAddList == null) { + return; + } + int selectedNum = 0; + for (LocalMusicBean localMusicBean : needAddList) { + if (localMusicBean == null) { + continue; + } + //记录选中的个数 + if (localMusicBean.isSelected()) { + selectedNum++; + } + } + if (selectedNum == 0) { + callback(null); + } else if (selectedNum == mLocalMusicInfo.size()) { + callback(true); + } else { + callback(false); + } + } + + /** + * 回调外部选择状态 + * + * @param isSelectedAll + */ + private void callback(Boolean isSelectedAll) { + if (onCallBack != null) { + onCallBack.onSelected(isSelectedAll); + } + } + + /** + * 外部全选时使用 + * + * @param select + */ + public void selectAll(boolean select) { + // 刷新 UI + for (LocalMusicBean localMusicInfo : mLocalMusicInfo) { + localMusicInfo.setSelected(select); + } + notifyDataSetChanged(); + // 缓存数据 + needAddList.clear(); + if (select) { + needAddList.addAll(mLocalMusicInfo); + } + callback(select ? true : null); + } + + /** + * 外部添加时,返回已选中的 item + * + * @return + */ + public List getNeedAddList() { + return needAddList; + } + + public void setOnCallBack(OnCallBack onCallBack) { + this.onCallBack = onCallBack; + } + + static class ViewHolder extends RecyclerView.ViewHolder { + ImageView addBtn; + TextView musicName; + TextView artistName; + View container; + + public ViewHolder(View itemView) { + super(itemView); + addBtn = itemView.findViewById(R.id.add_btn); + musicName = itemView.findViewById(R.id.music_name); + artistName = itemView.findViewById(R.id.artist_name); + container = itemView.findViewById(R.id.container); + } + + } + + + public interface OnCallBack { + /** + * true 是全选 + * false 是有选中的状态 + * null 是全不选 + * + * @param isSelectedAll + */ + void onSelected(Boolean isSelectedAll); + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/adapter/LocalMusicListAdapter.java b/app/src/module_music/java/com/chwl/app/music/adapter/LocalMusicListAdapter.java new file mode 100644 index 0000000..6d8f852 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/adapter/LocalMusicListAdapter.java @@ -0,0 +1,99 @@ +package com.chwl.app.music.adapter; + +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chwl.app.R; +import com.chwl.core.music.db.bean.LocalMusicBean; + +/** + * Created by chenran on 2017/11/1. + */ + +public class LocalMusicListAdapter extends BaseQuickAdapter { + + + private LocalMusicBean current; + + public LocalMusicListAdapter() { + super(R.layout.list_item_local_music); + } + + private OnCallback onCallback; + + public void setOnCallback(OnCallback onCallback) { + this.onCallback = onCallback; + } + + @Override + protected void convert(ViewHolder holder, LocalMusicBean item) { + if (item == null) { + return; + } + int position = holder.getLayoutPosition(); + holder.musicName.setText(item.getSongName()); + holder.artistName.setText(item.getArtistName()); + if(item.equals(current)){ + holder.musicName.setTextColor(ContextCompat.getColor(mContext,R.color.appColor)); + holder.artistName.setTextColor(ContextCompat.getColor(mContext,R.color.appColor)); + }else{ + holder.musicName.setTextColor(ContextCompat.getColor(mContext,R.color.color_333333)); + holder.artistName.setTextColor(ContextCompat.getColor(mContext,R.color.color_999999)); + } + + + holder.deleteBtn.setTag(item); + + holder.deleteBtn.setOnClickListener(v -> { + if (onCallback != null) { + onCallback.onDelete(item,position); + } +// PlayerModel.get().deleteMusicFromPlayerList(item); + }); + holder.container.setOnClickListener(v -> { + if (onCallback != null) { + onCallback.onPlay(item,position); + } +// PlayerModel.get().play(item); + }); + + + } + + public void setCurrent(LocalMusicBean current) { + this.current = current; + } + + public LocalMusicBean getCurrent() { + return current; + } + + + public class ViewHolder extends BaseViewHolder { + ImageView deleteBtn; + TextView musicName; + TextView artistName; + RelativeLayout container; + + public ViewHolder(View itemView) { + super(itemView); + container = itemView.findViewById(R.id.container); + deleteBtn = itemView.findViewById(R.id.delete_btn); + musicName = itemView.findViewById(R.id.music_name); + artistName = itemView.findViewById(R.id.artist_name); + } + + } + + public interface OnCallback { + void onDelete(LocalMusicBean localMusicBean, int position); + + void onPlay(LocalMusicBean localMusicBean, int position); + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/adapter/ShareMusicListAdapter.java b/app/src/module_music/java/com/chwl/app/music/adapter/ShareMusicListAdapter.java new file mode 100644 index 0000000..45cf560 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/adapter/ShareMusicListAdapter.java @@ -0,0 +1,44 @@ +package com.chwl.app.music.adapter; + +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.chad.library.adapter.base.BaseQuickAdapter; +import com.chad.library.adapter.base.BaseViewHolder; +import com.chwl.app.R; +import com.chwl.core.music.bean.ShareMusicInfo; +import com.chwl.library.utils.ResUtil; + +public class ShareMusicListAdapter extends BaseQuickAdapter { + + public ShareMusicListAdapter() { + super(R.layout.list_item_share_music); + } + + @Override + protected void convert(ViewHolder helper, ShareMusicInfo item) { + helper.musicName.setText(String.format("%s - %s", item.getSongName(), item.getAuthor())); + helper.artistName.setText(String.format(ResUtil.getString(R.string.music_adapter_sharemusiclistadapter_01), item.getNick())); + helper.addBtn.setEnabled(!item.isInLocalList()); + helper.addOnClickListener(helper.addBtn.getId()); +// helper.addOnClickListener(helper.container.getId()); + } + + public class ViewHolder extends BaseViewHolder { + ImageView addBtn; + TextView musicName; + TextView artistName; + RelativeLayout container; + + public ViewHolder(View view) { + super(view); + musicName = itemView.findViewById(R.id.music_name); + artistName = itemView.findViewById(R.id.artist_name); + addBtn = itemView.findViewById(R.id.add_btn); + container = itemView.findViewById(R.id.container); + } + } + +} diff --git a/app/src/module_music/java/com/chwl/app/music/fragment/LocalMusicListFragment.java b/app/src/module_music/java/com/chwl/app/music/fragment/LocalMusicListFragment.java new file mode 100644 index 0000000..80215e1 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/fragment/LocalMusicListFragment.java @@ -0,0 +1,412 @@ +package com.chwl.app.music.fragment; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.SeekBar; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpFragment; +import com.chwl.app.music.activity.AddLocalMusicListActivity; +import com.chwl.app.music.activity.MusicListActivity; +import com.chwl.app.music.adapter.LocalMusicListAdapter; +import com.chwl.app.music.presenter.LocalMusicListPresenter; +import com.chwl.app.music.widget.VoiceSeekDialog; +import com.chwl.core.Constants; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.event.CurrentMusicUpdateEvent; +import com.chwl.core.music.event.MusicPauseEvent; +import com.chwl.core.music.event.MusicPlayingEvent; +import com.chwl.core.music.event.MusicStopEvent; +import com.chwl.core.music.model.IPlayerModel; +import com.chwl.core.music.model.PlayerModel; +import com.chwl.core.music.view.ILocalMusicListView; +import com.chwl.core.utils.LogUtils; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.utils.ListUtils; +import com.chwl.library.utils.ResUtil; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.io.File; +import java.util.List; +import java.util.Locale; + +; +; + +@CreatePresenter(LocalMusicListPresenter.class) +public class LocalMusicListFragment extends BaseMvpFragment + implements ILocalMusicListView, SeekBar.OnSeekBarChangeListener, View.OnClickListener { + + public static final int REQUEST_CODE = 0x100; + + private ImageView musicPlayPauseBtn; + private TextView songName; + private View musicPlayPauseLayout; + private View musicAdjustVoiceLayout; + private TextView addLocalMusicView; + private TextView addShareMusicView; + private RecyclerView recyclerView; + private View emptyView; + private SmartRefreshLayout refreshLayout; + private View contentView; + private TextView tvSongNum; + + private LocalMusicListAdapter adapter; + private LocalMusicBean current; + + + private boolean isSpecial = false; + + /** + * 歌曲数量 + */ + private int musicCount = -1; + + public static LocalMusicListFragment newInstance() { + return new LocalMusicListFragment(); + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + isSpecial = (28 < Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 33); + EventBus.getDefault().register(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + EventBus.getDefault().unregister(this); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_music_list; + } + + @Override + public void onFindViews() { + musicPlayPauseBtn = mView.findViewById(R.id.music_play_pause_btn); + songName = mView.findViewById(R.id.song_name); + musicPlayPauseLayout = mView.findViewById(R.id.music_play_pause_layout); + musicAdjustVoiceLayout = mView.findViewById(R.id.music_adjust_voice_layout); + addLocalMusicView = mView.findViewById(R.id.tv_empty_option); + addShareMusicView = mView.findViewById(R.id.tv_share_music_option); + recyclerView = mView.findViewById(R.id.recycler_view); + emptyView = mView.findViewById(R.id.in_empty_bg); + refreshLayout = mView.findViewById(R.id.smart_refresh_layout); + contentView = mView.findViewById(R.id.ll_content); + tvSongNum = mView.findViewById(R.id.tv_song_num); + if (isSpecial) addLocalMusicView.setVisibility(View.INVISIBLE); + } + + @Override + public void onSetListener() { + musicPlayPauseLayout.setOnClickListener(this); + musicAdjustVoiceLayout.setOnClickListener(this); + addLocalMusicView.setOnClickListener(this); + addShareMusicView.setOnClickListener(this); + refreshLayout.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() { + @Override + public void onLoadMore(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(getContext())) { + refreshLayout.finishLoadMore(); + return; + } + List data = adapter.getData(); + if (ListUtils.isListEmpty(data)) { + refreshLayout.finishLoadMore(); + return; + } + getMvpPresenter().loadMoreData(); + } + + @Override + public void onRefresh(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(getContext())) { + refreshLayout.finishRefresh(); + return; + } + getMvpPresenter().loadFirstPage(); + } + }); + } + + @Override + public void initiate() { + adapter = new LocalMusicListAdapter(); + recyclerView.setAdapter(adapter); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + adapter.notifyDataSetChanged(); + adapter.setOnCallback(new LocalMusicListAdapter.OnCallback() { + @Override + public void onDelete(LocalMusicBean localMusicBean, int position) { + getMvpPresenter().delete(localMusicBean, position); + getDialogManager().showProgressDialog(getContext()); + } + + @Override + public void onPlay(LocalMusicBean localMusicBean, int position) { + if (current == localMusicBean) { + return; + } + getMvpPresenter().play(localMusicBean, position); + } + }); + current = PlayerModel.get().getCurrent(); + adapter.setCurrent(current); + updateView(); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.music_play_pause_layout: + int state = PlayerModel.get().getState(); + if (state == IPlayerModel.STATE_PLAY) { + PlayerModel.get().pause(); + } else if (state == IPlayerModel.STATE_PAUSE) { + int result = PlayerModel.get().play(null); + isPlaySuccess(result); + + } else { + int result = PlayerModel.get().playNext(); + isPlaySuccess(result); + } + break; + + case R.id.music_adjust_voice_layout: + VoiceSeekDialog voiceSeekDialog = new VoiceSeekDialog(getContext()); + voiceSeekDialog.show(); + break; + + case R.id.tv_empty_option: + AddLocalMusicListActivity.startForResult(this, REQUEST_CODE); + break; + + case R.id.tv_share_music_option: + if (getActivity() instanceof MusicListActivity) { + MusicListActivity activity = (MusicListActivity) getActivity(); + activity.changePage(1); + } + break; + + default: + } + } + + private void setUI(boolean isEmpty) { + contentView.setVisibility(isEmpty ? View.GONE : View.VISIBLE); + emptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); + } + + private void isPlaySuccess(int result) { + if (result < 0) { + toast(result == -3 ? ResUtil.getString(R.string.music_fragment_localmusiclistfragment_01) : ResUtil.getString(R.string.music_fragment_localmusiclistfragment_02)); + } + } + + private void updateView() { + if (current != null) { + songName.setText(current.getSongName()); + + int state = PlayerModel.get().getState(); + musicPlayPauseBtn.setImageResource(state == IPlayerModel.STATE_PLAY ? + R.drawable.icon_music_play_big : R.drawable.icon_music_pause_big); + + } else { + songName.setText(ResUtil.getString(R.string.music_fragment_localmusiclistfragment_03)); + musicPlayPauseBtn.setImageResource(R.drawable.icon_music_pause_big); + } + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean b) { + PlayerModel.get().seekVolume(progress); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMusicPlaying(MusicPlayingEvent event) { + this.current = PlayerModel.get().getCurrent(); + isPlaySuccess(0); + updateView(); + adapter.setCurrent(current); + adapter.notifyDataSetChanged(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMusicPause(MusicPauseEvent event) { + this.current = PlayerModel.get().getCurrent(); + updateView(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMusicStop(MusicStopEvent event) { + this.current = null; + updateView(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCurrentMusicUpdate(CurrentMusicUpdateEvent event) { + this.current = PlayerModel.get().getCurrent(); + } + + @Override + public void onGetListSuccess(List data, int page) { + if (!ListUtils.isListEmpty(data)) { + hideStatus(); + if (page == Constants.PAGE_START) { + setUI(false); + adapter.setNewData(data); + refreshLayout.finishRefresh(); + } else { + adapter.addData(data); + refreshLayout.finishLoadMore(); + } + } else { + if (page == Constants.PAGE_START) { + refreshLayout.finishRefresh(); + setUI(true); + } else { + refreshLayout.finishLoadMore(); + } + } + updatePlayerList(); + } + + @Override + public void onGetListFail(String message) { + if (getDialogManager().isDialogShowing()) { + getDialogManager().dismissDialog(); + } + toast(message); + } + + @Override + public void onResume() { + super.onResume(); + // 加载页面数据 + getMvpPresenter().loadFirstPage(); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) { + getMvpPresenter().loadFirstPage(); + } else if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_FIRST_USER) { + if (getActivity() instanceof MusicListActivity) { + MusicListActivity activity = (MusicListActivity) getActivity(); + activity.changePage(1); + } + } + } + + @Override + public void onDeleteSuccess(LocalMusicBean localMusicBean, int position) { + LocalMusicBean lmb = adapter.getData().get(position); + if (lmb.getId() == localMusicBean.getId()) { + //测试不要动画 +// adapter.remove(position); + adapter.getData().remove(position); + adapter.notifyDataSetChanged(); + //更新歌曲数量 + musicCount--; + updateMusicCount(); + updatePlayerList(); + MusicListActivity musicListActivity = (MusicListActivity) getActivity(); + if (musicListActivity == null) { + return; + } + + if (isSpecial) { + File file = new File(localMusicBean.getLocalUri()); + if (file.exists()) { + boolean delete = file.delete(); + if (delete) { + LogUtils.d(" isSpecial 删除文件 ,文件删除成功"); + } else { + LogUtils.d(" isSpecial 删除文件 ,文件删除失败"); + } + } else { + LogUtils.d(" isSpecial 删除文件 ,文件不存在"); + } + } + + musicListActivity.delete(localMusicBean); + } + if (adapter.getData().isEmpty()) { + setUI(true); + } + cancelLoading(); + } + + @Override + public void onDeleteFail(String message) { + cancelLoading(); + toast(ResUtil.getString(R.string.music_fragment_localmusiclistfragment_05) + message); + } + + private void cancelLoading() { + if (getDialogManager().isDialogShowing()) { + getDialogManager().dismissDialog(); + } + } + + public void add(LocalMusicBean localMusicBean) { + refreshLayout.autoRefresh(); + musicCount++; + updateMusicCount(); + } + + + private void updatePlayerList() { + PlayerModel.get().setLocalMusicBeanList(adapter.getData()); + } + + private void updateMusicCount() { + tvSongNum.setText(String.format(Locale.getDefault(), ResUtil.getString(R.string.music_fragment_localmusiclistfragment_06), musicCount == -1 ? 0 : musicCount)); + } + + @Override + public void onGetCountSuccess(int count) { + musicCount = count; + updateMusicCount(); + } + + @Override + public void onGetCountFail(String message) { + + } + + + public void specialAddMusic() { + + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/fragment/ShareMusicListFragment.java b/app/src/module_music/java/com/chwl/app/music/fragment/ShareMusicListFragment.java new file mode 100644 index 0000000..084aa9f --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/fragment/ShareMusicListFragment.java @@ -0,0 +1,291 @@ +package com.chwl.app.music.fragment; + +import android.text.Editable; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpFragment; +import com.chwl.app.music.activity.MusicListActivity; +import com.chwl.app.music.adapter.ShareMusicListAdapter; +import com.chwl.app.music.presenter.ShareMusicListPresenter; +import com.chwl.app.utils.KeyBoardUtils; +import com.chwl.core.Constants; +import com.chwl.core.music.bean.ShareMusicInfo; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.view.IShareMusicListView; +import com.chwl.library.base.factory.CreatePresenter; +import com.chwl.library.utils.ListUtils; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.TextWatcherWrapper; +import com.netease.nim.uikit.common.util.sys.NetworkUtil; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; + +import java.util.List; +import java.util.Objects; + +; +; + +@CreatePresenter(ShareMusicListPresenter.class) +public class ShareMusicListFragment extends BaseMvpFragment + implements IShareMusicListView, View.OnClickListener { + + private EditText searchInput; + private ImageView clearView; + private TextView searchBtn; + private SmartRefreshLayout refreshLayout; + private RecyclerView recyclerView; + private TextView tipsEmptyView; + private TextView tipsErrorView; + + private ShareMusicListAdapter adapter; + private String keyword = ""; + + public static ShareMusicListFragment newInstance() { + return new ShareMusicListFragment(); + } + + @Override + public int getRootLayoutId() { + return R.layout.fragment_share_music_list; + } + + @Override + public void onFindViews() { + searchInput = mView.findViewById(R.id.et_search); + clearView = mView.findViewById(R.id.iv_delete); + searchBtn = mView.findViewById(R.id.tv_search); + refreshLayout = mView.findViewById(R.id.srf_share_music); + recyclerView = mView.findViewById(R.id.rv_share_music); + tipsEmptyView = mView.findViewById(R.id.tv_tips_empty); + tipsErrorView = mView.findViewById(R.id.tv_tips_error); + + refreshLayout.setEnableLoadMore(true); + refreshLayout.setEnableRefresh(true); + refreshLayout.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() { + @Override + public void onLoadMore(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(getContext())) { + refreshLayout.finishLoadMore(); + return; + } + List data = adapter.getData(); + if (ListUtils.isListEmpty(data)) { + refreshLayout.finishLoadMore(); + return; + } + getMvpPresenter().loadMoreData(keyword); + } + + @Override + public void onRefresh(RefreshLayout refreshlayout) { + if (!NetworkUtil.isNetAvailable(getContext())) { + refreshLayout.finishRefresh(); + return; + } + getMvpPresenter().firstLoad(keyword); + } + }); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext(), + RecyclerView.VERTICAL, false)); + adapter = new ShareMusicListAdapter(); + recyclerView.setAdapter(adapter); + adapter.setOnItemChildClickListener((adapter1, view, position) -> { + ShareMusicInfo shareMusicInfo = (ShareMusicInfo) adapter1.getItem(position); + if (view.getId() == R.id.add_btn) { + getDialogManager().showProgressDialog(getContext()); + getMvpPresenter().addMusicToLocal(shareMusicInfo); + } + }); + recyclerView.requestFocus(); + clearView.setVisibility(View.GONE); + SpannableStringBuilder builder = new SpannableStringBuilder(tipsErrorView.getText()); + builder.setSpan(new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.appColor)), + tipsErrorView.getText().length() - 4, tipsErrorView.getText().length(), + SpannableStringBuilder.SPAN_INCLUSIVE_EXCLUSIVE); + tipsErrorView.setText(builder); + displayDataView(); + } + + @Override + public void onSetListener() { + searchInput.addTextChangedListener(new TextWatcherWrapper() { + @Override + public void afterTextChanged(Editable editable) { + super.afterTextChanged(editable); + clearView.setVisibility(TextUtils.isEmpty(editable.toString()) ? View.GONE : View.VISIBLE); + } + }); + clearView.setOnClickListener(this); + searchBtn.setOnClickListener(this); + tipsEmptyView.setOnClickListener(this); + tipsErrorView.setOnClickListener(this); + } + + @Override + public void initiate() { + + } + + @Override + public void onResume() { + super.onResume(); + // 加载页面数据 + getMvpPresenter().firstLoad(keyword); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.iv_delete: + searchInput.getText().clear(); + this.keyword = ""; + getMvpPresenter().firstLoad(keyword); + break; + + case R.id.tv_search: + String msg = searchInput.getText().toString(); + if (TextUtils.isEmpty(msg)) { + toast(ResUtil.getString(R.string.music_fragment_sharemusiclistfragment_02)); + return; + } + this.keyword = msg; + KeyBoardUtils.hideKeyBoard(getContext(), searchInput); + getMvpPresenter().firstLoad(keyword); + break; + + case R.id.tv_tips_empty: + break; + + case R.id.tv_tips_error: + getMvpPresenter().firstLoad(keyword); + break; + + default: + break; + } + } + + public void displayEmptyView() { + tipsEmptyView.setVisibility(View.VISIBLE); + tipsErrorView.setVisibility(View.GONE); + refreshLayout.setVisibility(View.GONE); + } + + public void displayErrorView() { + tipsEmptyView.setVisibility(View.GONE); + tipsErrorView.setVisibility(View.VISIBLE); + refreshLayout.setVisibility(View.GONE); + } + + public void displayDataView() { + tipsEmptyView.setVisibility(View.GONE); + tipsErrorView.setVisibility(View.GONE); + refreshLayout.setVisibility(View.VISIBLE); + } + + @Override + public void onGetDataFail(String errorMsg) { + if (getDialogManager().isDialogShowing()) { + getDialogManager().dismissDialog(); + } + toast(errorMsg); + displayErrorView(); + } + + @Override + public void onGetDataSuccess(List data, int page) { + if (!ListUtils.isListEmpty(data)) { + displayDataView(); + if (page == Constants.PAGE_START) { + adapter.setNewData(data); + refreshLayout.finishRefresh(); + } else { + adapter.addData(data); + refreshLayout.finishLoadMore(); + } + } else { + if (page == Constants.PAGE_START) { + refreshLayout.finishRefresh(); + adapter.setNewData(null); + displayEmptyView(); + } else { + refreshLayout.finishLoadMore(); + } + } + } + + @Override + public void onSearchSongSuccess(List data, int page) { + if (!ListUtils.isListEmpty(data)) { + displayDataView(); + if (page == Constants.PAGE_START) { + adapter.setNewData(data); + refreshLayout.finishRefresh(); + } else { + adapter.addData(data); + refreshLayout.finishLoadMore(); + } + } else { + if (page == Constants.PAGE_START) { + refreshLayout.finishRefresh(); + adapter.setNewData(null); + displayEmptyView(); + } else { + refreshLayout.finishLoadMore(); + } + } + } + + @Override + public void onAddSuccess(ShareMusicInfo shareMusicInfo, LocalMusicBean localMusicBean) { + for (int i = 0; i < adapter.getData().size(); i++) { + ShareMusicInfo smi = adapter.getData().get(i); + if (smi.getMusicId() == shareMusicInfo.getMusicId()) { + adapter.notifyItemChanged(i); + if (getActivity() instanceof MusicListActivity) { + MusicListActivity activity = (MusicListActivity) getActivity(); + activity.add(localMusicBean); + } + break; + } + } + cancelLoading(); + + } + + @Override + public void onAddFail(ShareMusicInfo shareMusicInfo, Throwable throwable) { + toast(ResUtil.getString(R.string.music_fragment_sharemusiclistfragment_05) + throwable.getMessage()); + cancelLoading(); + } + + public void delete(LocalMusicBean localMusicBean) { + for (int i = 0; i < adapter.getData().size(); i++) { + ShareMusicInfo smi = adapter.getData().get(i); + if (Objects.equals(smi.getLocalUri(), localMusicBean.getLocalUri())) { + smi.setInLocalList(false); + adapter.notifyItemChanged(i); + break; + } + } + } + + private void cancelLoading() { + if (getDialogManager().isDialogShowing()) { + getDialogManager().dismissDialog(); + } + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/presenter/AddLocalMusicListPresenter.kt b/app/src/module_music/java/com/chwl/app/music/presenter/AddLocalMusicListPresenter.kt new file mode 100644 index 0000000..7ea73a1 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/presenter/AddLocalMusicListPresenter.kt @@ -0,0 +1,164 @@ +package com.chwl.app.music.presenter + +import android.net.Uri +import android.os.Build +import android.os.Environment +import com.chwl.app.base.BaseMvpPresenter +import com.chwl.core.music.db.bean.LocalMusicBean +import com.chwl.core.music.db.model.LocalMusicDbModel +import com.chwl.core.music.view.IAddLocalMusicListView +import com.chwl.core.utils.CoreLogger +import com.chwl.core.utils.net.RxHelper +import com.chwl.library.base.PresenterEvent +import com.chwl.library.common.file.FileHelper +import io.reactivex.disposables.Disposable +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.io.File + +class AddLocalMusicListPresenter : BaseMvpPresenter() { + var isScanning = false + private set + private var scanningDisposable: Disposable? = null + private var addAllDisposable: Disposable? = null + + private var mCopyJob: Job? = null + + companion object{ + private const val TAG = "AddLocalMusicListPresenter" + } + + fun scanningMusicInLocal() { + LocalMusicDbModel.getInstance().scanLocalMusic() + } + + fun stopScanLocalMusic() { + isScanning = false + if (scanningDisposable?.isDisposed == false) { + scanningDisposable?.dispose() + } + } + + val localMusicBeans: Unit + get() { + LocalMusicDbModel.getInstance().localMusicInfoList + } + + fun getLocalMusicBeanList(page: Int) {} + + fun scanningLocalMusicBeans() { + if (isScanning) { + return + } + isScanning = true + scanningDisposable = LocalMusicDbModel.getInstance().scanLocalMusicBeans() + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleException()) + .compose(RxHelper.handleSchedulers()) + .subscribe { localMusicBeans: List?, throwable: Throwable? -> + isScanning = false + if (mvpView == null) { + return@subscribe + } + mvpView?.onScanningComplete() + if (throwable == null) { + mvpView?.onScanningLocalMusicSuccess(localMusicBeans) + } else { + mvpView?.onScanningLocalMusicFail(throwable) + } + } + } + + fun batchAddToPlayerList(needAddList: List) { + val list = ArrayList() + list.addAll(needAddList) + //APP 本地数据库里的数据 + mCopyJob = MainScope().launch { + withContext(Dispatchers.IO){ + if (list.isNotEmpty()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ + //localMusicList 手机外置存储的歌曲,android Q+ 需要插入到app 数据库的 + list.forEach { music -> + val newPath = copyFileToCache(music) + if (newPath != null){ + music.localUri = newPath + } + } + } + addAllDisposable = LocalMusicDbModel.getInstance().batchAddToDB(list) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchedulers()) + .subscribe { ids: List?, throwable: Throwable? -> + if (mvpView == null) { + return@subscribe + } + if (throwable == null) { + mvpView?.addAllSuccess(ids) + } else { + mvpView?.addAllFail(throwable) + } + } + } + } + } + } + + fun batchAddToPlayerListSpecial(needAddList: List) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){ + val list = ArrayList() + list.addAll(needAddList) + //APP 本地数据库里的数据 + mCopyJob = MainScope().launch { + withContext(Dispatchers.IO){ + if (list.isNotEmpty()) { + addAllDisposable = LocalMusicDbModel.getInstance().batchAddToDB(list) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchedulers()) + .subscribe { ids: List?, throwable: Throwable? -> + if (mvpView == null) { + return@subscribe + } + if (throwable == null) { + mvpView?.addAllSuccess(ids) + } else { + mvpView?.addAllFail(throwable) + } + } + } + } + } + } + + } + + /** + * 音乐文件缓存目录 + */ + private fun getCacheMusicDir():String{ + return "${FileHelper.getRootFilesDir(Environment.DIRECTORY_MUSIC).absolutePath}${File.separator}" + } + + private fun copyFileToCache(music: LocalMusicBean): String? { + val path = "${getCacheMusicDir()}${music.songName}" + return if (FileHelper.copyFileFromUri(Uri.parse(music.uri), path, false)) { + CoreLogger.debug(TAG, "copy success, path: $path ") + path + } else { + null + } + } + + override fun onDestroyPresenter() { + stopScanLocalMusic() + if (mCopyJob?.isActive == true){ + mCopyJob?.cancel() + } + if (addAllDisposable?.isDisposed == false) { + addAllDisposable?.dispose() + } + super.onDestroyPresenter() + } +} \ No newline at end of file diff --git a/app/src/module_music/java/com/chwl/app/music/presenter/LocalMusicListPresenter.java b/app/src/module_music/java/com/chwl/app/music/presenter/LocalMusicListPresenter.java new file mode 100644 index 0000000..3b425f7 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/presenter/LocalMusicListPresenter.java @@ -0,0 +1,116 @@ +package com.chwl.app.music.presenter; + +import android.annotation.SuppressLint; + +import com.chwl.app.base.BaseMvpPresenter; +import com.chwl.core.db.AppDataBase; +import com.chwl.core.Constants; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.db.model.LocalMusicDbModel; +import com.chwl.core.music.model.PlayerModel; +import com.chwl.core.music.view.ILocalMusicListView; +import com.chwl.core.utils.net.RxHelper; +import com.chwl.library.base.PresenterEvent; +import com.chwl.library.utils.ListUtils; + +import java.util.concurrent.atomic.AtomicInteger; + +import io.reactivex.Single; +import io.reactivex.SingleEmitter; +import io.reactivex.SingleOnSubscribe; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.BiConsumer; + +public class LocalMusicListPresenter extends BaseMvpPresenter { + + private volatile AtomicInteger page = new AtomicInteger(Constants.PAGE_START); + + private Disposable listDisposable; + + /** + * 加载本地数据库 + */ + public void loadMoreData() { + if (listDisposable != null && !listDisposable.isDisposed()) { + listDisposable.dispose(); + listDisposable = null; + } + listDisposable = LocalMusicDbModel.getInstance().getLocalMusicBeans(page.get()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleException()) + .compose(RxHelper.handleSchedulers()) + .subscribe((list, throwable) -> { + if (getMvpView() == null) { + return; + } + if (throwable == null) { + getMvpView().onGetListSuccess(list, page.get()); + if (!ListUtils.isListEmpty(list)) { + page.incrementAndGet(); + } + } else { + getMvpView().onGetListFail(throwable.getMessage()); + } + }); + } + + /** + * 删除数据库对象 + * + * @param localMusicBean + */ + @SuppressLint("CheckResult") + public boolean delete(LocalMusicBean localMusicBean, int position) { + Single.create(new SingleOnSubscribe() { + @Override + public void subscribe(SingleEmitter e) throws Exception { + e.onSuccess(AppDataBase.getInstance().localMusicDao().deleteByLocalUri(localMusicBean.getLocalUri())); + } + }) + .compose(RxHelper.handleSchedulers()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe((id, throwable) -> { + if (getMvpView() == null) { + return; + } + if (throwable == null) { + getMvpView().onDeleteSuccess(localMusicBean, position); + if (PlayerModel.get().isCurrent(localMusicBean)) { + PlayerModel.get().stop(); + } + } else { + getMvpView().onDeleteFail(throwable.getMessage()); + } + }); + return true; + } + + public void play(LocalMusicBean localMusicBean, int position) { + PlayerModel.get().play(localMusicBean); + } + + public void loadFirstPage() { + page.set(Constants.PAGE_START); + loadMoreData(); + getSongCount(); + } + + @SuppressLint("CheckResult") + public void getSongCount() { + LocalMusicDbModel.getInstance().getLocalMusicCount() + .compose(RxHelper.handleSchedulers()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)).subscribe(new BiConsumer() { + @Override + public void accept(Integer integer, Throwable throwable) throws Exception { + if (getMvpView() == null) { + return; + } + if (throwable == null) { + getMvpView().onGetCountSuccess(integer == null ? 0 : integer); + } else { + getMvpView().onGetCountFail(throwable.getMessage()); + } + } + }); + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/presenter/MusicListPresenter.java b/app/src/module_music/java/com/chwl/app/music/presenter/MusicListPresenter.java new file mode 100644 index 0000000..d28cc4c --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/presenter/MusicListPresenter.java @@ -0,0 +1,7 @@ +package com.chwl.app.music.presenter; + +import com.chwl.app.base.BaseMvpPresenter; +import com.chwl.core.music.view.IMusicListView; + +public class MusicListPresenter extends BaseMvpPresenter { +} diff --git a/app/src/module_music/java/com/chwl/app/music/presenter/ShareMusicListPresenter.java b/app/src/module_music/java/com/chwl/app/music/presenter/ShareMusicListPresenter.java new file mode 100644 index 0000000..cda523c --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/presenter/ShareMusicListPresenter.java @@ -0,0 +1,142 @@ +package com.chwl.app.music.presenter; + +import android.annotation.SuppressLint; + +import com.chwl.app.base.BaseMvpPresenter; +import com.chwl.core.db.AppDataBase; +import com.chwl.core.Constants; +import com.chwl.core.music.bean.ShareMusicInfo; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.model.ShareMusicListModel; +import com.chwl.core.music.view.IShareMusicListView; +import com.chwl.core.utils.net.RxHelper; +import com.chwl.library.base.PresenterEvent; +import com.chwl.library.utils.ListUtils; + +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class ShareMusicListPresenter extends BaseMvpPresenter { + + private volatile AtomicInteger page = new AtomicInteger(Constants.PAGE_START); + private volatile AtomicInteger searchPage = new AtomicInteger(Constants.PAGE_START); + + @SuppressLint("CheckResult") + public void firstLoad(String keyword) { + page.set(Constants.PAGE_START); + loadMoreData(keyword); + } + + @SuppressLint("CheckResult") + public void loadMoreData(String song) { + ShareMusicListModel.getInstance() + .searchShareMusicList(song,page.get()) + .observeOn(Schedulers.io()) + .map(new Function, List>() { + @Override + public List apply(List shareMusicInfos) throws Exception { + for (ShareMusicInfo shareMusicInfo : shareMusicInfos) { + checkInDb(shareMusicInfo); + } + return shareMusicInfos; + } + }) + .compose(RxHelper.handleSchedulers()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe((shareMusicInfos, throwable) -> { + if (throwable == null) { + getMvpView().onGetDataSuccess(shareMusicInfos, page.get()); + if (!ListUtils.isListEmpty(shareMusicInfos)) { + page.incrementAndGet(); + } + } else { + getMvpView().onGetDataFail(throwable.getMessage()); + } + }); + } + + /** + * 检查是否在数据库中 + * + * @param shareMusicInfo + */ + private void checkInDb(ShareMusicInfo shareMusicInfo) { + if (shareMusicInfo == null) { + return; + } + shareMusicInfo.setInLocalList( + !ListUtils.isListEmpty( + AppDataBase + .getInstance() + .localMusicDao() + .checkExist( + shareMusicInfo.getSongName(), shareMusicInfo.getLocalUri()))); + } + +// @SuppressLint("CheckResult") +// public void searchSong(String song) { +// searchPage.set(Constants.PAGE_START); +// ShareMusicListModel.getInstance() +// .searchShareMusicList(song, searchPage.get()) +// .observeOn(Schedulers.io()) +// .map(new Function, List>() { +// @Override +// public List apply(List shareMusicInfos) throws Exception { +// for (ShareMusicInfo shareMusicInfo : shareMusicInfos) { +// checkInDb(shareMusicInfo); +// } +// return shareMusicInfos; +// } +// }) +// .compose(RxHelper.handleSchedulers()) +// .compose(bindUntilEvent(PresenterEvent.DESTROY)) +// .subscribe((shareMusicInfos, throwable) -> { +// if (throwable == null) { +// getMvpView().onSearchSongSuccess(shareMusicInfos, searchPage.get()); +// if (!ListUtils.isListEmpty(shareMusicInfos)) { +// searchPage.incrementAndGet(); +// } +// } else { +// getMvpView().onGetDataFail(throwable.getMessage()); +// } +// }); +// } + + @SuppressLint("CheckResult") + public void addMusicToLocal(ShareMusicInfo shareMusicInfo) { + if (shareMusicInfo == null) { + return; + } + ShareMusicListModel.getInstance().addToLocalMusic(shareMusicInfo) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchedulers()) + .subscribe(new BiConsumer() { + @Override + public void accept(LocalMusicBean localMusicBean, Throwable throwable) throws Exception { + if (getMvpView() == null) { + return; + } + if (throwable == null) { + shareMusicInfo.setInLocalList(true); + getMvpView().onAddSuccess(shareMusicInfo, localMusicBean); + } else { + getMvpView().onAddFail(shareMusicInfo, throwable); + } + } + }); + //调用添加音乐接口 + ShareMusicListModel.getInstance().addMusic(shareMusicInfo.getMusicId()) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchedulers()).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + } + }); + } + + +} diff --git a/app/src/module_music/java/com/chwl/app/music/widget/MusicPlayerView.java b/app/src/module_music/java/com/chwl/app/music/widget/MusicPlayerView.java new file mode 100644 index 0000000..471ff26 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/widget/MusicPlayerView.java @@ -0,0 +1,353 @@ +package com.chwl.app.music.widget; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.chwl.app.R; +import com.chwl.app.base.BaseMvpActivity; +import com.chwl.app.music.activity.MusicListActivity; +import com.chwl.app.ui.widget.magicindicator.buildins.UIUtil; +import com.chwl.core.DemoCache; +import com.chwl.core.music.db.bean.LocalMusicBean; +import com.chwl.core.music.event.CurrentMusicUpdateEvent; +import com.chwl.core.music.event.MusicPauseEvent; +import com.chwl.core.music.event.MusicPlayingEvent; +import com.chwl.core.music.event.MusicStopEvent; +import com.chwl.core.music.model.IPlayerModel; +import com.chwl.core.music.model.PlayerModel; +import com.chwl.library.utils.ResUtil; +import com.chwl.library.utils.SingleToastUtil; + +import org.greenrobot.eventbus.EventBus; +import org.greenrobot.eventbus.Subscribe; +import org.greenrobot.eventbus.ThreadMode; + +import java.util.List; + +/** + * 音乐播放入口 + * Created by chenran on 2017/10/28. + */ + +public class MusicPlayerView extends FrameLayout implements View.OnClickListener, SeekBar.OnSeekBarChangeListener { + private View musicFlagLayout; + private RelativeLayout musicBoxLayout; + private View musicFlag; + private ImageView musicListMore; + private ImageView musicPlayPause; + private ImageView nextBtn; + private ImageView musicPlayCycle; + private SeekBar volumeSeekBar; + private TextView musicName; + private String imageBg; + private View layoutMusicBgClick; + private CallBack mCallBack; + + public MusicPlayerView(Context context) { + this(context, null); + } + + public MusicPlayerView(Context context, AttributeSet attr) { + this(context, attr, 0); + } + + public MusicPlayerView(Context context, AttributeSet attr, int i) { + super(context, attr, i); + init(); + } + + private void init() { + EventBus.getDefault().register(this); + LayoutInflater.from(getContext()).inflate(R.layout.layout_music_player_view, this, true); + musicBoxLayout = findViewById(R.id.music_box_layout); + musicBoxLayout.setOnClickListener(this); + musicListMore = findViewById(R.id.music_list_more); + musicListMore.setOnClickListener(this); + + musicPlayPause = findViewById(R.id.music_play_pause); + musicPlayPause.setOnClickListener(this); + volumeSeekBar = findViewById(R.id.voice_seek); + volumeSeekBar.setMax(100); + volumeSeekBar.setProgress(PlayerModel.get().getCurrentVolume()); + volumeSeekBar.setOnSeekBarChangeListener(this); + musicName = findViewById(R.id.music_name); + nextBtn = findViewById(R.id.music_play_next); + nextBtn.setOnClickListener(this); + layoutMusicBgClick = findViewById(R.id.layout_music_bg_click); + layoutMusicBgClick.setOnClickListener(this); + layoutMusicBgClick.setVisibility(INVISIBLE); + + musicPlayCycle = findViewById(R.id.music_play_cycle); + musicPlayCycle.setOnClickListener(this); + if (DemoCache.readBgmSingleCycle()) { + musicPlayCycle.setImageResource(R.drawable.icon_music_single_cycle); + } else { + musicPlayCycle.setImageResource(R.drawable.icon_music_all_cycle); + } + updateView(); + } + + public void setImageBg(String imageBg) { +// this.imageBg = imageBg; + } + + private void playFlagRotateAnim() { + if (musicFlag == null) { + return; + } + Animation operatingAnim = AnimationUtils.loadAnimation(getContext(), R.anim.rotate_quick_anim); + LinearInterpolator lin = new LinearInterpolator(); + operatingAnim.setInterpolator(lin); + musicFlag.startAnimation(operatingAnim); + } + + private void stopFlagRotateAnim() { + if (musicFlag == null) { + return; + } + musicFlag.clearAnimation(); + } + + private void showFlagInAnim() { +// if (musicFlagLayout == null) { +// return; +// } + ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(musicBoxLayout, "translationY", 0, UIUtil.dip2px(getContext(), 317)).setDuration(150); + objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + layoutMusicBgClick.setVisibility(GONE); + if (mCallBack != null) { + mCallBack.onClose(); + } + } + }); + objectAnimator.start(); + +// ObjectAnimator objectAnimatorFlag = ObjectAnimator.ofFloat( +// musicFlagLayout, +// "translationX", +// UIUtil.dip2px(getContext(), 76), +// 0) +// .setDuration(150); +// objectAnimatorFlag.setInterpolator(new AccelerateDecelerateInterpolator()); +// objectAnimatorFlag.setStartDelay(150); +// objectAnimatorFlag.addListener(new AnimatorListenerAdapter() { +// @Override +// public void onAnimationStart(Animator animation) { +// super.onAnimationStart(animation); +// layoutMusicBgClick.setVisibility(GONE); +// } +// }); +// objectAnimatorFlag.start(); + } + + public void showBoxInAnim() { +// if (musicFlagLayout == null) { +// return; +// } +// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat( +// musicFlagLayout, +// "translationX", +// 0, +// UIUtil.dip2px(getContext(), 76)) +// .setDuration(150); +// objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); +// objectAnimator.start(); + + + ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(musicBoxLayout, "translationY", UIUtil.dip2px(getContext(), 317), 0).setDuration(150); + objectAnimator1.setInterpolator(new AccelerateDecelerateInterpolator()); + objectAnimator1.setStartDelay(150); + objectAnimator1.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + layoutMusicBgClick.setVisibility(VISIBLE); + } + }); + objectAnimator1.start(); + } + + public void updateVoiceValue() { + volumeSeekBar.setProgress(PlayerModel.get().getCurrentVolume()); + } + + @Override + protected void onDetachedFromWindow() { + EventBus.getDefault().unregister(this); + super.onDetachedFromWindow(); + } + + public void release() { + stopFlagRotateAnim(); + EventBus.getDefault().unregister(this); +// stopMusic(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.layout_music_bg_click: + showFlagInAnim(); + break; + case R.id.music_list_more: + MusicListActivity.openLocalMusicList(getContext()); + break; + case R.id.music_play_pause: + List localMusicInfoList = PlayerModel.get().getPlayerListMusicInfos(); + if (localMusicInfoList != null && localMusicInfoList.size() > 0) { + int state = PlayerModel.get().getState(); + if (state == IPlayerModel.STATE_PLAY) { + PlayerModel.get().pause(); + } else if (state == IPlayerModel.STATE_PAUSE) { + PlayerModel.get().play(null); + } else { + int result = PlayerModel.get().playNext(); + if (result < 0) { + if (result == -3) { + ((BaseMvpActivity) getContext()).toast(ResUtil.getString(R.string.music_widget_musicplayerview_03)); + } else { + ((BaseMvpActivity) getContext()).toast(ResUtil.getString(R.string.music_widget_musicplayerview_04)); + } + } + } + } else { + MusicListActivity.openLocalMusicList(getContext()); + } + break; + case R.id.music_play_next: + List localMusicInfoList1 = PlayerModel.get().getPlayerListMusicInfos(); + if (localMusicInfoList1 != null && localMusicInfoList1.size() > 0) { + int result = PlayerModel.get().playNext(); + if (result < 0) { + if (result == -3) { + ((BaseMvpActivity) getContext()).toast(ResUtil.getString(R.string.music_widget_musicplayerview_05)); + } else { + ((BaseMvpActivity) getContext()).toast(ResUtil.getString(R.string.music_widget_musicplayerview_06)); + } + } + } else { + MusicListActivity.openLocalMusicList(getContext()); + } + break; + case R.id.music_play_cycle: + if (DemoCache.readBgmSingleCycle()) { + DemoCache.saveBgmSingleCycle(false); + musicPlayCycle.setImageResource(R.drawable.icon_music_all_cycle); + SingleToastUtil.showToast(ResUtil.getString(R.string.music_widget_musicplayerview_07)); + } else { + DemoCache.saveBgmSingleCycle(true); + musicPlayCycle.setImageResource(R.drawable.icon_music_single_cycle); + SingleToastUtil.showToast(ResUtil.getString(R.string.music_widget_musicplayerview_08)); + } + default: + break; + } + } + + private void updateView() { + LocalMusicBean current = PlayerModel.get().getCurrent(); + if (current != null) { + musicName.setText(current.getSongName()); + int state = PlayerModel.get().getState(); + if (state == IPlayerModel.STATE_PLAY) { + musicPlayPause.setImageResource(R.drawable.icon_music_play); + } else { + musicPlayPause.setImageResource(R.drawable.icon_music_pause); + } + playFlagRotateAnim(); + } else { + musicName.setText(ResUtil.getString(R.string.music_widget_musicplayerview_09)); + musicPlayPause.setImageResource(R.drawable.icon_music_pause); + stopFlagRotateAnim(); + } + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMusicPlaying(MusicPlayingEvent event) { + LocalMusicBean localMusicInfo = PlayerModel.get().getCurrent(); + updateView(); + playFlagRotateAnim(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMusicPause(MusicPauseEvent event) { + updateView(); + + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onMusicStop(MusicStopEvent event) { + updateView(); + } + + @Subscribe(threadMode = ThreadMode.MAIN) + public void onCurrentMusicUpdate(CurrentMusicUpdateEvent localMusicInfo) { + updateView(); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + PlayerModel.get().seekVolume(progress); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + + /** + * 关联入口View + * @param iconView 入口View + * @param stateView 播放状态View + * + */ + public void linkIconView(View iconView, View stateView) { + this.musicFlagLayout = iconView; + this.musicFlag = stateView; + this.musicFlagLayout.setOnClickListener(view -> { + showBoxInAnim(); + }); + } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + if (musicFlagLayout != null) { + this.musicFlagLayout.setVisibility(visibility); + } + if (musicFlag != null) { + this.musicFlag.setVisibility(visibility); + } + } + + public void setCallBack(CallBack mCallBack) { + this.mCallBack = mCallBack; + } + + public interface CallBack{ + void onClose(); + } +} diff --git a/app/src/module_music/java/com/chwl/app/music/widget/VoiceSeekDialog.java b/app/src/module_music/java/com/chwl/app/music/widget/VoiceSeekDialog.java new file mode 100644 index 0000000..3e86692 --- /dev/null +++ b/app/src/module_music/java/com/chwl/app/music/widget/VoiceSeekDialog.java @@ -0,0 +1,84 @@ +package com.chwl.app.music.widget; + +import android.content.Context; +import android.os.Bundle; +import android.view.Gravity; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.chwl.app.ui.widget.dialog.BaseDialog; +import com.chwl.app.R; +import com.chwl.core.manager.AudioEngineManager; +import com.chwl.core.music.model.PlayerModel; + + +/** + * Created by chenran on 2017/12/18. + */ + +public class VoiceSeekDialog extends BaseDialog implements SeekBar.OnSeekBarChangeListener{ + private Context context; + private SeekBar musicVoiceSeek; + private SeekBar voiceSeek; + private TextView musicVoiceNum; + private TextView voiceNum; + + public VoiceSeekDialog(@NonNull Context context) { + super(context, R.style.ErbanBottomSheetDialog); + this.context = context; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_voice_seek); + setCanceledOnTouchOutside(true); + + musicVoiceSeek = findViewById(R.id.music_voice_seek); + musicVoiceSeek.setMax(100); + musicVoiceSeek.setProgress(PlayerModel.get().getCurrentVolume()); + musicVoiceSeek.setOnSeekBarChangeListener(this); + + voiceSeek = findViewById(R.id.voice_seek); + voiceSeek.setMax(100); + voiceSeek.setProgress(PlayerModel.get().getCurrentRecordingVolume()); + voiceSeek.setOnSeekBarChangeListener(this); + + musicVoiceNum = findViewById(R.id.music_voice_number); + voiceNum = findViewById(R.id.voice_number); + + musicVoiceNum.setText(PlayerModel.get().getCurrentVolume()+"%"); + voiceNum.setText(PlayerModel.get().getCurrentRecordingVolume()+"%"); + + WindowManager.LayoutParams params = getWindow().getAttributes(); + params.width = WindowManager.LayoutParams.MATCH_PARENT; + params.gravity = Gravity.BOTTOM; + getWindow().setAttributes(params); + + getWindow().setDimAmount(0F); // 弹框背景全透明 + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (seekBar == musicVoiceSeek) { + PlayerModel.get().seekVolume(progress); + musicVoiceNum.setText(progress+"%"); + } else { + PlayerModel.get().seekRecordingVolume(progress); + voiceNum.setText(progress+"%"); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } +} diff --git a/app/src/module_music/res/drawable-xhdpi/drawable_scanning_local_music.webp b/app/src/module_music/res/drawable-xhdpi/drawable_scanning_local_music.webp new file mode 100644 index 0000000..521cfc1 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/drawable_scanning_local_music.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/ic_add_music.webp b/app/src/module_music/res/drawable-xhdpi/ic_add_music.webp new file mode 100644 index 0000000..4eb24bd Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/ic_add_music.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/ic_pay_diamond_delete.webp b/app/src/module_music/res/drawable-xhdpi/ic_pay_diamond_delete.webp new file mode 100644 index 0000000..7dec5bb Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/ic_pay_diamond_delete.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_adjust_voice.webp b/app/src/module_music/res/drawable-xhdpi/icon_adjust_voice.webp new file mode 100644 index 0000000..8705a84 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_adjust_voice.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_delete_music.webp b/app/src/module_music/res/drawable-xhdpi/icon_delete_music.webp new file mode 100644 index 0000000..92a0a43 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_delete_music.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_game_top.webp b/app/src/module_music/res/drawable-xhdpi/icon_game_top.webp new file mode 100644 index 0000000..f02e05b Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_game_top.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_add.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_add.webp new file mode 100644 index 0000000..30fcf7c Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_add.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_all_cycle.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_all_cycle.webp new file mode 100644 index 0000000..4a27204 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_all_cycle.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_list_more.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_list_more.webp new file mode 100644 index 0000000..690f3db Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_list_more.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_next.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_next.webp new file mode 100644 index 0000000..d748d00 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_next.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_pause_big.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_pause_big.webp new file mode 100644 index 0000000..485f69c Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_pause_big.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_play.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_play.webp new file mode 100644 index 0000000..5c6f524 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_play.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_play_big.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_play_big.webp new file mode 100644 index 0000000..63aac56 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_play_big.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_refresh.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_refresh.webp new file mode 100644 index 0000000..a435081 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_refresh.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_music_single_cycle.webp b/app/src/module_music/res/drawable-xhdpi/icon_music_single_cycle.webp new file mode 100644 index 0000000..27771a8 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_music_single_cycle.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_room_music_voice.webp b/app/src/module_music/res/drawable-xhdpi/icon_room_music_voice.webp new file mode 100644 index 0000000..966e9c0 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_room_music_voice.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/icon_room_voice_point.webp b/app/src/module_music/res/drawable-xhdpi/icon_room_voice_point.webp new file mode 100644 index 0000000..c7f19dd Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/icon_room_voice_point.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/music_icon_search.webp b/app/src/module_music/res/drawable-xhdpi/music_icon_search.webp new file mode 100644 index 0000000..c744d23 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/music_icon_search.webp differ diff --git a/app/src/module_music/res/drawable-xhdpi/music_icon_search_delete.webp b/app/src/module_music/res/drawable-xhdpi/music_icon_search_delete.webp new file mode 100644 index 0000000..caa7129 Binary files /dev/null and b/app/src/module_music/res/drawable-xhdpi/music_icon_search_delete.webp differ diff --git a/app/src/module_music/res/drawable/bg_room_music_player.xml b/app/src/module_music/res/drawable/bg_room_music_player.xml new file mode 100644 index 0000000..4e8f26a --- /dev/null +++ b/app/src/module_music/res/drawable/bg_room_music_player.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/app/src/module_music/res/drawable/layer_list_room_music_bar.xml b/app/src/module_music/res/drawable/layer_list_room_music_bar.xml new file mode 100644 index 0000000..a935200 --- /dev/null +++ b/app/src/module_music/res/drawable/layer_list_room_music_bar.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/module_music/res/drawable/shape_round_f5f5f5_radius_15dp.xml b/app/src/module_music/res/drawable/shape_round_f5f5f5_radius_15dp.xml new file mode 100644 index 0000000..53fa5af --- /dev/null +++ b/app/src/module_music/res/drawable/shape_round_f5f5f5_radius_15dp.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/module_music/res/layout/activity_add_music_list.xml b/app/src/module_music/res/layout/activity_add_music_list.xml new file mode 100644 index 0000000..af1cefe --- /dev/null +++ b/app/src/module_music/res/layout/activity_add_music_list.xml @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +