Android-简易版弹钢琴

来源:互联网 发布:故宫淘宝店叫什么名 编辑:程序博客网 时间:2024/05/01 04:36

目标效果:

 

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 0