• Android实现简易版弹钢琴效果


    Android实现简易版弹钢琴效果

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

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

    在这里插入图片描述

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

    • 整个钢琴实现的效果图

    在这里插入图片描述

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

    在这里插入图片描述

    在这里插入图片描述

    • 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_46153949/12536768

    欢迎查阅
  • 相关阅读:
    C ------ 标准函数介绍
    socket编程 ------ 建立 TCP 服务器和客户端流程(阻塞方式)
    TCP ------ keep-alive
    ARM指令集、Thumb指令集、Thumb-2指令集
    poj万人题
    Codeforces Round #273 (Div. 2)
    bnuoj 34990(后缀数组 或 hash+二分)
    hdu4691(后缀数组)
    simpson公式求定积分(模板)
    acdream1415(dij+优先队列+桥)
  • 原文地址:https://www.cnblogs.com/gh110/p/13167382.html
Copyright © 2020-2023  润新知