웹_프론트_백엔드/JAVA프레임윅기반_풀스택

2020.04.21

shine94 2020. 4. 21. 09:02

1. a014_dialog 모듈

1) Main2Activity 액티비티 activity_main2 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lec.android.a014_dialog">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".Main2Activity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MainActivity" />
    </application>

</manifest>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="AlertDialog"
        android:textAppearance="@style/TextAppearance.AppCompat.Display1" />

    <Button
        android:id="@+id/btnText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="다이얼로그 1 - 글자만" />

    <Button
        android:id="@+id/btnList"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="다이얼로그 2 - 리스트" />

    <Button
        android:id="@+id/btnRadio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="다이얼로그 3 - 라디오버튼" />

    <Button
        android:id="@+id/btnMultiChoice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="다이얼로그 4 - multi choice" />

    <TextView
        android:id="@+id/tvResult"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="결과값"
        android:textAppearance="@style/TextAppearance.AppCompat.Large" />

</LinearLayout>
package com.lec.android.a014_dialog;

import androidx.appcompat.app.AlertDialog;
//import android.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.DialogInterface;
import android.os.Bundle;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class Main2Activity extends AppCompatActivity {

    // 다이얼로그의 ID를 보기 좋은 상수로 선언해서 사용한다
    final int DIALOG_TEXT = 1;
    final int DIALOG_LIST = 2; // 리스트 형식의 다이얼로그 ID
    final int DIALOG_RADIO = 3; // 하나만 선택할 수 있는 다이얼로그 ID
    final int DIALOG_MULTICHOICE = 4;

    TextView tvResult;

    int choice = -1; // 라디오 버튼 선택 값

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        // AlertDialog : Dialog 를 상속받은 자식클래스로
        //          다이얼로그를 쉽게 만들수 있도록 지원해주고,
        //          Activity 라이프 사이클과 다이얼로그의 라이프사이클을
        //          맞춰줌

        tvResult = findViewById(R.id.tvResult);

        Button btnText = findViewById(R.id.btnText);
        Button btnList = findViewById(R.id.btnList);
        Button btnRadio = findViewById(R.id.btnRadio);
        Button btnMultiChoice = findViewById(R.id.btnMultiChoice);

        btnText.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showAlert(DIALOG_TEXT);
            }
        });

        btnList.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showAlert(DIALOG_LIST);
            }
        });

        btnRadio.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showAlert(DIALOG_RADIO);
            }
        });

        btnMultiChoice.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showAlert(DIALOG_MULTICHOICE);
            }
        });

    } // end onCreate()

    protected AlertDialog.Builder showAlert(int id) {

        switch (id) {
            case DIALOG_TEXT:
                AlertDialog.Builder builder1 =
                        new AlertDialog.Builder(this);

                builder1.setTitle("다이얼로그 제목임")
                        .setMessage("안녕들 하세요~?")
                        .setPositiveButton("긍정", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getApplicationContext(), "긍정", Toast.LENGTH_LONG).show();
                            }
                        })
                        .setNegativeButton("부정", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getApplicationContext(), "부정", Toast.LENGTH_LONG).show();
                            }
                        })
                        .setNeutralButton("중립", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getApplicationContext(), "중립", Toast.LENGTH_LONG).show();
                            }
                        });
                builder1.show();    // 다이얼로그 보이기
                return builder1;

            case DIALOG_LIST:
                AlertDialog.Builder builder2
                        = new AlertDialog.Builder(this);

                final String str[] = {"사과", "딸기", "수박", "배"};
                builder2.setTitle("리스트 형식 다이얼로그 제목")
                        .setNeutralButton("취소", null)
                        .setItems(str, // 리스트 목록에 사용할 배열
                                new DialogInterface.OnClickListener() {
                            // 리스트 아이템이 선택되었을때 호출되는 콜백
                            // which : 몇 번째 선택되었는지에 대한 값
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getApplicationContext(), "선택은 : " + str[which], Toast.LENGTH_LONG).show();
                            }
                        });
                builder2.show();
                return builder2;

            case DIALOG_RADIO:
                // 커스텀 스타일 적용. styles.xml 편집
                AlertDialog.Builder builder3
                        = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AlertDialogCustom));

                final String[] str2 = {"빨강", "녹색", "파랑"};
                builder3.setTitle("색을 고르세요")
                        .setPositiveButton("선택완료", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                Toast.makeText(getApplicationContext(), str2[choice] + "을 선택", Toast.LENGTH_LONG).show();

                            }
                        })
                        .setNeutralButton("취소", null)
                        .setSingleChoiceItems(
                                str2, // 리스트 배열 목록
                                -1, // 기본 설정값
                                new DialogInterface.OnClickListener() {
                                    // 라디오 버튼에서 선택했을때 호출되는 콜백
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        choice = which;
                                    }
                                }
                        );
                builder3.show();
                return builder3;

            case DIALOG_MULTICHOICE:
                AlertDialog.Builder builder4 =
                        new AlertDialog.Builder(this);

                final String[] data = {"한국", "북한", "소련", "영국"};
                final boolean[] checked = {true, false, true, false};

                builder4.setTitle("MultiChoice 다이얼로그 제목")
                        .setPositiveButton("선택완료", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                String str = "선택된 값은 : ";

                                for (int i = 0; i < checked.length; i++){
                                    if(checked[i]){
                                        str = str + data[i] + ", ";
                                    }
                                }

                                tvResult.setText(str);
                            }
                        })
                        .setNegativeButton("취소", null)
                        .setMultiChoiceItems(data, // 체크박스 리스트 항목 배열
                                checked, // 초기값(선택 여부) 배열
                                // 체크 박스 선택했을때 호출하는 콜백
                                new DialogInterface.OnMultiChoiceClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                                        checked[which] = isChecked;
                                    }
                                });
                builder4.show();
                return builder4;

        } // end switch

        return  null;
    }

} // end Activity

 

