안드로이드 완벽 가이드 - 01 안드로이드 스튜디오와 기본 레이아웃 익히기

출처

정재곤, 『Do it! 안드로이드 앱 프로그래밍 - 개정 4판』, 이지스퍼블리싱(주)(2017-06-26), 128-179p


01-1 안드로이드 스튜디오 살펴보기

안드로이드 스튜디오

  • 인텔리제이(IntelliJ)라는 개발도구를 확장하여 만든 것

첫째마당을 참고하여 Test 프로젝트 만들기

image

  • 도메인(Domain): 패키지 명을 겹치지 않게 하기 위한 이름
  • 계속 Next 버튼 클릭 후 Empty Activity 선택

image

  • 액티비티 이름: MainActivity
  • Finish 버튼 누르기
  • 프로젝트 닫으려면 File –> Close Project

프로젝트 창의 구성과 기능

File –> Settings –> Editor –> General –> Auto Imports 선택

image

빠른 메뉴(Quick Access Menu)

image

Ctrl + Tab –> 개꿀 단축키

Ctrl + Q –> 클래스가 사용하는 API 문서 보기

Ctrl + P –> 함수 파라미터 확인

Generator 사용하기

  • MainActivity 클래스에서 onCreate를 재정의하려 함
  • onCreate 중괄호 시작점에서 마우스 오른쪽 클릭 후 Generate… 클릭
  • Override Methods… 입력

image

폴더 내 text 검색은 폴더 선택 후 Edit –> Find –> Find in Path…

디자이너 도구 살펴보기

  • 딴 건 다 필요없고 res/layout/activity_main.xml에서
  • Nexus 4라고 표시된 거 누르면 다른 것으로 해상도 바꿀 수 있음

image


01-2 뷰와 뷰의 크기 속성 이해하기

뷰의 속성

  • 뷰(view): 일반적으로 컨트롤이나 위젯으로 불리는 UI 구성 요소
  • 뷰그룹(ViewGroup): 뷰를 여러 개 포함하고 있는 것
  • 뷰그룹은 뷰를 상속함 –> 컴포지트 패턴(Composite Pattern)
  • TextView 태그를 Button으로 바꾸면 바뀌는 이유도 바로
  • TextView를 Button이 상속하였기 때문

위젯과 레이아웃

  • 위젯: 사용자의 눈에 보이는 컨트롤의 역할을 하는 화면 구성 요소
  • 레이아웃: 뷰들을 배치하는 역할을 하는 것

버튼과 리니어 레이아웃의 계층도

image

  • 레이아웃은 여러 위젯을 담고 위치를 지정
  • 레이아웃 안에 레이아웃을 넣으면 레이아웃 안에서 버튼과 같은 위젯으 위치를 잡음

뷰의 크기 속성

  • 정리해보면 화면에 추가할 수 있는 모든 것은 뷰
  • 뷰는 위젯과 레이아웃으로 구분
  • 뷰는 화면의 일정 영역을 차지하므로 크기 속성이 있어야 함

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
  • android:로 시작하는 건 안드로이드의 기본 API에서 정의한 속성이라는 의미

layout_width와 layout_height 속성

  • 뷰가 가질 수 있는 내부 속성 중에서 필수 속성
  • 각각 가로와 세로를 나타냄

wrap_content: 뷰에 들어 있는 내용물의 크기에 자동으로 맞춤 match_parent: 뷰를 담고 있는 뷰그룹의 여유 공간을 꽉 채움 숫자로 크기 지정: 숫자를 사용해 크기를 지정, 크기는 단위가 꼭 있어야 함

1. 버튼 추가(안녕하세요, 반갑습니다!)

image

2. layout_width 속성을 match_parent로 변경

image

3. layout_width를 240dp로 변경

image

4. ‘Hello World!’ 글자 삭제 후 버튼 layout_width는 wrap_content, layout_height은 match_parent

image

