소스 검색

增加节拍器节拍UI逻辑

Pq 2 년 전
부모
커밋
374bf70503

+ 1 - 0
BaseLibrary/src/main/res/values/colors.xml

@@ -144,6 +144,7 @@
     <color name="color_f37c17">#F37C17</color>
     <color name="color_10a0a0a0">#10A0A0A0</color>
     <color name="color_102dc7aa">#102dc7aa</color>
+    <color name="color_502dc7aa">#502dc7aa</color>
 
     <color name="color_25292e">#25292E</color>
     <color name="color_F8F8F8">#F8F8F8</color>

+ 128 - 8
metronome/src/main/java/com/cooleshow/metronome/MetronomeActivity.java

@@ -1,7 +1,5 @@
 package com.cooleshow.metronome;
 
-import androidx.viewbinding.ViewBinding;
-
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Color;
@@ -12,21 +10,32 @@ import android.os.Bundle;
 import android.os.Handler;
 import android.util.Log;
 import android.view.View;
+import android.widget.TextView;
 
+import com.bigkoo.pickerview.builder.OptionsPickerBuilder;
+import com.bigkoo.pickerview.view.OptionsPickerView;
 import com.cooleshow.base.ui.activity.BaseActivity;
+import com.cooleshow.metronome.adapter.MetronomeAdapter;
 import com.cooleshow.metronome.constants.MetronomeConfig;
 import com.cooleshow.metronome.constants.MetronomeType;
 import com.cooleshow.metronome.databinding.ActivityMetronomeLayoutBinding;
 import com.cooleshow.metronome.widget.CircularSeekBar;
 
-public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBinding> {
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBinding> implements View.OnClickListener {
     public MetronomeType currentBeatType;
     public int currentBeatRate = MetronomeConfig.DEFAULT_PLAY_RATE;
     private SoundPool soundPool;
     private int tickVoiceId;
     private int tockVoiceId;
-
-    public int playPosition = 0;
+    private OptionsPickerView pvOptions;
+    private int playPosition = 0;
+    private boolean isPlaying = false;
     private Handler mHandler = new Handler();
     private Runnable mRunnable = new Runnable() {
         @Override
@@ -38,10 +47,23 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
             } else {
                 soundPool.play(tockVoiceId, 1F, 1F, 0, 0, 1F);
             }
+            if (mMetronomeAdapter != null) {
+                mMetronomeAdapter.notifyData(playPosition);
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        //实现闪烁动画效果
+                        mMetronomeAdapter.notifyData(MetronomeAdapter.DEFAULT_SELECT_POSITION);
+                    }
+                }, delayMillis / 2);
+            }
             playPosition++;
             mHandler.postDelayed(mRunnable, delayMillis);
         }
     };
+    private List<MetronomeType> beatSymbolLists;
+    private int currentSelectPosition;
+    private MetronomeAdapter mMetronomeAdapter;
 
     public static void start(Context context) {
         Intent intent = new Intent(context, MetronomeActivity.class);
@@ -56,8 +78,6 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
     @Override
     protected void initView() {
         viewBinding.toolbarInclude.toolbar.setBackgroundColor(Color.TRANSPARENT);
-        currentBeatType = MetronomeType.METRONOME_44_TYPE;
-        viewBinding.tvCurrentBeat.setText(currentBeatType.getName());
         viewBinding.tvSpeed.setText(String.valueOf(currentBeatRate));
     }
 
@@ -66,11 +86,61 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
         return ActivityMetronomeLayoutBinding.inflate(getLayoutInflater());
     }
 
