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

源码:点击打开链接

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

(0)

相关推荐

  • Android使用Handler实现打地鼠游戏

    本文实例为大家分享了Android使用Handler实现打地鼠的具体代码,供大家参考,具体内容如下 1.实现效果 如下图所示: 2.代码实现 新建一个名为DiglettDemo的项目,activity_main.xml代码如下: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/a

  • 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:

  • Android实现简易版打地鼠

    本文实例为大家分享了Android实现简易版打地鼠的具体代码,供大家参考,具体内容如下 目标效果: 1.activity_main.xml页面: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schema

  • Android实现微博菜单弹出效果

    先上Android仿微博菜单弹出效果图,这个截图不是很流畅,大家可以下载apk试一下. 说一下实现思路: 1.截取当前窗口,对图片做高斯模糊处理,将处理后的图片做popupwindow的背景图片: 2.创建popupwindow,完成布局,这儿要注意:View的移动范围是由parent的大小决定的,就是只能在parent的范围内移动: 3.给买个View添加进入动画,每个比前一个延期50ms播放动画,关闭窗口时相反: 4.为View的动画添加回弹插值器: MoreWindow.java窗口 pa

  • Android仿Iphone屏幕底部弹出半透明PopupWindow效果

    本文实例为大家分享了Android仿Iphone屏幕底部弹出效果的具体代码,供大家参考,具体内容如下 main.xml如下: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent&

  • Android学习项目之简易版微信为例(二)

    1 概述 从这篇开始,正式进入简易版微信的开发.深入学习前,想谈谈个人对Android程序开发一些理解,不一定正确,只是自己的一点想法.Android程序开发不像我们在大学时候写C控制台程序那样,需要从main开始写代码逻辑,大部分逻辑控制代码都由自己来实现.事实上,Android已经为我们提供了一个程序运行的框架,我们只需要往框架中填入我们所需的内容即可,这里的内容主要是:四大组件--Activity.Service.ContentProvider.BroadCast.在这四大组件中,可以实现

  • Android编程实现popupwindow弹出后屏幕背景变成半透明效果

    本文实例讲述了Android编程实现popupwindow弹出后屏幕背景变成半透明效果的方法.分享给大家供大家参考,具体如下: android中popupwindow弹出后,屏幕背景变成半透明这个效果很普通.实现的方法也很多.我使用的可能是最简单的一种,就是设置一下getWindows的透明度.不多说上代码 /** * 设置添加屏幕的背景透明度 * @param bgAlpha */ public void backgroundAlpha(float bgAlpha) { WindowManag

  • Android学习项目之简易版微信为例(一)

    这是"Android学习之路"系列文章的开篇,可能会让大家有些失望--这篇文章中我们不介绍简易版微信的实现(不过不是标题党哦,我会在后续文章中一步步实现这个应用程序的).这里主要是和广大朋友们聊聊一个非Java程序员对Android操作系统的理解以及一个Android工程的目录结构,为进一步学习做准备. 1 缘起 智能手机的出现与普及为人们的生活.工作带来了极大的便利,我们可以用手机随时随地.随心所欲地购物.玩游戏.聊天.听音乐等等.一个个精心设计.体验良好的移动客户端应用,让用户们爱

  • Android自定义PopWindow带动画向下弹出效果

    本文实例为大家分享了PopWindow实现带动画向下弹出效果的具体代码,供大家参考,具体内容如下 首先建一个popwin的实体类 package dmpte.mytest; import android.content.Context; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.widget.PopupWindow; i

  • Android 实现抖音头像底部弹框效果的实例代码

    布局文件 activity_test.xml <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"

  • Android使用ViewBinding的详细步骤(Kotlin简易版)

    ViewBinding 是什么 2020年的3月份 巨佬 JakeWharton 开源的 butterknife 被官宣 停止维护,在github 上 说明 Attention: This tool is now deprecated. Please switch to view binding. Existing versions will continue to work, obviously, but only critical bug fixes for integration with

随机推荐