首页 > 系统 > Android > 正文

Android实现简易版弹钢琴效果

2019-12-12 00:11:40
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android实现弹钢琴效果展示的具体代码,供大家参考,具体内容如下

目标效果:

1.drawable下新建button_selector.xml页面:

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">  <item android:drawable="@drawable/button_pressed" android:state_pressed="true"></item> <item android:drawable="@drawable/button"></item> </selector>

2.drawable下新建button.xml页面:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" >  <corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" > </corners>  <stroke android:width="2dp" android:color="#605C59" />  <gradient android:angle="270" android:endColor="#FFFFFF" android:startColor="#F5F5F5" /> </shape>

3.drawable下新建button_pressed.xml页面:

<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android" >  <solid android:color="#A4A4A4" />  <corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" > </corners>  <stroke android:width="2dp" android:color="#605C59" /> </shape>

4.新建PanioMusic.java类

package com.example.weixu.view; /** * 音乐播放帮助类 */ import java.util.HashMap;import android.content.Context;import android.media.AudioManager;import android.media.SoundPool; import com.example.weixu.playpanio.R; public class PanioMusic { // 资源文件 int Music[] = {R.raw.do1, 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 PanioMusic(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(); }}

5.activity_main.xml页面:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/llparent" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" >  <LinearLayout android:id="@+id/llKeys" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="5" android:orientation="horizontal" android:padding="10dp" >  <Button android:id="@+id/btPanioOne" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="1" />  <Button android:id="@+id/btPanioTwo" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="2" />  <Button android:id="@+id/btPanioThree" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="3" />  <Button android:id="@+id/btPanioFour" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="4" />  <Button android:id="@+id/btPanioFive" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="5" />  <Button android:id="@+id/btPanioSix" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="6" />  <Button android:id="@+id/btPanioSeven" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:background="@drawable/button" android:text="7" /> </LinearLayout> </LinearLayout>

6.MainActivity.java页面:

package com.example.weixu.playpanio; 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.weixu.view.PanioMusic; public class MainActivity extends Activity { private Button button[];// 按钮数组 private PanioMusic 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.llparent); 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]) {// 在某个按键范围内   button[temp]   .setBackgroundResource(R.drawable.button_pressed);   // 播放音阶   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) {// 移入的按键没有按下   // 设置当前按键   button[i]    .setBackgroundResource(R.drawable.button_pressed);   // 发音   utils.soundPlay(i);   havePlayed[i] = true;   }    pressedkey[count] = i;    if (!laststill) {// 没有手指按在上面   // 设置上一个按键   button[temp]    .setBackgroundResource(R.drawable.button);   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) {// 已经没有手指按在该键上   button[temp]   .setBackgroundResource(R.drawable.button);   havePlayed[temp] = false;   Log.i("--", "button" + temp + "up");   }   break;  }  }  }  //  if (event.getActionMasked() == MotionEvent.ACTION_MOVE  && !moveflag) {  if (pressedkey[count] != -1) {  button[pressedkey[count]]   .setBackgroundResource(R.drawable.button);  havePlayed[pressedkey[count]] = false;  }  } } return false; } });  keys = (View) findViewById(R.id.llKeys); }  private void init() { // 新建工具类 utils = new PanioMusic(getApplicationContext());  // 按钮资源Id buttonId = new int[7]; buttonId[0] = R.id.btPanioOne; buttonId[1] = R.id.btPanioTwo; buttonId[2] = R.id.btPanioThree; buttonId[3] = R.id.btPanioFour; buttonId[4] = R.id.btPanioFive; buttonId[5] = R.id.btPanioSix; buttonId[6] = R.id.btPanioSeven;  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; }}

7.AndroidManifest.xml页面对某个Activity页面进行设置横屏

android:screenOrientation="landscape"

8.另外,每个按键的音效需要提前导入res下raw文件夹中。

源码:点击打开链接

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表