[추가] 커스텀 스타일 추가
 : res > values > styles.xml 편집

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <!-- AlertDialog 예제 스타일 -->
    <style name="AlertDialogCustom" parent="@android:style/Theme.Dialog">
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
        <item name="android:textSize">18sp</item>
    </style>

</resources>

 

3) Main3Activity 액티비티 activity_main3 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.lec.android.a014_dialog">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".Main3Activity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
        </activity>

        <activity android:name=".Main2Activity" />
        <activity android:name=".MainActivity" />
    </application>

</manifest>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="타임피커, 데이트피커"
        android:textAppearance="@style/TextAppearance.AppCompat.Display1" />

    <Button
        android:id="@+id/btnDatePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="날짜 선택" />

    <Button
        android:id="@+id/btnTimePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="시간 선택" />

</LinearLayout>
package com.lec.android.a014_dialog;

import androidx.appcompat.app.AppCompatActivity;

import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.TimePicker;
import android.widget.Toast;

public class Main3Activity extends AppCompatActivity {

    final int DIALOG_DATE = 1;
    final int DIALOG_TIME = 2;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        
        Button btnDatePicker = findViewById(R.id.btnDatePicker);
        Button btnTimePicker = findViewById(R.id.btnTimePicker);

        btnDatePicker.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showPickerDialog(DIALOG_DATE); // 날짜 설정 다이얼로그 띄우기
            }
        });

        btnTimePicker.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                showPickerDialog(DIALOG_TIME);
            }
        });

    } // end of onCreate

    protected Dialog showPickerDialog(int id) {

        switch (id) {
            case DIALOG_DATE:
                DatePickerDialog dpd = new DatePickerDialog(
                        this,   // 현재 화면의 제어권자

                        // 날짜 설정후 Dialog 빠져나올때 호출되는 콜백
                        new DatePickerDialog.OnDateSetListener(){
                            @Override
                            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                                Toast.makeText(getApplicationContext(),
                                        year + "년" + (month + 1) + "월" + dayOfMonth + "일 선택",
                                        Toast.LENGTH_LONG
                                        ).show();
                            }
                        },
                        2020, 4, 21 // 기본값 연월일
                );
                dpd.show();
                return dpd;

            case DIALOG_TIME:
                TimePickerDialog tpd =
                        new TimePickerDialog(this,
                                // 시간값 선택 후 호출되는 콜백
                                new TimePickerDialog.OnTimeSetListener() {
                                    @Override
                                    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                                        Toast.makeText(getApplicationContext(),
                                                hourOfDay + "시" + minute + "분 선택",
                                                Toast.LENGTH_LONG
                                        ).show();
                                    }
                                },
                                17, 21, false // 기본값 시, 분 등록
                                // is24HoursView
                                //  true : 24시간제 (0 ~ 23) 표시
                                //  false :  12시간제 (오전/오후) 항목 표시
                        );
                tpd.show();
                return tpd;
        }

        return null;
    } // end showPickerDialog()

} // end Activity

 

 

