安卓弹钢琴的软件叫啥_如何在手机上弹奏钢琴

(45) 2024-08-12 10:01:05

Android实现简易版弹钢琴效果

参考于:https://www.jb51.net/article/161904.htm

最近由于要写Android的期末报告,老师让写一个类似于钢琴的小程序, 但对深受网课熏陶的我来说,嗯!!! 这是个大问题,一学期快结束了,课没怎么听,回放还没有???这作业怎么写??? 于是,百度出现了,百度是真的香!!! 虽然,他广告多,还收费,链接假……但他实用!!! 嗯,不会写作业 ???问度娘就好了。于是参考了上面链接的东西。 说实话,第一遍看,没怎么看懂!! 确实,毕竟没听课嘛,也不为过,都是这考试的错,毕竟量劫来袭,贫道闭关静颂黄庭! 不怨我!毕竟家里网不好,住在山沟沟里……反正各种理由就是不想上网课。 但是要写作业,毕竟不想挂科!!! 

安卓弹钢琴的软件叫啥_如何在手机上弹奏钢琴 (https://mushiming.com/)  第1张

好了,终止废话。干货如下:

  • 整个钢琴实现的效果图

安卓弹钢琴的软件叫啥_如何在手机上弹奏钢琴 (https://mushiming.com/)  第2张

  • 整个APP的整体框架!!!!!这里很重要!!!!

安卓弹钢琴的软件叫啥_如何在手机上弹奏钢琴 (https://mushiming.com/)  第3张

安卓弹钢琴的软件叫啥_如何在手机上弹奏钢琴 (https://mushiming.com/)  第4张

  • 1.新建activity_main.xml文件源码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/parents" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/background"> <LinearLayout android:id="@+id/llKeys" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="5" android:layout_alignParentBottom="true" android:orientation="horizontal" android:padding="10dp" > <Button android:id="@+id/iv_do" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_do" /> <Button android:id="@+id/iv_re" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_re" /> <Button android:id="@+id/iv_mi" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_mi"/> <Button android:id="@+id/iv_fa" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_fa"/> <Button android:id="@+id/iv_so" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_so"/> <Button android:id="@+id/iv_la" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_la" /> <Button android:id="@+id/iv_si" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/icon_si"/> </LinearLayout> </RelativeLayout> 
  • 2.新建PanioMusic.java文件
/** * 音乐播放工具类 */ import java.util.HashMap; import android.content.Context; import android.media.AudioManager; import android.media.SoundPool; import com.example.pinao.R; public class Pinao { 
    // 资源文件 int Music[] = { 
   R.raw.dol, R.raw.re2, R.raw.mi3, R.raw.fa4, R.raw.sol5, R.raw.la6, R.raw.si7,}; SoundPool soundPool; HashMap<Integer, Integer> soundPoolMap; public Pinao(Context context) { 
    soundPool = new SoundPool(2, AudioManager.STREAM_MUSIC, 100); soundPoolMap = new HashMap<Integer, Integer>(); for (int i = 0; i < Music.length; i++) { 
    soundPoolMap.put(i, soundPool.load(context, Music[i], 1)); } } public int soundPlay(int no) { 
    return soundPool.play(soundPoolMap.get(no), 100, 100, 1, 0, 1.0f); } public int soundOver() { 
    return soundPool.play(soundPoolMap.get(1), 100, 100, 1, 0, 1.0f); } @Override protected void finalize() throws Throwable { 
    soundPool.release(); super.finalize(); } } 
  • 3.新建MainActivity.java文件
import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.widget.Button; import com.example.pinao.Pinao; public class MainActivity extends Activity { 
    private Button button[];// 按钮数组 private Pinao utils;// 工具类 private View parent;// 父视图 private int buttonId[];// 按钮id private boolean havePlayed[];// 是否已经播放了声音,当手指在同一个按钮内滑动,且已经发声,就为true private View keys;// 按钮们所在的视图 private int pressedkey[]; @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); parent = (View) findViewById(R.id.parents); parent.setClickable(true); parent.setOnTouchListener(new OnTouchListener() { 
    @Override public boolean onTouch(View v, MotionEvent event) { 
    int temp; int tempIndex; int pointercount; pointercount = event.getPointerCount(); for (int count = 0; count < pointercount; count++) { 
    boolean moveflag = false;// 标记是否是在按键上移动 temp = isInAnyScale(event.getX(count), event.getY(count), button); if (temp != -1) { 
   // 事件对应的是当前点 switch (event.getActionMasked()) { 
    case MotionEvent.ACTION_DOWN: // // 单独一根手指或最先按下的那个 // pressedkey = temp; case MotionEvent.ACTION_POINTER_DOWN: Log.i("--", "count" + count); pressedkey[count] = temp; if (!havePlayed[temp]) { 
   // 在某个按键范围内 // 播放音阶 utils.soundPlay(temp); Log.i("--", "sound" + temp); havePlayed[temp] = true; } break; case MotionEvent.ACTION_MOVE: temp = pressedkey[count]; for (int i = temp + 1; i >= temp - 1; i--) { 
    // 当在两端的按钮时,会有一边越界 if (i < 0 || i >= button.length) { 
    continue; } if (isInScale(event.getX(count), event.getY(count), button[i])) { 
   // 在某个按键内 moveflag = true; if (i != temp) { 
   // 在相邻按键内 boolean laststill = false; boolean nextstill = false; // 假设手指已经从上一个位置抬起,但是没有真的抬起,所以不移位 pressedkey[count] = -1; for (int j = 0; j < pointercount; j++) { 
    if (pressedkey[j] == temp) { 
    laststill = true; } if (pressedkey[j] == i) { 
    nextstill = true; } } if (!nextstill) { 
   // 移入的按键没有按下 // 发音 utils.soundPlay(i); havePlayed[i] = true; } pressedkey[count] = i; if (!laststill) { 
   // 没有手指按在上面 havePlayed[temp] = false; } break; } } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: // 事件与点对应 tempIndex = event.getActionIndex(); if (tempIndex == count) { 
    Log.i("--", "index" + tempIndex); boolean still = false; // 当前点已抬起 for (int t = count; t < 5; t++) { 
    if (t != 4) { 
    if (pressedkey[t + 1] >= 0) { 
    pressedkey[t] = pressedkey[t + 1]; } else { 
    pressedkey[t] = -1; } } else { 
    pressedkey[t] = -1; } } for (int i = 0; i < pressedkey.length; i++) { 
   // 是否还有其他点 if (pressedkey[i] == temp) { 
    still = true; break; } } if (!still) { 
   // 已经没有手指按在该键上 havePlayed[temp] = false; Log.i("--", "button" + temp + "up"); } break; } } } // if (event.getActionMasked() == MotionEvent.ACTION_MOVE && !moveflag) { 
    if (pressedkey[count] != -1) { 
    havePlayed[pressedkey[count]] = false; } } } return false; } }); keys = (View) findViewById(R.id.llKeys); } private void init() { 
    // 新建工具类 utils = new Pinao(getApplicationContext()); // 按钮资源Id buttonId = new int[7]; buttonId[0] = R.id.iv_do; buttonId[1] = R.id.iv_re; buttonId[2] = R.id.iv_mi; buttonId[3] = R.id.iv_fa; buttonId[4] = R.id.iv_so; buttonId[5] = R.id.iv_la; buttonId[6] = R.id.iv_si; button = new Button[7]; havePlayed = new boolean[7]; // 获取按钮对象 for (int i = 0; i < button.length; i++) { 
    button[i] = (Button) findViewById(buttonId[i]); button[i].setClickable(false); havePlayed[i] = false; } pressedkey = new int[5]; for (int j = 0; j < pressedkey.length; j++) { 
    pressedkey[j] = -1; } } /** * 判断某个点是否在某个按钮的范围内 * * @param x 横坐标 * @param y 纵坐标 * @param button 按钮对象 * @return 在:true;不在:false */ private boolean isInScale(float x, float y, Button button) { 
    // keys.getTop()是获取按钮所在父视图相对其父视图的右上角纵坐标 if (x > button.getLeft() && x < button.getRight() && y > button.getTop() + keys.getTop() && y < button.getBottom() + keys.getTop()) { 
    return true; } else { 
    return false; } } /** * 判断某个点是否在一个按钮集合中的某个按钮内 * * @param x 横坐标 * @param y 纵坐标 * @param button 按钮数组 * @return */ private int isInAnyScale(float x, float y, Button[] button) { 
    // keys.getTop()是获取按钮所在父视图相对其父视图的右上角纵坐标 for (int i = 0; i < button.length; i++) { 
    if (x > button[i].getLeft() && x < button[i].getRight() && y > button[i].getTop() + keys.getTop() && y < button[i].getBottom() + keys.getTop()) { 
    return i; } } return -1; } } 

以上就是全部源码文件!!!

  • 至于相关的音频素材可自行百度获取。

  • 源码文件素材地址:https://download.csdn.net/download/m0_/

THE END

发表回复