package com.cooleshow.musicmerge.ui; import android.Manifest; import android.annotation.SuppressLint; import android.content.pm.ActivityInfo; import android.os.Handler; import android.text.TextUtils; import android.view.Gravity; import android.view.View; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; import com.alibaba.android.arouter.launcher.ARouter; import com.cooleshow.base.router.RouterPath; import com.cooleshow.base.ui.fragment.BaseFragment; import com.cooleshow.base.utils.FileUtils; import com.cooleshow.base.utils.MyFileUtils; import com.cooleshow.base.utils.PermissionUtils; import com.cooleshow.base.utils.ToastUtil; import com.cooleshow.base.utils.helper.GlideEngine; import com.cooleshow.base.widgets.DialogUtil; import com.cooleshow.musicmerge.R; import com.cooleshow.musicmerge.constants.MusicMergeConfig; import com.cooleshow.musicmerge.databinding.FgMusicHandleSettingLayoutBinding; import com.cooleshow.musicmerge.helper.MixHelper; import com.cooleshow.musicmerge.viewmodel.MusicMergeViewModel; import com.cooleshow.musicmerge.widget.UploadCoverTipDialog; import com.luck.picture.lib.PictureSelector; import com.luck.picture.lib.config.PictureConfig; import com.luck.picture.lib.config.PictureMimeType; import com.tbruyelle.rxpermissions3.RxPermissions; import org.json.JSONException; import org.json.JSONObject; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.lifecycle.ViewModelProvider; /** * Author by pq, Date on 2023/8/28. */ public class MusicHandleSettingFragment extends BaseFragment implements View.OnClickListener { public static final int MAX_OFFSET_SECTION = 1200; public static final int MIN_OFFSET_SECTION = MAX_OFFSET_SECTION / 10; public static final int ACCOMPANY_TYPE = 1; public static final int RECORD_TYPE = 2; private String accompanyUrl; private String worksId; private OnEventListener mEventListener; private MusicMergeViewModel mViewModel; private Runnable mRunnable = new Runnable() { @Override public void run() { if (mViewBinding != null) { mViewBinding.tvRecordVolumeValue.setVisibility(View.GONE); } } }; private Runnable mRunnable2 = new Runnable() { @Override public void run() { if (mViewBinding != null) { mViewBinding.tvAccompanyVolumeValue.setVisibility(View.GONE); } } }; @Override protected FgMusicHandleSettingLayoutBinding getLayoutView() { return FgMusicHandleSettingLayoutBinding.inflate(getLayoutInflater()); } @Override protected void initView(View rootView) { mViewBinding.seekBarOffset.setMax(MAX_OFFSET_SECTION); mViewBinding.seekBarOffset.setProgress(MAX_OFFSET_SECTION / 2); formatProgress(); } @Override protected void initData() { accompanyUrl = getArguments().getString("accompanyUrl"); initViewModel(); initListener(); } private void initViewModel() { ViewModelProvider.AndroidViewModelFactory instance = ViewModelProvider.AndroidViewModelFactory .getInstance(getActivity().getApplication()); mViewModel = new ViewModelProvider(getActivity(), instance) .get(MusicMergeViewModel.class); worksId = mViewModel.getWorksId().getValue(); } private void initListener() { mViewBinding.ivAdd.setOnClickListener(this); mViewBinding.ivReduce.setOnClickListener(this); mViewBinding.tvSaveWorks.setOnClickListener(this); mViewBinding.tvRecord.setOnClickListener(this); mViewBinding.tvSave.setOnClickListener(this); mViewBinding.ivShrinkArrow.setOnClickListener(this); mViewBinding.seekVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mEventListener != null) { float value = mViewBinding.seekVolume.getProgress() * 1.0f / mViewBinding.seekVolume.getMax(); mEventListener.onVolumeChange(RECORD_TYPE, value); if (fromUser) { setUpdateStatus(); if (mViewBinding.tvRecordVolumeValue.getVisibility() == View.GONE) { mViewBinding.tvRecordVolumeValue.setVisibility(View.VISIBLE); } ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mViewBinding.viewLine.getLayoutParams(); layoutParams.horizontalBias = value; mViewBinding.viewLine.setLayoutParams(layoutParams); mViewBinding.tvRecordVolumeValue.setText(String.valueOf(mViewBinding.seekVolume.getProgress())); } } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { mViewBinding.tvRecordVolumeValue.postDelayed(mRunnable, 200); } }); mViewBinding.seekVolume2.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mEventListener != null) { float value = mViewBinding.seekVolume2.getProgress() * 1.0f / mViewBinding.seekVolume2.getMax(); mEventListener.onVolumeChange(ACCOMPANY_TYPE, value); if (fromUser) { setUpdateStatus(); if (mViewBinding.tvAccompanyVolumeValue.getVisibility() == View.GONE) { mViewBinding.tvAccompanyVolumeValue.setVisibility(View.VISIBLE); } ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) mViewBinding.viewLine2.getLayoutParams(); layoutParams.horizontalBias = value; mViewBinding.viewLine2.setLayoutParams(layoutParams); mViewBinding.tvAccompanyVolumeValue.setText(String.valueOf(mViewBinding.seekVolume2.getProgress())); } } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { mViewBinding.tvAccompanyVolumeValue.postDelayed(mRunnable2, 200); } }); mViewBinding.seekBarOffset.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (roundOffProgress(progress)) { formatProgress(); } if (fromUser) { setUpdateStatus(); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } private void setUpdateStatus() { mViewModel.getUpdateEvent().postValue(true); } @Override public void onClick(View view) { int id = view.getId(); if (id == R.id.tv_save_works) { showUploadCoverImgDialog(); // if (checkUploadCover()) { // showUploadCoverImgDialog(); // } else { // toCheckDownload(true); // } return; } if (id == R.id.iv_reduce) { changeOffsetValue(false); return; } if (id == R.id.iv_add) { changeOffsetValue(true); return; } if (id == R.id.tv_record) { if (getActivity() != null) { getActivity().finish(); } return; } if (id == R.id.tv_save) { if (mEventListener != null) { mEventListener.saveDraft(); } // toCheckDownload(false); return; } if (id == R.id.iv_shrink_arrow) { if (mEventListener != null) { mEventListener.hideSetting(); } return; } } private void changeOffsetValue(boolean isAdd) { int value = isAdd ? MAX_OFFSET_SECTION / MIN_OFFSET_SECTION : -MAX_OFFSET_SECTION / MIN_OFFSET_SECTION; int currentValue = mViewBinding.seekBarOffset.getProgress(); currentValue += value; if (currentValue < 0) { currentValue = 0; } if (currentValue > MAX_OFFSET_SECTION) { currentValue = MAX_OFFSET_SECTION; } mViewBinding.seekBarOffset.setProgress(currentValue); } @SuppressLint("CheckResult") private void toCheckDownload(boolean isNeedNotify) { new RxPermissions(MusicHandleSettingFragment.this) .request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE) .subscribe(permission -> { if (permission) { checkDownload(isNeedNotify); } else { DialogUtil.showInCenter(MusicHandleSettingFragment.this.getChildFragmentManager(), com.cooleshow.base.R.layout.accompany_permissions_popu, (holder, dialog) -> { TextView tvTitle = holder.getView(com.cooleshow.base.R.id.tv_title); TextView tvContent = holder.getView(com.cooleshow.base.R.id.tv_content); ImageView btncancel = holder.getView(com.cooleshow.base.R.id.btn_cancel); ImageView btnCommit = holder.getView(com.cooleshow.base.R.id.btn_commit); tvTitle.setText("提示"); tvContent.setText("请开储存访问权限"); btncancel.setOnClickListener(view1 -> { dialog.dismiss(); }); btnCommit.setOnClickListener(view1 -> { PermissionUtils.toSelfSetting(getContext()); dialog.dismiss(); }); }); } }); } private boolean checkUploadCover() { return TextUtils.isEmpty(worksId); } private void showUploadCoverImgDialog() { UploadCoverTipDialog coverTipDialog = new UploadCoverTipDialog(); coverTipDialog.setGravity(Gravity.CENTER); coverTipDialog.setHeight(-1); coverTipDialog.setWidth(316); coverTipDialog.setEventListener(new UploadCoverTipDialog.OnEventListener() { @Override public void onUploadCover() { toAlbum(1, 1, MusicHandleActivity.REQUEST_CODE_LOCAL); } @Override public void onPublish(String des) { mViewModel.refreshMusicDes(des); toCheckDownload(true); } @Override public void onSelectVideoCover(boolean isByAlbum) { if (isByAlbum) { toAlbum(16, 9, MusicHandleActivity.REQUEST_CODE_LOCAL_VIDEO_COVER); } else { String value = mViewModel.getVideoFilePath().getValue(); ARouter.getInstance().build(RouterPath.MusicTuner.MUSIC_SELECT_VIDEO_FRAME) .withString("videoFilePath", value) .withInt("c_orientation", ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) .navigation(getActivity(), MusicHandleActivity.REQUEST_CODE_VIDEO_COVER); } } }); coverTipDialog.show(getChildFragmentManager(), ""); } private void toAlbum(int aspect_ratio_x, int aspect_ratio_y, int requestCode) { new RxPermissions(this) .request(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE) .subscribe(granted -> { if (granted) { goAlbum(aspect_ratio_x, aspect_ratio_y, requestCode); } else { ToastUtil.getInstance().show(getContext(), "请打开存储和相机权限!"); } }); } private void goAlbum(int aspect_ratio_x, int aspect_ratio_y, int requestCode) { PictureSelector.create(getActivity()) .openGallery(PictureMimeType.ofImage())//全部.PictureMimeType.ofAll()、图片.ofImage()、视频.ofVideo()、音频.ofAudio() .loadImageEngine(GlideEngine.createGlideEngine()) .theme(com.cooleshow.base.R.style.picture_daya_style)// 主题样式设置 具体参考 values/styles 用法:R .style.picture.white.style .selectionMode(PictureConfig.SINGLE)// 多选 or 单选 PictureConfig.MULTIPLE or PictureConfig.SINGLE .enableCrop(true)// 是否裁剪 true or false .withAspectRatio(aspect_ratio_x, aspect_ratio_y) .cutOutQuality(100) .showCropGrid(false)// 是否显示裁剪矩形网格 圆形裁剪时建议设为false true or false .compress(true)// 是否压缩 true or false .circleDimmedLayer(false)// 是否圆形裁剪 true or false .forResult(requestCode); } private void checkDownload(boolean isNeedNotify) { String downloadSavePath = MixHelper.getInstance().getDownloadSavePath(accompanyUrl, MyFileUtils.MP3_FILE_SUFFIX); boolean fileExists = FileUtils.isFileExists(downloadSavePath); if (!fileExists) { return; } toMix(isNeedNotify); } private float getSeekVolume() { return mViewBinding.seekVolume.getProgress() * 1.0f / mViewBinding.seekVolume.getMax(); } private float getAccompanySeekVolume() { return mViewBinding.seekVolume2.getProgress() * 1.0f / mViewBinding.seekVolume2.getMax(); } private void toMix(boolean isNeedNotify) { int i = getOffsetValue(); float recordFileVolume = getSeekVolume(); float accompanyFileVolume = getAccompanySeekVolume(); if (mEventListener != null) { mEventListener.toMix(i, recordFileVolume, accompanyFileVolume, isNeedNotify); } } private int formatProgress() { int lastValue = getOffsetValue(); if (lastValue > 0) { mViewBinding.tvOffsetResult.setText("已为您对齐演奏伴奏,演奏提前" + lastValue + "毫秒"); } else if (lastValue < 0) { mViewBinding.tvOffsetResult.setText("已为您对齐演奏伴奏,演奏延后" + Math.abs(lastValue) + "毫秒"); } else { mViewBinding.tvOffsetResult.setText("演奏伴奏没有对齐?试试调整这里"); } if (mEventListener != null) { mEventListener.onOffsetValueChange(lastValue); } return lastValue; } private int getOffsetValue() { if (mViewBinding != null) { int progress = mViewBinding.seekBarOffset.getProgress(); int lastValue = progress - MAX_OFFSET_SECTION / 2; return lastValue; } return 0; } private int getProgressFromOffsetValue(int offset) { int progress = offset + MAX_OFFSET_SECTION / 2; return progress; } private boolean roundOffProgress(int progress) { int minSection = MAX_OFFSET_SECTION / MIN_OFFSET_SECTION; int result = progress % minSection; if (result == 0) { return true; } mViewBinding.seekBarOffset.setProgress(progress - result); return false; } public int getCurrentOffsetValue() { return getOffsetValue(); } public int getOriginalVolume() { int originalVolume = mViewBinding.seekVolume.getProgress(); return originalVolume; } public int getAccompanyVolume() { int accompanyVolume = mViewBinding.seekVolume2.getProgress(); return accompanyVolume; } public String getConfigJson() { if (isDetached()) { return ""; } if (!isAdded()) { return ""; } int currentOffsetValue = getCurrentOffsetValue(); int originalVolume = mViewBinding.seekVolume.getProgress(); int accompanyVolume = mViewBinding.seekVolume2.getProgress(); JSONObject jsonObject = new JSONObject(); try { jsonObject.put(MusicMergeConfig.OFFSET_KEY, currentOffsetValue); jsonObject.put(MusicMergeConfig.ORIGINALVOLUME_KEY, originalVolume); jsonObject.put(MusicMergeConfig.ACCOMPANYVOLUME_KEY, accompanyVolume); return jsonObject.toString(); } catch (JSONException e) { e.printStackTrace(); } return ""; } public void setEventListener(OnEventListener eventListener) { mEventListener = eventListener; } public void applyConfig(String jsonConfig) { try { JSONObject jsonObject = new JSONObject(jsonConfig); int offset = jsonObject.optInt(MusicMergeConfig.OFFSET_KEY, 0); int originalVolume = jsonObject.optInt(MusicMergeConfig.ORIGINALVOLUME_KEY, 100); int accompanyVolume = jsonObject.optInt(MusicMergeConfig.ACCOMPANYVOLUME_KEY, 100); int progressFromOffsetValue = getProgressFromOffsetValue(offset); mViewBinding.seekBarOffset.setProgress(progressFromOffsetValue); mViewBinding.seekVolume.setProgress(originalVolume); mViewBinding.seekVolume2.setProgress(accompanyVolume); mViewBinding.tvRecord.setVisibility(View.GONE); } catch (Exception e) { e.printStackTrace(); } } public void setAccompanyUrl(String accompanyUrl) { this.accompanyUrl = accompanyUrl; } public interface OnEventListener { void onVolumeChange(int type, float value); void onOffsetValueChange(int value); void toMix(int offsetValue, float volume1, float volume2, boolean isNeedNotify); void hideSetting(); void saveDraft(); } @Override public void onDestroy() { removeCallBack(mViewBinding.tvRecordVolumeValue, mRunnable); removeCallBack(mViewBinding.tvAccompanyVolumeValue, mRunnable2); super.onDestroy(); } private void removeCallBack(View view, Runnable runnable) { Handler handler = view.getHandler(); if (handler != null) { handler.removeCallbacks(runnable); } } }