2. blockgame 게임 만들어서 구글 스토어에 앱출시하기

1) blockgame 모듈 만들기
[이때..!] 패키지명 매우 매우 중요, 중복된 패키지명이 있으면 등록 불가..!!
           주로 실무에서는 com.회사명으로 많이 시작함

2) MainActivity 액티비티, activity_main 레이아웃 생성했으나 이름 변경할 예정

** 액티비티 MainActivity를 Intro로 이름 변경

[추가] 변경된 액티비티명은 아래의 사진처럼 java 액티비아 리스트에서도 볼 수 있으나

         manifest에서도 확인할 수 있다

** 레이아웃 activity_main을 intro로 변경

3) 필요한 그림 다운로드
 : res > drawable로 복사해서 붙여 넣기

4) Main 액티비티, main 레이아웃 추가

5) 액션바(ActionBar) 제거하기

 : values > styles.xml에서 "Theme.AppCompat.Light.NoActionBar"로 수정하기

   (원래는 style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"로 되어 있음)

6) Start 액티비티, start 레이아웃 추가

7) HowToPaly 액티비티, howtoplay 레이아웃 추가

8) Info 액티비티, info 레이아웃 추가

9) btn_blue selector 만들기(버튼을 눌렀을때와 누르지 않았을때의 이미지 설정하기)

10) btn_red selector 만들기(버튼을 눌렀을때와 누르지 않았을때의 이미지 설정하기)

11) btn_green selector 만들기(버튼을 눌렀을때와 누르지 않았을때의 이미지 설정하기)

12) 음향 파일 추가하기

 : res 선택 후 우클릭 > New > Android Resource Directory > 이름과 타입을 raw으로 기재 > OK 클릭

> res 폴더 만들어지면 해당 폴더 클릭 후 필요한 음향 복사해서 붙여넣기

 

13) 구글 플레이 앱 등록하기

① 빌드 변형(Release 버전으로)

 : 해당 모듈 선택 후 Build > Select Build Variant... 클릭

> Build Variants 리스트에서 원하는 모듈의 Active Build Variant를 debug에서 release로 변경

> 변경된 모습...!!

② 앱에 서명(sign)하기(APK 방식) 

 : 서명할 모듈 클릭 후 Build > Generate Signed Bundle / APK 클릭
> Generate Signed Bundle or APK 창 뜨면 Next 클릭

> Create new... 클릭 > 아래의 그림처럼 작성 후 OK 클릭

> Next 클릭 > V1과 V2 체크 후 Finish 클릭

> 아래의 그림처럼 확인되면 API 방식의 서명이 된 것임..!!

③ 구글 플레이 콘솔
 : https://play.google.com/apps/publish 로 들어가서 앱 등록하기  

 

** 등록 방법은 워낙 구글 정책과 화면이 자주 변경되기 때문에 등록할때마다

    어떻게 등록하면 되는지 알아본 뒤에 등록하는 것이 좋다..!!

 

** 아래의 사진은 구글 플레이어에 검토 요청한 상태, 검토 후 실질적으로 구글 스토어에서 다운 받기가 가능해진다...!!

14) 소스 코드

** manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.gmail.every5116.binna940404.blockgame">

    <!-- 진동 권한 획득 -->
    <uses-permission android:name="android.permission.VIBRATE" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/btn_red_off"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".Info" android:screenOrientation="portrait"
            tools:ignore="LockedOrientationActivity" />

        <activity android:name=".HowToPaly" android:screenOrientation="portrait"
            tools:ignore="LockedOrientationActivity" />

        <activity android:name=".Start" android:screenOrientation="portrait"
            tools:ignore="LockedOrientationActivity" />

        <activity android:name=".Main" android:screenOrientation="portrait"
            tools:ignore="LockedOrientationActivity" />

        <activity
            android:name=".Intro"
            android:screenOrientation="portrait"
            tools:ignore="LockedOrientationActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


** Intro 액티비티

package com.gmail.every5116.binna940404.blockgame;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

// 현재 화면이 가로/세로 변경되지 않도록 지정하기
// AndroidManifest.xml 에 screenOrientation="portrait" 지정