5. layout_width, layout_height 둘 다 match_parent

image

  • 이런 식으로 나오는 이유는 제약 레이아웃(ConstLayout)이기 때문
  • 리니어 레이아웃(LinearLayout)이나 상대 레이아웃(RelativeLayout)이면 결과가 달라짐

01-3 제약 레이아웃 익히기

제약 조건 이해하기

  • 제약 레이아웃은 제약 조건(Constraint)를 사용함
  • 제약 조건: 뷰가 레이아웃 안의 다른 요소와 어떻게 연결되는지 알려주는 것
  • 뷰의 연결점(Anchor Point)과 대상(Target)을 연결

image

  • 버튼 입장에서 부모는 자신을 감싸는 레이아웃 즉, 부모 레이아웃(Parent Layout)
  • 최소 2개의 연결점이 2개의 대상과 연결되어야 자신의 위치를 고정됨

대상이 될 수 있는 점

  1. 같은 레이아웃 안에 들어있는 다른 뷰의 연결점
  2. 부모 레이아웃의 연결점
  3. 가이드라인(Guideline)

대상 뷰와 대상의 연결점으로 될 수 있는 것

  1. 상하좌우(Top, Bottom, Left, Right) left는 Start, Right은 End로도 표시 가능
  2. 가로축의 가운데(CenterX), 세로축의 가운데(CenterY)
  3. 베이스라인(Baseline) –> 텍스트를 보여주는 뷰인 경우에만 적용

1. SampleConstraintLayout 프로젝트 만들기

2. activitiy_main.xml 디자인 탭에서 텍스트 지우고 버튼 추가하기

3. 버튼의 왼쪽, 위쪽 연결점을 부모의 대상에 연결하기

4. 오른쪽 Properties창 위에서 왼, 위쪽 값을 80으로 설정하기

image

  • 여기서 설정한 숫자는 마진(Margin)이라 하며 연결점과 대상과의 거리를 나타냄

5. 버튼 하나 더 추가하기

6. 새로 추가한 버튼의 왼쪽 연결점을 기존 버튼과 위쪽 연결점을 위쪽 벽면과 연결

7. Properties창에서 새로 추가한 버튼의 위쪽 마진은 80, 왼쪽 마진은 40으로 설정

image

화면 가운데에 뷰 배치하기

1. 버튼 하나 더 추가 후 상하좌우 연결점을 전부 부모의 대상에 연결하기

image

  • 이렇게 하면 마진 값은 고려되지 않고 중간에 위치하게 됨

2. Properties 창에서 두 막대기 중 세로 막대기 값을 35로 조정하기

image

  • 바이어스(Bias): 한 쪽으로 얼마나 치우쳐 있는지를 나타내는 값

3. 버튼 꼭짓점을 잡아서 크기 바꾸고 Properties에서 사각형 내부 선이 직선이 됨을 확인하기

image

  • wrap_content에서 특정 dp값으로 바뀜

내부 선의 종류

  1. 부모 여유 공간 채우기: 구불구불한 선

image

  1. 뷰의 내용물 채우기: 중앙을 향하는 화살표

image

  1. 고정 크기: 직선

image

  • 여유 공간: 해당 뷰가 차지할 수 있는 공간

가이드라인 사용하기

  • 가이드라인(Guideline): 여러 개의 뷰를 일정한 기준 선에 정렬할 때 사용
  • 크기가 0이고 화면에 보이지 않음

1. res>layout 폴더에 마우스 오른쪽 버튼 클릭 후 New –> Layout resource file 선택

2. File name: activity_menu.xml, Root element: android.support.constraint.ConstraintLayout

image

3. 디자이너 도구에서 Guidelines 아이콘 클릭 후 Add Vertical Guideline 선택

image

4. 가이드라인 선을 끌어당기며 조절해보고 text 탭에서 android.support.constraint.Guideline 태그 찾아 100dp로 바꾸기

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.constraint.Guideline
        android:id="@+id/guideline3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp" />
