欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现简易版弹钢琴效果

程序员文章站 2023-10-22 16:37:34
本文实例为大家分享了android实现弹钢琴效果展示的具体代码,供大家参考,具体内容如下 目标效果: 1.drawable下新建button_selector.xm...

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

目标效果:

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文件夹中。

源码:点击打开链接

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