Le_Penseur

[안드로이드 스튜디오] Ch11. 다이얼로그(Dialog) 본문

개인(Personal)/안드로이드 (Andorid Studio)

[안드로이드 스튜디오] Ch11. 다이얼로그(Dialog)

LePenseur 2019. 8. 29. 12:26
반응형

2019년 8월 29일 (목)

 

 

 

창업의 길로 가기 위한 두번째 걸음, [안드로이드 스튜디오]로 향해보자!

 

*질적으로 많이 부족한 글입니다. 지적 및 조언 환영합니다.

*이 글에선 "안드로이드 스튜디오"를 줄여서 "안스" 라고 표현합니다. 참고 바랍니다.

 

우선, 본인은 학원에서 'JAVA' 기초 수업을 선수강했다. 안드로이드 스튜디오를 배우기 위해선 피할 수 없는 언어이기 때문이다.

(그런데 Ch11까지 배운 현재, JAVA에 대한 공부가 더 필요하다고 느껴진다...)

 


**잡담**

그나저나 경력있는 한 프로그래머가 나에게 이런 조언을 해주었다.

 

"자꾸 이어붙이면서 이해하지말라, 개별적으로 생각하고 이해하라"

 

...라는 말이 무슨말일까?

각각의 xml, java파일들을 독립적으로 생각하라는말일까?

근데 그 여러 파일들이 모여 하나의 뷰가 되고, 기능이 되는건데 어찌 개별적으로 생각하라는것인가 ㅠㅠ..

 

갈길이 멀다고 느꼈다.


 

이번글에서는 다이얼로그(dialog)에 대해 알아보며 이해하는시간을 갖도록한다.

 

 

 


<차례>

1. MyDialog (+다이얼로그 개념설명)

2. MyRatingDialog


 

1. MyDialog
1.1 결과

 

사진1

 

설명: 프로젝트 자체는 매우 간단하다. "ShowDialog"라는 버튼하나만 생성해주고, 새로운 xml파일에서 다이얼로그에 들어갈 목록들을 디자인 및 스타일링 해주고, 버튼 클릭 기능을 만들면된다.

잠깐! 그래서 다이얼로그가 뭔데?

 

Q. 다이얼로그(dialog)란 무엇인가?

 

직역하자면 '대화' 인데, 컴퓨터 언어라는점을 감안하면, 사용자와 프로그램간의 대화, 즉 알림창 정도로 생각하면 dialog를 이해하는데 크게 어렵지 않다. 또한 실제 스마트폰(특히 안드로이드)을 많이 사용하는 사람들은 이 알림창을 생각하면 dialog가 무엇인지 단번에 이해할 수 있다.

 

Q. 다이얼로그의 종류?

 

(1) 모달 알림창 (Modal Dialog)

 

사진2

 

- 다이얼로그를 닫기전까지 원래 창, 즉 해당 다이얼로그를 호출한 창을 사용자가 사용할 수 없다.

- 무엇인가에 대한 confirm(동의)을 받아야하는 경우 이 모델 다이얼로그를 많이 사용한다.

- 밑에 나올 AlertDialog가 그 예시이다.

- 모덜리스 알림창과는 달리 멤버변수화와 객체화를 둘다 해야한다.

 

 

(2) 모덜리스 알림창 (Modeless Dialog)

 

사진3

 

- 다이얼로그가 회면에 떠있더라도 원래 창을 계속 사용할 수 있다.

- 사용자에게 무엇인가 알려야 하는 경우에 사용된다. (동의를 받아야하는 등 강제성은 없다)

- 전 글에서도 사용되었던 안드로이드의 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) 설정한 다이얼로그의 모습이다.

사진4

 

(Case.2)

<item name = "android:windowNoTitle">false</item>

<item name = "android:windowIsFloating">false</item>

설명: 밑의 사진5는 둘다 false를 주었을때의 모습이다. 즉, 타이틀바를 설정하고(false) 전체화면 크기로(false) 설정한 다이얼로그의 모습이다.

사진5

 

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 결과

사진6

설명: 위의 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();

            }
        });

    }
}
반응형
Comments