</android.support.constraint.ConstraintLayout>
  • app:layout_constraintGuide_begin=”100dp”

5. 가이드라인 오른쪽에 버튼 세 개 추가하기(왼쪽 연결점은 가이드라인, 위쪽은 위쪽 벽면)

image

XML 원본에 추가된 속성 확인하기

activity_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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.support.constraint.Guideline
        android:id="@+id/guideline3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="36dp"
        android:layout_marginStart="36dp"
        android:layout_marginTop="24dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="@+id/guideline3"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="76dp"
        android:layout_marginStart="76dp"
        android:layout_marginTop="140dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="@+id/guideline3"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="132dp"
        android:layout_marginStart="132dp"
        android:layout_marginTop="248dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="@+id/guideline3"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

XML 파일에 일반적으로 추가하는 정보

<?xml version="1.0" encoding="utf-8"?>

최상위 레이아웃

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  • 안드로이드 기본 API에 포함된 위젯이나 레이아웃이 아니면 패키지 이름까지 써야 함
  • ConstraintLayout은 기본 API가 아니여서 앞에 패키지 이름을 붙인 것

xmlns:로 시작하는 속성들

  • xmlns:android를 예를 들어 보자
  • xmlns 뒤의 값은 나머지 속성의 접두어(prefix)로 사용됨
  • android:layout_width 속성에서 앞에 있는 android:는 xmlns:android로 지정된 정보를 참조한다는 뜻
xmlns:android
  • 안드로이드 기본 SDK에 포함되어 있는 속성을 사용
xmlns:app
  • 프로젝트에서 사용하는 외부 라이브러리에 포함되어 있는 속성을 사용
xmlns:tools
  • 안드로이드 스튜디오의 디자이너 도구 등에서 화면을 보여줄 때 사용
  • 앱이 실행될 때는 적용되지 않고 안드로이드 스튜디오에서만 적용

android:id 속성

  • 뷰를 구분하는 구분자 역할을 함
id 속성이 사용되는 두 가지 용도
  1. XML 레이아웃 파일 안에서 뷰를 구분할 때
  2. XML 레이아웃 파일에서 정의한 뷰를 자바 소스 파일에서 찾을 때

제약 레이아웃에서 하나의 뷰를 다른 뷰와 연결할 때 사용하는 XML 속성의 이름 규칙

layout _constraint [소스 뷰의 연결점]_[대상 뷰의 연결점]="[대상 뷰의 id]"

제약 레이아웃에서 사용할 수 있는 속성들

layout _constraintTop _toTopOf
layout _constraintTop _toBottomOf
layout _constraintBottom _toTopOf
layout _constraintBottom _toBottomOf
layout _constraintLeft _toTopOf
layout _constraintLeft _toBottomOf
layout _constraintLeft _toLeftOf
layout _constraintLeft _toRightOf
layout _constraintRight _toTopOf
layout _constraintRight _toBottomOf
layout _constraintRight _toLeftOf
layout _constraintRight _toRightOf

가이드라인을 위해 추가된 태그

 <android.support.constraint.Guideline
        android:id="@+id/guideline3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp" />
  • Guideline 클래스도 외부 라이브러리에 포함된 패키지
  • 때문에 andorid.support.constraint를 붙임
  • id 값으로 @+id/guideline이 설정되어 있음
  • android:orientation은 가로, 세로 방향을 결정하는 필수 속성
  • layout_constraintGuide_begin은 부모 레이아웃과의 거리를 나타냄

부모 레이아웃과 Guideline의 거리를 나타내는 세 가지 속성

1. layout_constraintGuide_begin

세로 방향인 경우 왼쪽부터, 가로 방향인 경우 위쪽부터 거리 지정

2. layout_constraintGuide_end

세로 방향인 경우 오른쪽부터, 가로 방향인 경우 아래쪽부터 거리 지정

