Le_Penseur
[안드로이드 스튜디오] Ch11. 다이얼로그(Dialog) 본문
2019년 8월 29일 (목)
창업의 길로 가기 위한 두번째 걸음, [안드로이드 스튜디오]로 향해보자!
*질적으로 많이 부족한 글입니다. 지적 및 조언 환영합니다.
*이 글에선 "안드로이드 스튜디오"를 줄여서 "안스" 라고 표현합니다. 참고 바랍니다.
우선, 본인은 학원에서 'JAVA' 기초 수업을 선수강했다. 안드로이드 스튜디오를 배우기 위해선 피할 수 없는 언어이기 때문이다.
(그런데 Ch11까지 배운 현재, JAVA에 대한 공부가 더 필요하다고 느껴진다...)
**잡담**
그나저나 경력있는 한 프로그래머가 나에게 이런 조언을 해주었다.
"자꾸 이어붙이면서 이해하지말라, 개별적으로 생각하고 이해하라"
...라는 말이 무슨말일까?
각각의 xml, java파일들을 독립적으로 생각하라는말일까?
근데 그 여러 파일들이 모여 하나의 뷰가 되고, 기능이 되는건데 어찌 개별적으로 생각하라는것인가 ㅠㅠ..
갈길이 멀다고 느꼈다.
이번글에서는 다이얼로그(dialog)에 대해 알아보며 이해하는시간을 갖도록한다.
<차례>
1. MyDialog (+다이얼로그 개념설명)
2. MyRatingDialog
1. MyDialog
1.1 결과
설명: 프로젝트 자체는 매우 간단하다. "ShowDialog"라는 버튼하나만 생성해주고, 새로운 xml파일에서 다이얼로그에 들어갈 목록들을 디자인 및 스타일링 해주고, 버튼 클릭 기능을 만들면된다.
잠깐! 그래서 다이얼로그가 뭔데?
Q. 다이얼로그(dialog)란 무엇인가?
직역하자면 '대화' 인데, 컴퓨터 언어라는점을 감안하면, 사용자와 프로그램간의 대화, 즉 알림창 정도로 생각하면 dialog를 이해하는데 크게 어렵지 않다. 또한 실제 스마트폰(특히 안드로이드)을 많이 사용하는 사람들은 이 알림창을 생각하면 dialog가 무엇인지 단번에 이해할 수 있다.
Q. 다이얼로그의 종류?
(1) 모달 알림창 (Modal Dialog)
- 다이얼로그를 닫기전까지 원래 창, 즉 해당 다이얼로그를 호출한 창을 사용자가 사용할 수 없다.
- 무엇인가에 대한 confirm(동의)을 받아야하는 경우 이 모델 다이얼로그를 많이 사용한다.
- 밑에 나올 AlertDialog가 그 예시이다.
- 모덜리스 알림창과는 달리 멤버변수화와 객체화를 둘다 해야한다.
(2) 모덜리스 알림창 (Modeless Dialog)
- 다이얼로그가 회면에 떠있더라도 원래 창을 계속 사용할 수 있다.
- 사용자에게 무엇인가 알려야 하는 경우에 사용된다. (동의를 받아야하는 등 강제성은 없다)
- 전 글에서도 사용되었던 안드로이드의 Toast가 그 예이다.
- 모달 알림창과는 달리 멤버변수화를 할필요가 없다. 객체화만 시키면된다.
- 예시) 밑의 로직은 위에서 따로 Toast를 멤버변수화 시키지 않았다. 그럼에도 불구하고 바로 호출이 가능하다.
switch (motionEvent.getAction()){
case MotionEvent.ACTION_DOWN:
Toast.makeText(MainActivity.this,"Action Down!!!", Toast.LENGTH_SHORT).show();
msg = "Result : DOWN";
break;
이번글에서는 모달알림창에 대해서 배울것이다.
Toast는 Ch8의 MyChatEvent에서 다루었으니 확인바란다.
https://lepenseur-blog.tistory.com/11
[안드로이드 스튜디오] Ch8. 리스트뷰 이벤트처리 (ListView Event Handling
2019년 8월 25일 (일) 창업의 길로 가기 위한 두번째 걸음, [안드로이드 스튜디오]로 향해보자! *질적으로 많이 부족한 글입니다. 지적 및 조언 환영합니다. *이 글에선 "안드로이드 스튜디오"를 줄여서 "안스" 라..
lepenseur-blog.tistory.com
1.2 코드
1.2.1 activity_main.xml
<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"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="20dp"
android:text="@string/showDialog"
android:textSize="25dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
설명: 초기화면 디자인이다. 버튼이 하나밖에 없으니 간단하다. 단, id적는것을 잊지말자.
1.2.2 dialog_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Menu1"/>
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="닫기"/>
</LinearLayout>
설명: 알림창내 화면을 디자인하는 것이다. 초기화면과 알림창내 화면을 이런식으로 독립적인 xml 파일로 디자인해야한다.
1.2.3 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>
<!--
누가 버전 이후에는 다이얼로그의 타이틀이 보여지지 않는다...
타이틀을 보여지게 하려면 우리가 따로 설정을 잡아주어야 한다...
-->
<style name="Dialog" parent="@android:style/Theme.Holo.Light.Dialog">
<!-- 다이얼 로그의 기본 테마...-->
<item name="android:windowNoTitle">false</item>
<!-- 타이틀바가 true면 없고 false면 있다.,.. -->
<item name="android:windowIsFloating">true</item>
<!-- 화면 범위 설정 true는 전체 화면 false면 아니다.. -->
</style>
</resources>
설명: AppTheme 에서의 스타일링 아이템 순서는 [타이틀 배경 - 타이틀 위 (시간표시되는곳) 배경 - ?] 이다.
또한 그 밑은 다이얼로그의 테마설정인데, 본래 존재하던 Holo.Light라는 테마를 상속받는것을 볼수있다.
windowNoTitle을 false 로 두면 타이틀바가 생기고 true 라 두면 타이틀바가 사라진다.
...뭔말이야? NoTitle뿐만 아니라 IsFloating도 함께 예시를 통해 비교해보자.
(Case.1)
<item name = "android:windowNoTitle">true</item>
<item name = "android:windowIsFloating">true</item>
설명: 밑의 사진4는 둘다 true를 주었을때의 모습이다. 즉, 타이틀바를 없애고(true) 데코에 맞는 크기로(true) 설정한 다이얼로그의 모습이다.
(Case.2)
<item name = "android:windowNoTitle">false</item>
<item name = "android:windowIsFloating">false</item>
설명: 밑의 사진5는 둘다 false를 주었을때의 모습이다. 즉, 타이틀바를 설정하고(false) 전체화면 크기로(false) 설정한 다이얼로그의 모습이다.
1.2.4 strings.xml
<resources>
<string name="app_name">MyDialog</string>
<string name="showDialog">ShowDialog</string>
</resources>
설명: 이 string의 역할은 "string 내에서 정의한 문자열을 프로그램에서 사용할 변수처럼 정의한것"
음... 한마디로 java와는 또다른 변수선언(?) 정도라고 생각하자.
1.2.5 MainActivity.java
package com.example.mydialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button button,button2,button3;
private Dialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//객체화
button = (Button)findViewById(R.id.button);
//리스너설정
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//버튼 클릭시 다이얼로그 생성을 할것이다. (버튼 클릭시 알림창이라는 객체가 뜨도록할것이다)
dialog = new Dialog(MainActivity.this,R.style.Dialog);
//생성자
//Dialog(Context context)
// - 기본대화 상자 테마를 사용하는 대화 상자.(다이얼로그)
//Dialog(Context context, int themeResId)
// - 커스텀 다이얼로그 스타일을 사용하여 다이얼로그 윈도우를 작성한다.
//타이틀 설정
dialog.setTitle("타이틀 설정");
//다이얼로그 설정시 왠만하면 setContentView위에 작성하는것이 좋다.
//타이틀 없애기
// dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
//반투명화 제거
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
//다이얼로그 자체 배경을 투명하게
//dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
//인플레이션 진행
dialog.setContentView(R.layout.dialog_layout);
//버튼 객체화
button2 = (Button)dialog.findViewById(R.id.button2);
button3 = (Button)dialog.findViewById(R.id.button3);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss(); // 다이얼로그 닫기
}
});
dialog.show();
}
});
}
}
설명: 우선적으로는 기존에 만들어두었던 id들을 모두 불러 멤버변수화를 시킨다. 다음은 객체화인데, 이 부분이 매우 중요하다.
객체화는 반드시 인플레이터를 받고있는 뷰가 누구인지 따져봐야한다.
지금 우리가 진행중인 프로젝트내에서는 독립적으로 운영되어야할 뷰가 2개이다. (초기화면뷰 & 다이얼로그뷰)
따라서 처음 activity_main을 인플레이터 하고 있는곳에는 button1만 객체화를 시키고
그 객체화된 버튼안에서 dialog 실행 메소드와 함께 dialog_layout을 인플레이터 해주어 나머지 button2, button3도 객체화를 해주는 순서다.
**핵심 요약:
(1) 객체화는 반드시 인플레이터해주는 뷰가 누구인지 따져보고 하자.
(2) "버튼을 클릭했을때 누가 나타나느냐"를 상기시키며 로직을 만들자. (상위->하위)
2. MyRatingBarDialog
1.1 결과
설명: 위의 MyDialog를 이해했다면 이번 RatingBar역시 크게 어렵지 않게 만들수있다.
왜냐하면 전체적인 로직은 동일하기때문이다.
전체적인 로직: [초기화면뷰 -> 다이얼로그뷰 -> 기능 로직 작성]
그러므로 따로 설명 없이 프로젝트의 코드만 파일별로 첨부한다.
이해가 되지 않는부분은 반드시 위의 MyDialog를 다시 복습하자.
2.2 코드
2.2.1 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#ffffff">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="별점 주기"
android:textSize="40dp"
android:textColor="#000000"/>
<RatingBar
android:id="@+id/ratingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="확인"
android:textSize="25dp"/>
</LinearLayout>
2.2.2 dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#ffffff">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="별점 주기"
android:textSize="40dp"
android:textColor="#000000"/>
<RatingBar
android:id="@+id/ratingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="5"
/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="확인"
android:textSize="25dp"/>
</LinearLayout>
2.2.3 MainActivity.java
package com.example.myratingbardialog;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.RatingBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button button1,button2;
private TextView textView;
private RatingBar ratingBar;
private Dialog dialog;
private String str;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//객체화
textView = (TextView)findViewById(R.id.textView);
button1 = (Button)findViewById(R.id.button1);
//리스너 설정
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//다이얼로그 객체 생성
dialog = new Dialog(MainActivity.this);
//인플레이션
dialog.setContentView(R.layout.dialog);
//객체화
ratingBar = (RatingBar)dialog.findViewById(R.id.ratingBar);
button2 = (Button)dialog.findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
textView.setText(str + " / 10.0");
dialog.dismiss();
}
});
//리스너 설정 - OnRatingBarChangeListener
ratingBar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
@Override
public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
//float v(rating) - 별점 반칸 0.5점
//별개수에 따른 별 한칸당 평균
float st = 10.0f/ratingBar.getNumStars();
//String 객체를 이용해서 구한 평균값을 소수점 한자리로 표현..
str = String.format("%.1f",(st * v) );
}
});
//다이얼로그 창 주변부분 터치 가능여부
//false면 터치 불가 true 터치 가능
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
});
}
}
'개인(Personal) > 안드로이드 (Andorid Studio)' 카테고리의 다른 글
[안드로이드 스튜디오] Ch13. 플래그 & 핸들러 (Flag & Handler) (0) | 2019.09.01 |
---|---|
[안드로이드 스튜디오] Ch12. 다이얼로그 & 인텐트 (Dialog & Intent) (0) | 2019.08.30 |
[안드로이드 스튜디오] Ch10. 버튼 이펙트 & 핵심 수신기(ButtonEffect & KeyListener) (0) | 2019.08.28 |
[안드로이드 스튜디오] Ch9. 버튼 클릭 이벤트 처리 & 인플레이터(OnClickListener & Inflater) (0) | 2019.08.27 |
[안드로이드 스튜디오] Ch8. 리스트뷰 이벤트처리 (ListView Event Handling (0) | 2019.08.25 |