// 액션바 없애기 -> styles.xml 에서 NoActionBar 지정
public class Intro extends AppCompatActivity {
    // 초기화면
    // 3초 동안 보이고, 다음 화면 (Main)으로 넘어가기

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.intro);

        Handler mHandler = new Handler() {
            @Override
            public void handleMessage(@NonNull Message msg) {
                Intent intent = new Intent(getApplicationContext(), Main.class);
                startActivity(intent);  // 화면 전환
                finish();   // intro 화면은 종료
            }
        };
        mHandler.sendEmptyMessageDelayed(1, 3000);

    } // end onCreate()

} // end Activity


** Main 액티비티

package com.gmail.every5116.binna940404.blockgame;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class Main extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button btnInfo = findViewById(R.id.btnInfo);
        Button btnStart = findViewById(R.id.btnStart);
        final Button btnHowto = findViewById(R.id.btnHowto);

        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {   // 게임 시작
                Intent intent = new Intent(getApplicationContext(), Start.class);
                startActivity(intent);
            }
        });

        btnHowto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {   // 게임방법 보기
                Intent intent = new Intent(getApplicationContext(), HowToPaly.class);
                startActivity(intent);
            }
        });

        btnInfo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {   // 정보 보기
                Intent intent = new Intent(getApplicationContext(), Info.class);
                startActivity(intent);
            }
        });

    } // end onCreate()

} // and Activity


** Start 액티비티

package com.gmail.every5116.binna940404.blockgame;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.DialogInterface;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Random;

public class Start extends AppCompatActivity implements View.OnClickListener{

    TextView tvTime;    // 시간표시
    TextView tvPoint;   // 점수표시

    int time = 30;  // 시간값
    int point = 0;  // 점수값

    // 블럭이미지 리소스 배열
    int[] img = {R.drawable.block_red, R.drawable.block_green, R.drawable.block_blue};

    // 떨어지는 블럭의 ImageView 배열 객체
    ImageView[] iv = new ImageView[8];  // iv[0] <-- null 값이 들어 있음, 8개 모두가 초기화가 됨..!!

    private Vibrator vibrator;  // 진동
    private SoundPool soundPool;    // 음향

    private int soundID_OK; // 음향 id : 블럭 맞추었을때
    private int soundID_Error;  // 음향 id :  블럭 못 맞추었을때

    private MediaPlayer mp; // 배경 음악

    final int DIALOG_TIMEOVER = 1;  // 다이얼로그 ID

    Handler handler = new Handler();    // 시간 흐르는 것