+    private void setBeat(MetronomeType metronomeType) {
+        currentBeatType = metronomeType;
+        viewBinding.tvCurrentBeat.setText(metronomeType.getName());
+        playPosition = 0;
+        mMetronomeAdapter.notifyData(MetronomeAdapter.DEFAULT_SELECT_POSITION);
+        mMetronomeAdapter.setCount(getBeatSymbolCount());
+    }
+
+    private int getBeatSymbolCount() {
+        int value = currentBeatType.getValue();
+        if (value == MetronomeType.METRONOME_12_TYPE.getValue()
+                || value == MetronomeType.METRONOME_14_TYPE.getValue()) {
+            return 1;
+        }
+
+        if (value == MetronomeType.METRONOME_22_TYPE.getValue()
+                || value == MetronomeType.METRONOME_24_TYPE.getValue()) {
+            return 2;
+        }
+
+        if (value == MetronomeType.METRONOME_34_TYPE.getValue()
+                || value == MetronomeType.METRONOME_38_TYPE.getValue()) {
+            return 3;
+        }
+
+        if (value == MetronomeType.METRONOME_44_TYPE.getValue()) {
+            return 4;
+        }
+
+        if (value == MetronomeType.METRONOME_68_TYPE.getValue()) {
+            return 6;
+        }
+        return 0;
+    }
+
     @Override
     protected void initData() {
         super.initData();
+        mMetronomeAdapter = new MetronomeAdapter();
+        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
+        viewBinding.recyclerView.setLayoutManager(linearLayoutManager);
+        viewBinding.recyclerView.setAdapter(mMetronomeAdapter);
+        //set default
+        setBeat(MetronomeType.METRONOME_44_TYPE);
         initListener();
         mteronomeSoundPool();
+        beatSymbolLists = new ArrayList<>();
+        beatSymbolLists.add(MetronomeType.METRONOME_12_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_22_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_14_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_24_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_34_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_44_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_38_TYPE);
+        beatSymbolLists.add(MetronomeType.METRONOME_68_TYPE);
     }
 
     private void play() {
@@ -78,6 +148,16 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
         soundPool.stop(tickVoiceId);
         soundPool.stop(tockVoiceId);
         mHandler.post(mRunnable);
+        isPlaying = true;
+        viewBinding.tvPlay.setText(getString(R.string.pause_play_str));
+    }
+
+    private void pausePlay() {
+        mHandler.removeCallbacksAndMessages(null);
+        soundPool.stop(tickVoiceId);
+        soundPool.stop(tockVoiceId);
+        isPlaying = false;
+        viewBinding.tvPlay.setText(getString(R.string.play_str));
     }
 
     private void mteronomeSoundPool() {
@@ -101,10 +181,15 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
     private int lastProgress = 0;
 
     private void initListener() {
+        viewBinding.ivBeatValue.setOnClickListener(this);
         viewBinding.tvPlay.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                play();
+                if (isPlaying) {
+                    pausePlay();
+                } else {
+                    play();
+                }
             }
         });
         viewBinding.cirSeekbar.setSeekBarChangeListener(new CircularSeekBar.OnSeekChangeListener() {
@@ -175,6 +260,32 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
         }
     }
 
+    private void selectSymbols() {
+        pvOptions = new OptionsPickerBuilder(this, (options1, options2, options3, v) -> {
+            this.currentSelectPosition = options1;
+            MetronomeType metronomeType = beatSymbolLists.get(currentSelectPosition);
+            viewBinding.tvCurrentBeat.setText(metronomeType.getName());
+            setBeat(metronomeType);
+            pausePlay();
+        }).setTitleText("拍号").setTitleColor(Color.BLACK).setLayoutRes(R.layout.pickerview_beat_symbol_layout, v -> {
+            //自定义布局中的控件初始化及事件处理
+            final TextView tvSubmit = (TextView) v.findViewById(com.cooleshow.base.R.id.tv_finish);
+            TextView ivCancel = (TextView) v.findViewById(com.cooleshow.base.R.id.tv_cancel);
+            tvSubmit.setOnClickListener(v12 -> {
+                pvOptions.returnData();
+                pvOptions.dismiss();
+            });
+            ivCancel.setOnClickListener(v1 -> pvOptions.dismiss());
+
+        }).isDialog(false).build();
+        pvOptions.setPicker(beatSymbolLists);
+        if (currentSelectPosition < beatSymbolLists.size()) {
+            pvOptions.setSelectOptions(currentSelectPosition);
+        }
+        pvOptions.show();
+
+    }
+
 
     @Override
     public void onDestroy() {
@@ -187,4 +298,13 @@ public class MetronomeActivity extends BaseActivity<ActivityMetronomeLayoutBindi
 
         }
     }