3. layout_constraintGuide_percent

layout_constraintGuide_begin 속성 대신 지정하되 %단위로 거리 지정

  • 제약 조건을 설정하는 속성은 외부 라이브러리의 속성이여서 app: 접두어가 붙음
  • tools:는 디자이너 도구 표시용 속성으로 건들일 필요 없음

거리 단위 여러 가지 있는데 결론은 dp를 써라

dp

  • 160dpi 화면을 기준으로 한 픽셀
  • px: 픽셀, 화면 픽셀의 수
  • 예) 1인치 당 160개의 점이 있는 디스플레이 화면에서 1dp는 1px, 1인치 당 320개의 점이 있는 디스플레이 화면에서는 1dp는 2px와 같음

나머지 부분

 <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="36dp"
        android:layout_marginStart="36dp"
        android:layout_marginTop="24dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="@+id/guideline3"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="76dp"
        android:layout_marginStart="76dp"
        android:layout_marginTop="140dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="@+id/guideline3"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="132dp"
        android:layout_marginStart="132dp"
        android:layout_marginTop="248dp"
        android:text="Button"
        app:layout_constraintStart_toStartOf="@+id/guideline3"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
  • 디자이너 도구에서 버튼을 추가하면 버튼의 id가 자동으로 중복되지 않게 붙음
  • text 속성은 버튼 위에 표시되는 글자를 설정할 때 사용

app:layout_constraintStart_toStartOf 속성

  • 이 버튼의 왼쪽의 연결점과 대상 뷰의 왼쪽 연결점을 연결하여 제약 조건을 만들자

layout_marginTop 속성

속성 이름 설명
layout_marginTop 뷰의 위쪽을 얼마나 띄울지 지정함
layout_marginBottom 뷰의 아래쪽을 얼마나 띄울지 지정함
layout_marginLeft 뷰의 왼쪽을 얼마나 띄울지 지정함
layout_marginRight 뷰의 오른쪽을 얼마나 띄울지 지정함
layout_margin 뷰의 위, 아래, 왼쪽, 오른쪽을 얼마나 띄울지 지정함

도전! 01 새 프로젝트 아래쪽에 두 개의 버튼 추가하기

프로젝트 소스: DoitMission-01

1. 제약 레이아웃을 사용해 화면 구성

2. 화면의 아래쪽에 가이드라인을 배치

3. 가이드라인의 위쪽에 버튼을 추가한 후 가이드라인과 연결(적절한 간격 필요)

4. 가이드라인의 위쪽에 버튼을 하나 더 추가한 후 이전에 추가했던 버튼 및 가이드라인과 연결(적절한 간격 필요)


도전! 01 답

image

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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">

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_begin="444dp" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="44dp"
        android:layout_marginLeft="64dp"
        android:layout_marginStart="64dp"
        android:text="버튼 1"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="44dp"
        android:layout_marginLeft="64dp"
        android:layout_marginStart="64dp"
        android:text="버튼 2"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintStart_toEndOf="@+id/button" />

</android.support.constraint.ConstraintLayout>

도전! 02 위, 아래, 중앙의 공간을 차지하는 전형적인 화면 구성하기

프로젝트 소스: DoitMission-02

1. 제약 레이아웃을 사용해 화면을 구성

2. 화면의 위쪽에 버튼을 추가하고 가로 방향으로 꽉 차도록 만들기

3. 화면의 아래쪽에 버튼을 추가하고 가로 방향으로 꽉 차도록 만들기

4. 화면의 가운데에 버튼을 추가하고 위쪽 버튼과 아래쪽 버튼 사이의 중앙 공간을 꽉 채우도록 만들기


도전! 02 답

image

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="match+parent"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:text="Button"
        app:layout_constraintBottom_toTopOf="@+id/button2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />

</android.support.constraint.ConstraintLayout>

Comments