    // 게임진행 쓰레드
    class GameThread extends Thread {
        @Override
        public void run() {
            // 시간은 1초마다 다시 표시(업데이트)
            // Handler 사용하여 화면 UI 업데이트
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(time >= 0) {
                        tvTime.setText("시간: " + time);

                        if(time > 0) {
                            time--; // 1초 감소, 1초 후에 다시 run() 수행
                            handler.postDelayed(this, 1000);
                        } else {
                            // time -> 0 이 된 경우.
                            AlertDialog.Builder builder
                                    = new AlertDialog.Builder(Start.this);
                            builder.setTitle("타임아웃")
                                    .setMessage("점수: " + point)
                                    .setNegativeButton("그만하기", new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            finish();   // 현재 화면 종료. 메인 화면으로 가기
                                        }
                                    })
                                    .setPositiveButton("다시하기", new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            // 게임 리셋하고, 새 게임 시작
                                            time = 30;
                                            point = 0;
                                            tvTime.setText("시간: " + time);
                                            tvPoint.setText("점수: " + point);
                                            new GameThread().start();   // 새로운 게임 시작!
                                        }
                                    })
                                    .setCancelable(false);
                            builder.show();
                        } // end if

                    } // end if
                } // end run()
            }, 1000);   // 1초 후에 시간 표시
        } // end run()
    } // end class GameThread

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 상태바(status bar) 없애기, 반드시 setContentView() 앞에서 처리
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.start);

        // 레이아웃 객체(뷰) 초기화
        tvTime = findViewById(R.id.tvTime);
        tvPoint = findViewById(R.id.tvPoint);

        ImageView ivRed = findViewById(R.id.ivRed);
        ImageView ivGreen = findViewById(R.id.ivGreen);
        ImageView ivBlue = findViewById(R.id.ivBlue);

        iv[0] = findViewById(R.id.ivBlock1);
        iv[1] = findViewById(R.id.ivBlock2);
        iv[2] = findViewById(R.id.ivBlock3);
        iv[3] = findViewById(R.id.ivBlock4);
        iv[4] = findViewById(R.id.ivBlock5);
        iv[5] = findViewById(R.id.ivBlock6);
        iv[6] = findViewById(R.id.ivBlock7);
        iv[7] = findViewById(R.id.ivBlock8);

        // 게임 시작되면, 초기화, 랜덤으로 블럭의 색상 지정
        for (int i = 0; i < iv.length; i++) {
            // 0, 1, 2 <- red, green, blue
            int num = new Random().nextInt(3);  // 0, 1, 2 중의 랜덤 정수
            iv[i].setImageResource(img[num]);
            iv[i].setTag(num + ""); // 태그를 버튼의 색상 판단하기 위한 값으로 활용
        }

        // 점수 초기화
        point = 0;
        tvPoint.setText("점수 : " + point);

        // r, g, b 버튼의 이벤트 리스너 등록
        ivRed.setOnClickListener(this);
        ivGreen.setOnClickListener(this);
        ivBlue.setOnClickListener(this);

        // 시간 표시, 시간이 흘러야 함, 게임진행 쓰레드 시작하기기
        new GameThread().start();


    } // end nCreate()

    @Override
    public void onClick(View v) {
        // 버튼을 눌렀을때 호출되는 콜백
        // 블럭과 같은 색깔의 버튼이 눌렸는지 판별,
        // 같은 블럭이면 이미지 블럭 한칸씩 내려오기,
        // 맨 위에는 새로운 블럭 생성

        boolean isOK = false;   // 맞추었는지 판별 결과

        ImageView imageView = (ImageView) v;

        switch (imageView.getId()) {
            // 맨 아래 블럭 iv[7] 의 ImageView 의 색상과 일치하는 버튼인지 판정
            case R.id.ivRed:    // 빨간버튼 클릭시
                if("0".equals(iv[7].getTag().toString())) {isOK = true;}    // 빨강블럭의 tag 값 "0"
                break;
            case R.id.ivGreen:  // 초록버튼 클릭시
                if("1".equals(iv[7].getTag().toString())) {isOK = true;}    // 초록블럭의 tag 값 "1"
                break;
            case R.id.ivBlue:   // 파랑버튼 클릭시
                if("2".equals(iv[7].getTag().toString())) {isOK = true;}    // 파랑블럭의 tag 값 "2"
                break;
        } // end switch

        if(isOK) {  // 버튼 색깔을 맞추었다면..!

            // 위의 7개 블럭을 한 칸 아래로 이동, iv[i] -> iv[i + 1]
            for (int i = iv.length - 2; i >= 0; i--) {
                int num = Integer.parseInt(iv[i] .getTag().toString()); // "0", "1", "2"
                iv[i + 1].setImageResource(img[num]);   // i 아래쪽 블럭 이미지 업데이트
                iv[i + 1].setTag(num + ""); // i 아래쪽 블럭 tag 값 업데이트
            } // end for

            // 가장 위의 블럭(iv[0]) ImageView 는 랜덤으로 생성
            int num = new Random().nextInt(3);  // 0, 1, 2
            iv[0].setImageResource(img[num]);
            iv[0].setTag(num + "");

            // 진동 & 음향
            vibrator.vibrate(200);
            soundPool.play(soundID_OK, 1, 1, 0, 0, 1);

            // 점수올리기
            point++;
            tvPoint.setText("점수: " + point);

        } else {    // 버튼 색깔이 틀리다면..!

            // 진동 & 음향
            vibrator.vibrate(new long[] {20, 80, 20, 80, 20, 80}, -1);
            soundPool.play(soundID_Error, 1, 1, 0, 0, 1);

            // 점수 깍기
            point--;
            tvPoint.setText("점수: " + point);

        } // end if

    } // end onClick()

    @Override
    protected void onResume() {
        super.onResume();
        // 자원 획득

        // Vibrator 객체 얻어오기
        vibrator = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);

        // SoundPool 객체
        soundPool = new SoundPool.Builder().setMaxStreams(5).build();
        soundID_OK = soundPool.load(Start.this, R.raw.gun3, 1);
        soundID_Error = soundPool.load(Start.this, R.raw.error, 1);

        // MediaPlayer 객체, 배경음악 연주 시작
        mp = MediaPlayer.create(getApplicationContext(), R.raw.bgm);
        mp.setLooping(false);   // 반복 재생 안함
        mp.start(); // 배경음악 재생 시작
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 자원 해제
        if(mp != null) {
            mp.stop();
            mp.release();
        }
    }

} // end Activity