+
+    @Override
+    public void onClick(View v) {
+        int id = v.getId();
+        if (id == R.id.iv_beat_value) {
+            selectSymbols();
+            return;
+        }
+    }
 }

+ 63 - 0
metronome/src/main/java/com/cooleshow/metronome/adapter/MetronomeAdapter.java

@@ -0,0 +1,63 @@
+package com.cooleshow.metronome.adapter;
+
+import android.util.Log;
+import android.view.View;
+
+import com.chad.library.adapter.base.BaseQuickAdapter;
+import com.chad.library.adapter.base.viewholder.BaseViewHolder;
+import com.cooleshow.metronome.R;
+import com.cooleshow.metronome.bean.BeatBean;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Author by pq, Date on 2022/9/19.
+ */
+public class MetronomeAdapter extends BaseQuickAdapter<BeatBean, BaseViewHolder> {
+    public static final int DEFAULT_SELECT_POSITION=-1;
+    private int selectPosition = DEFAULT_SELECT_POSITION;
+    private int count = 0;
+
+    public MetronomeAdapter() {
+        super(R.layout.item_beat_symbol_layout);
+    }
+
+    @Override
+    protected void convert(@NonNull BaseViewHolder holder, BeatBean bean) {
+        View view_first = holder.getView(R.id.view_first);
+        View view_other = holder.getView(R.id.view_other);
+        int position = holder.getLayoutPosition();
+        view_first.setVisibility(position == 0 ? View.VISIBLE : View.GONE);
+        view_other.setVisibility(position == 0 ? View.GONE : View.VISIBLE);
+        if (position == selectPosition) {
+            view_first.setBackgroundResource(R.drawable.shape_2dc7aa_beat_select);
+            view_other.setBackgroundResource(R.drawable.shape_2dc7aa_beat_select);
+        } else {
+            view_first.setBackgroundResource(R.drawable.shape_2dc7aa_beat_normal);
+            view_other.setBackgroundResource(R.drawable.shape_2dc7aa_beat_normal);
+        }
+    }
+
+    public void setCount(int count) {
+        this.count = count;
+        Log.i("pq", "count:" + count);
+        ArrayList<BeatBean> arrayList = new ArrayList();
+        for (int i = 0; i < count; i++) {
+            arrayList.add(new BeatBean());
+        }
+        setList(arrayList);
+    }
+
+
+    public void notifyData(int selectPosition) {
+        Log.i("pq", "position:" + selectPosition);
+        int defItemCount = getDefItemCount();
+        Log.i("pq", "defItemCount:" + defItemCount);
+        this.selectPosition = selectPosition != -1 ? selectPosition % defItemCount : -1;
+        Log.i("pq", "selectPosition:" + this.selectPosition);
+        notifyDataSetChanged();
+    }
+}

+ 7 - 0
metronome/src/main/java/com/cooleshow/metronome/bean/BeatBean.java

@@ -0,0 +1,7 @@
+package com.cooleshow.metronome.bean;
+
+/**
+ * Author by pq, Date on 2022/9/19.
+ */
+public class BeatBean {
+}

+ 1 - 1
metronome/src/main/java/com/cooleshow/metronome/constants/MetronomeConfig.java

@@ -8,6 +8,6 @@ public class MetronomeConfig {
     public static final int MIN_PLAY_RATE = 50;//最小播放速度
     public static final int MAX_PLAY_RATE = 200;//最大播放速度
     public static final int PLAY_RATE_UNIT = 10;//10个进度 +1或者-1速度
-    public static String rhythns[] = {"1/2", "2/2", "1/4", "2/4", "3/4", "4/4", "3/8", "6/8"};
+    public static String RHYTHNS[] = {"1/2", "2/2", "1/4", "2/4", "3/4", "4/4", "3/8", "6/8"};
 
 }

