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 |