** HowToPaly 액티비티

package com.gmail.every5116.binna940404.blockgame;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class HowToPaly extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.howtopaly);

        Button btnBack = findViewById(R.id.btnBack);
        btnBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();   // 현재 화면 종료하고 이전 화면으로 돌아가기
            }
        });

    } // end onCreate()

} // end Activity


** Info 액티비티

package com.gmail.every5116.binna940404.blockgame;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class Info extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.info);

        Button btnBack = findViewById(R.id.btnBack);
        btnBack.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();   // 현재 화면 종료하고 이전 화면으로 돌아가기
            }
        });
    }
}


** intro 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Intro">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/intro" />

</LinearLayout>


** main 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/main"
    tools:context=".Main">

    <Button
        android:id="@+id/btnStart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="360dp"
        android:text="START"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnHowto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:text="How To Play"
        android:textAllCaps="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnStart" />

    <Button
        android:id="@+id/btnInfo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:text="INFO"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btnHowto" />
</androidx.constraintlayout.widget.ConstraintLayout>


** start 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/playbg"
    android:contentDescription=".Start">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:padding="10dp">

        <TextView
            android:id="@+id/tvTime"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="시간"
            android:textStyle="normal|bold"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            android:background="#FFFFFF" />

        <TextView
            android:id="@+id/tvPoint"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:text="점수"
            android:textStyle="normal|bold"
            android:textAppearance="@style/TextAppearance.AppCompat.Large"
            android:background="#FFFFFF" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="7"
        android:orientation="vertical"
        android:gravity="center_horizontal">

        <ImageView
            android:id="@+id/ivBlock1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_blue"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_green"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_red"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_blue"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_blue"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_blue"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock7"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_blue"
            android:layout_weight="1"

            android:layout_margin="2dp"/>

        <ImageView
            android:id="@+id/ivBlock8"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/block_blue"
            android:layout_weight="1"
            android:layout_margin="2dp"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/ivRed"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="10dp"
            android:src="@drawable/btn_red" />

        <ImageView
            android:id="@+id/ivGreen"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="10dp"
            android:src="@drawable/btn_green" />

        <ImageView
            android:id="@+id/ivBlue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_margin="10dp"
            android:src="@drawable/btn_blue" />

    </LinearLayout>
</LinearLayout>


** howtopaly 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/main"
    tools:context=".HowToPaly">

    <TextView
        android:id="@+id/textView"
        android:background="#CCFFFFFF"
        android:layout_width="300dp"
        android:layout_height="130dp"
        android:layout_marginStart="60dp"
        android:layout_marginTop="60dp"
        android:gravity="center"
        android:text="떨어지는 블럭과\n같은 색깔의 버튼을 누르세요."
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnBack"
        android:layout_width="130dp"
        android:layout_height="65dp"
        android:layout_marginEnd="60dp"
        android:layout_marginBottom="50dp"
        android:text="Back"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>


** info 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/main"
    tools:context=".Info">

    <TextView
        android:id="@+id/textView"
        android:background="#CCFFFFFF"
        android:layout_width="300dp"
        android:layout_height="130dp"
        android:layout_marginStart="60dp"
        android:layout_marginTop="60dp"
        android:gravity="center"
        android:text="게임소개\n
개발자: shine\n
개발일자: 2020. 04. 21\n
앱설명: 잼있는 블럭게임"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnBack"
        android:layout_width="130dp"
        android:layout_height="65dp"
        android:layout_marginEnd="60dp"
        android:layout_marginBottom="50dp"
        android:text="Back"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

 

 

3. android:layout_margin : 바깥 여백, 

   android:padding : 안쪽 여백

 

 

4. 최종 목표를 만들기 위해서는 중간 목표를 만들기가 중요

   중간 목표점을 찍고 그것들을 검증해가면서 코딩하는 것이 중요..!!

'웹_프론트_백엔드 > JAVA프레임윅기반_풀스택' 카테고리의 다른 글

2020.04.23  (0) 2020.04.23
2020.04.22  (0) 2020.04.22
2020.04.20  (0) 2020.04.20
2020.04.17  (0) 2020.04.17
2020.04.16  (0) 2020.04.16