+ 8 - 1
metronome/src/main/java/com/cooleshow/metronome/constants/MetronomeType.java

@@ -1,9 +1,11 @@
 package com.cooleshow.metronome.constants;
 
+import com.contrarywind.interfaces.IPickerViewData;
+
 /**
  * Author by pq, Date on 2022/9/16.
  */
-public enum MetronomeType {
+public enum MetronomeType implements IPickerViewData {
     METRONOME_12_TYPE(0, "1/2"),
     METRONOME_22_TYPE(1, "2/2"),
     METRONOME_14_TYPE(2, "1/4"),
@@ -42,4 +44,9 @@ public enum MetronomeType {
 
         return METRONOME_14_TYPE;
     }
+
+    @Override
+    public String getPickerViewText() {
+        return  this.name ;
+    }
 }

+ 5 - 0
metronome/src/main/res/drawable/shape_2dc7aa_beat_normal.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="@color/color_502dc7aa"/>
+</shape>

+ 5 - 0
metronome/src/main/res/drawable/shape_2dc7aa_beat_select.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="@color/color_2dc7aa"/>
+</shape>

+ 28 - 15
metronome/src/main/res/layout/activity_metronome_layout.xml

@@ -11,6 +11,19 @@
         android:id="@+id/toolbar_include"
         layout="@layout/common_toolbar_layout" />
 
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/recyclerView"
+        android:layout_width="wrap_content"
+        android:layout_height="21dp"
+        android:layout_marginStart="13dp"
+        android:layout_marginTop="22dp"
+        android:layout_marginEnd="13dp"
+        android:overScrollMode="never"
+        android:scrollbars="none"
+        app:layout_constraintLeft_toLeftOf="parent"
+        app:layout_constraintRight_toRightOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/toolbar_include" />
+
     <ImageView
         android:id="@+id/iv_plate"
         android:layout_width="300dp"
@@ -23,9 +36,9 @@
         app:layout_constraintTop_toBottomOf="@+id/toolbar_include" />
 
     <com.cooleshow.metronome.widget.CircularSeekBar
+        android:id="@+id/cir_seekbar"
         android:layout_width="220dp"
         android:layout_height="220dp"
-        android:id="@+id/cir_seekbar"
         app:layout_constraintBottom_toBottomOf="@+id/iv_plate"
         app:layout_constraintLeft_toLeftOf="@+id/iv_plate"
         app:layout_constraintRight_toRightOf="@+id/iv_plate"
@@ -36,10 +49,10 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:includeFontPadding="false"
+        android:text="136"
         android:textColor="@color/color_333333"
         android:textSize="@dimen/sp_40"
         android:textStyle="bold"
-        android:text="136"
         app:layout_constraintBottom_toBottomOf="@+id/iv_plate"
         app:layout_constraintLeft_toLeftOf="@+id/iv_plate"
         app:layout_constraintRight_toRightOf="@+id/iv_plate"
@@ -69,13 +82,13 @@
         app:layout_constraintTop_toBottomOf="@+id/iv_plate" />
 
     <ImageView
-        app:layout_constraintRight_toRightOf="@+id/iv_reduce"
-        app:layout_constraintLeft_toLeftOf="@+id/iv_reduce"
-        app:layout_constraintBottom_toBottomOf="@+id/iv_reduce"
-        app:layout_constraintTop_toTopOf="@+id/iv_reduce"
-        android:src="@mipmap/icon_reduce_symbol"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
+        android:layout_height="wrap_content"
+        android:src="@mipmap/icon_reduce_symbol"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_reduce"
+        app:layout_constraintLeft_toLeftOf="@+id/iv_reduce"
+        app:layout_constraintRight_toRightOf="@+id/iv_reduce"
+        app:layout_constraintTop_toTopOf="@+id/iv_reduce" />
 
     <ImageView
         android:id="@+id/iv_beat_value"
@@ -96,22 +109,22 @@
         app:layout_constraintTop_toTopOf="@+id/iv_reduce" />
 
     <ImageView
-        app:layout_constraintRight_toRightOf="@+id/iv_add"
-        app:layout_constraintLeft_toLeftOf="@+id/iv_add"
-        app:layout_constraintBottom_toBottomOf="@+id/iv_add"
-        app:layout_constraintTop_toTopOf="@+id/iv_add"
-        android:src="@mipmap/icon_add_symbol"
         android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
+        android:layout_height="wrap_content"
+        android:src="@mipmap/icon_add_symbol"
+        app:layout_constraintBottom_toBottomOf="@+id/iv_add"
+        app:layout_constraintLeft_toLeftOf="@+id/iv_add"
+        app:layout_constraintRight_toRightOf="@+id/iv_add"
+        app:layout_constraintTop_toTopOf="@+id/iv_add" />
 
     <TextView
         android:id="@+id/tv_current_beat"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:includeFontPadding="false"
+        android:text="6/4"
         android:textColor="@color/color_1a1a1a"
         android:textSize="@dimen/sp_16"
-        android:text="6/4"
         app:layout_constraintBottom_toBottomOf="@+id/iv_beat_value"
         app:layout_constraintLeft_toLeftOf="@+id/iv_beat_value"
         app:layout_constraintRight_toRightOf="@+id/iv_beat_value"

+ 23 - 0
metronome/src/main/res/layout/item_beat_symbol_layout.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="21dp"
+    android:layout_height="21dp"
+    android:layout_marginStart="5dp"
+    android:layout_marginEnd="5dp">
+
+    <View
+        android:visibility="gone"
+        android:id="@+id/view_first"
+        android:layout_width="21dp"
+        android:layout_height="21dp"
+        android:layout_gravity="center"
+        android:background="@drawable/shape_2dc7aa_beat_normal" />
+
+    <View
+        android:id="@+id/view_other"
+        android:layout_width="17dp"
+        android:layout_height="17dp"
+        android:layout_gravity="center"
+        android:background="@drawable/shape_2dc7aa_beat_normal"
+        android:visibility="visible" />
+</FrameLayout>

+ 76 - 0
metronome/src/main/res/layout/pickerview_beat_symbol_layout.xml

@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="@drawable/bg_white_top_10dp"
+    android:orientation="vertical">
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="50dp">
+
+
+        <TextView
+            android:id="@+id/tv_cancel"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="17dp"
+            android:text="取消"
+            android:textColor="@color/color_999999"
+            android:textSize="@dimen/dp_16" />
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerInParent="true"
+            android:text=""
+            android:textColor="@color/color_1a1a1a"
+            android:textSize="18dp" />
+
+        <TextView
+            android:id="@+id/tv_finish"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:layout_marginRight="17dp"
+            android:padding="8dp"
+            android:text="确定"
+            android:textColor="@color/colorPrimary"
+            android:textSize="@dimen/dp_16" />
+
+    </RelativeLayout>
+
+    <View style="@style/line_style" />
+    <!--此部分需要完整复制过去,删减或者更改ID会导致初始化找不到内容而报空-->
+    <LinearLayout
+        android:id="@+id/optionspicker"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/dp_200"
+        android:background="#ffffff"
+        android:gravity="center"
+        android:minHeight="150dp"
+        android:orientation="horizontal">
+
+        <com.contrarywind.view.WheelView
+            android:id="@+id/options1"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <com.contrarywind.view.WheelView
+            android:id="@+id/options2"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+
+        <com.contrarywind.view.WheelView
+            android:id="@+id/options3"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+    </LinearLayout>
+
+
+</LinearLayout>

+ 2 - 0
metronome/src/main/res/values/strings.xml

@@ -1,2 +1,4 @@
 <resources>
+    <string name="pause_play_str">暂停</string>
+    <string name="play_str">播放</string>
 </resources>