Programming/Android Studio

Andriod Studio #01

주눅 2026. 10. 19. 08:55
MOBILE PROGRAMMING / JAVA + XML

안드로이드 실습형 시험 대비
Part 1 + Part 2 완전 통합 노트

업로드한 6개 강의 PDF · 핵심 기능 + 완성 코드 + 강의자료 실습 결과 사진 · 시험 직전 빠른 검색

이 글을 이용하는 방법
① Ctrl+F로 기능명 검색 → ② 해당 실습 코드 확인 → ③ 결과 사진과 배치 비교 → ④ 자신의 프로젝트에 맞게 패키지·파일명·ID 수정. 출처는 업로드한 강의 PDF이며, 일부 완성 코드는 동일 요구사항을 충족하도록 재작성한 예제입니다.
PDF 7쪽

Part 1 · Chapter 01 — 안드로이드란?

안드로이드 플랫폼을 이해하기 위한 개념 장입니다.

1. 안드로이드 운영체제의 특징

📘 강의자료 p.3~5

용어 강의 핵심 문제에 연결하면
오픈소스 공개된 소스코드를 바탕으로 하는 운영체제 플랫폼 확장성
Java 강의 실습의 주 개발 언어 Java + XML View 기반 화면
컴포넌트 기반 기능별 구성 요소를 조합해 앱 개발 Activity 등의 구성 요소
앱 간 연동 다른 앱의 기능을 호출할 수 있음 Intent를 이용한 웹/전화 앱 열기
ART(Android Runtime) 애플리케이션 실행 환경 안드로이드 앱 실행

2. 안드로이드 생태계

📘 강의자료 p.4~7

운영체제, 단말기 제조사, 이동통신사, 앱 개발자 등 다양한 주체가 참여하는 에코시스템(Ecosystem)을 형성합니다. 강의의 핵심은 오픈소스와 컴포넌트 기반 구조입니다.

시험 대비
이 장은 구현보다는 용어와 특징을 묻는 문제에 가깝습니다. 자세한 코드는 Part 1 Chapter 03부터 확인합니다.

↑ 목차로 이동

PDF 55쪽

Part 1 · Chapter 03 — 첫 번째 앱 만들기

새 프로젝트 → 에뮬레이터 → XML/Java 연결 → 이벤트 → 외부 앱 호출.

1. 프로젝트 만들기·파일 구조

📘 강의자료 p.3~11

  • New Project → Empty Activity/Empty Views Activity(강의 화면의 버전별 명칭 차이) → Java 선택.
  • MainActivity.java: 이벤트와 Activity 코드. activity_main.xml: 화면 모양. AndroidManifest.xml: 실행 Activity 선언.
  • Code/Split/Design과 Blueprint로 화면의 구조 및 겹침 확인.
MainActivity.java — XML 화면 연결
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

2. 에뮬레이터로 Hello World 실행

📘 강의자료 p.12~19

  • AVD(Android Virtual Device) / Device Manager에서 가상 기기 생성.
  • 실행 대상 기기를 선택하고 상단 Run ▶ 클릭.
  • 실행한 앱의 화면을 확인. 프로그램 실행 중 로그는 Logcat에서 확인.
Hello World 에뮬레이터 실습 그림
Hello World 에뮬레이터 실습 그림 (강의 PDF에서 발췌)

3. 버튼·이벤트 연결

📘 강의자료 p.20~40

실습 / 완성 예제

버튼을 클릭하면 Toast 메시지 보여주기

버튼을 XML에 배치하고 Java의 이벤트 메서드를 연결합니다.

activity_main.xml (LinearLayout 내부의 버튼)
<Button
    android:id="@+id/button1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="확인"
    android:onClick="onButtonClicked" />
버튼을 클릭하면 Toast 메시지 보여주기 — 강의자료 속 결과·예시 화면
버튼을 클릭하면 Toast 메시지 보여주기 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
XML의 onClick 문자열과 Java 메서드 이름을 동일하게 맞추고, 인자로 View를 받습니다.
MainActivity.java — Activity 클래스 내부
public void onButtonClicked(View view) {
    Toast.makeText(this, "버튼이 눌렸습니다.", Toast.LENGTH_SHORT).show();
}
구분 용도
setContentView(R.layout.activity_main) XML 화면 불러오기
findViewById(R.id.button1) ID로 View 찾아서 코드로 접근
android:onClick="메서드명" XML에서 이벤트 함수 연결
Toast.makeText(...).show() 짧은 알림 출력

4. 여러 버튼과 외부 앱 실행

📘 강의자료 p.41~55

실습 / 완성 예제

웹 브라우저 열기 / 전화 앱 열기

강의는 버튼을 눌러 다른 앱의 기능을 호출하는 암시적 Intent를 다룹니다.

MainActivity.java — 버튼 클릭 시 호출할 메서드
public void openWeb(View view) {
    Intent intent = new Intent(Intent.ACTION_VIEW,
            Uri.parse("https://www.naver.com"));
    startActivity(intent);
}

public void openDial(View view) {
    Intent intent = new Intent(Intent.ACTION_DIAL,
            Uri.parse("tel:01012345678"));
    startActivity(intent);
}
웹 브라우저 열기 / 전화 앱 열기 — 강의자료 속 결과·예시 화면
웹 브라우저 열기 / 전화 앱 열기 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
android:onClick="openWeb"/"openDial"로 메서드에 연결. ACTION_DIAL은 전화 다이얼 화면을 엽니다.
Intent 요소 역할
Intent.ACTION_VIEW 데이터를 볼 수 있는 앱 호출
Intent.ACTION_DIAL 전화 다이얼 실행
Uri.parse("https://...") 문자열 주소를 URI로 변환
startActivity(intent) 요청을 처리할 Activity 시작

↑ 목차로 이동

PDF 9쪽

Part 1 · Chapter 04 — 실제 단말 연결하기

PC와 안드로이드폰을 연결해 실제 기기에서 실행하는 절차입니다.

1. 실제 스마트폰에서 실행

📘 강의자료 p.3~9

  • 삼성 단말 기준 필요할 경우 통합 USB 드라이버 설치.
  • 휴대전화 정보 → 소프트웨어 정보 → 빌드 번호를 7회 터치해 개발자 옵션 활성화.
  • 개발자 옵션 → USB 디버깅 켜기.
  • 데이터 전송 가능한 USB 케이블 연결 후 휴대폰의 디버깅 승인.
  • Android Studio 실행 대상 목록에서 실제 장치를 선택하고 Run ▶.
주의
에뮬레이터는 PC에서 가상으로 실행하는 장치이고, 실제 단말은 USB 또는 무선 디버깅으로 연결한 스마트폰입니다. 실습 결과가 서로 다르면 기기 화면 크기·OS 버전 등도 확인하세요.

↑ 목차로 이동

PDF 109쪽

Part 2 · Chapter 01 — 스튜디오와 친숙해지기

기존에 만든 포스팅의 모든 기능·단계별 실습·완성 XML을 그대로 포함했습니다.

ANDROID · 실습형 시험 대비

Part 2 · Chapter 01
안드로이드 스튜디오와 친숙해지기

View와 크기 속성부터 ConstraintLayout · Guideline · XML 실습까지
문제를 보고 바로 구현할 수 있도록 만든 실전 정리 노트

이 글을 사용하는 방법
① 목차에서 필요한 기능 찾기 → ② 속성과 코드 확인하기 → ③ 하단 실습문제 완성 예제를 복사·수정하기.
아래 예제는 Java + XML(View 기반)을 기준으로 작성했습니다.

빠른 목차

1. Android Studio · 프로젝트 도구

📄 강의자료 3~31페이지

1-1. 새 프로젝트 생성

  1. 시작 화면에서 New Project 선택
  2. 화면 템플릿으로 Empty Views Activity 선택
  3. Name(프로젝트명), Package name(패키지명) 확인
  4. Language = Java, Minimum SDK/API Level 설정 후 Finish
Minimum SDK(API Level)의 의미
앱을 설치해 실행할 수 있는 최소 안드로이드 버전을 정합니다. 낮추면 더 오래된 기기를 지원할 수 있지만, API 사용 범위를 함께 고려해야 합니다.

1-2. 편집 창의 구성

도구/영역 무엇을 할 때 사용하는가
Project 파일·폴더 구조 확인: Java, res/layout, AndroidManifest.xml 등
Code XML 원본 코드를 직접 편집
Split XML 코드와 디자인 미리보기를 함께 표시
Design 화면 요소를 시각적으로 배치
Palette Button, TextView 등의 위젯을 끌어다 추가
Component Tree 부모·자식 View의 계층구조 확인
Attributes 선택한 View의 속성 변경
Logcat 실행 중인 앱의 로그·오류 확인
Blueprint 겹쳐진 View와 제약조건을 청사진으로 확인

1-3. 작업 단축키

단축키 (Windows) 기능
Ctrl + Q 클래스·메서드의 API 설명 확인
Ctrl + P 메서드 매개변수 목록 확인
Ctrl + Shift + F 프로젝트 전체에서 텍스트 검색
Ctrl + Tab 최근 파일·도구창 전환(Switcher)
Generate → Override Methods 상속받은 메서드 재정의 코드 생성
시험에서 빠르게 찾기
메서드가 기억나지 않으면 자동 완성과 Ctrl+P로 파라미터를 확인합니다. 부모 메서드를 재정의할 때는 Override Methods를 활용하세요.

1-4. Design vs Blueprint vs 실제 실행

모드 가능한 것 한계
Design XML 화면 배치·외형 미리보기 실제 이벤트 코드를 실행하는 것은 아님
Blueprint View의 배치 관계, 겹침, 제약조건 보기 최종 색상·외형 확인 용도는 아님
앱 실행 Java 코드와 사용자 이벤트까지 실제 실행 에뮬레이터 또는 실제 단말이 필요
실습 주의 — Java로 만든 버튼이 Preview에 안 보일 때
new Button(this), addView(), setContentView(mainLayout)처럼 Java에서 실행 중에 만드는 View는 XML 레이아웃 미리보기에서 나타나지 않습니다. XML에 직접 작성한 View는 Split/Design에서 확인할 수 있습니다.

2. View / ViewGroup / 파일 구조

📄 강의자료 32~40페이지

2-1. 개념과 상속 관계

개념 설명 예시
View 화면을 구성하는 기본 요소 TextView, Button
ViewGroup 자식 View를 포함할 수 있는 View LinearLayout, ConstraintLayout
Widget 화면 표시 또는 사용자 입력을 담당 Button, TextView
Layout 자식 View의 크기·위치를 정하는 ViewGroup ConstraintLayout, LinearLayout

ViewGroup도 View의 일종이므로 레이아웃 안에 레이아웃을 넣는 중첩 구조가 가능합니다. 강의는 이를 컴포지트 패턴(Composite Pattern)과 연결합니다. 또한 Button은 TextView를 상속하므로 텍스트 관련 속성을 사용합니다.

2-2. 실습에서 만지는 대표 파일

파일 역할
app/src/main/java/.../MainActivity.java Activity에서 화면 연결·동작 처리
app/src/main/res/layout/activity_main.xml XML로 화면에 배치할 View와 속성 정의
app/src/main/AndroidManifest.xml Activity 등의 앱 구성요소 선언
MainActivity.java — XML 화면 연결
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}
코드 해석
R.layout.activity_main은 res/layout/activity_main.xml을 가리킵니다. 다른 레이아웃 XML을 표시하려면 setContentView(R.layout.새파일명)으로 변경합니다.

3. View 크기 지정하기

과제 완성 화면
강의자료 p.59 관련 실습·결과 화면

📄 강의자료 39~50페이지

3-1. 가장 기본이 되는 두 속성

View의 크기를 지정하는 XML 속성
android:layout_width="wrap_content"
android:layout_height="wrap_content"
값 의미 시험에서 기대 결과
wrap_content 내부 글자·이미지 등의 크기만큼 차지 버튼 글자가 길어지면 크기가 커질 수 있음
match_parent 부모가 허용하는 영역을 채움 부모의 너비 또는 높이에 맞춤
240dp 직접 지정한 고정 크기 지정한 크기로 표현
0dp (ConstraintLayout) 양쪽 제약조건 사이의 사용 가능한 공간에 맞춤 연결된 제약 사이를 채움

3-2. 실습 A — 버튼의 글자와 크기 바꾸기

  1. XML 편집기에서 Button의 android:text를 긴 문장으로 변경
  2. layout_width="wrap_content"이면 글자에 따라 버튼 너비가 바뀌는지 확인
  3. layout_width="240dp"로 바꾸고 고정 너비 확인
  4. layout_width="match_parent"로 바꾸고 부모 너비에 맞는지 확인
Button — 긴 텍스트와 고정 크기
<Button
    android:layout_width="240dp"
    android:layout_height="wrap_content"
    android:text="안녕하세요, 반갑습니다!" />

3-3. 실습 B — 부모 레이아웃을 바꿔보기

강의에서는 Component Tree에서 최상위 ConstraintLayout을 선택한 후 Convert View를 통해 LinearLayout으로 변경하고 버튼의 크기 변화를 살펴봅니다.

LinearLayout에서 버튼이 가로 너비 전체를 채우는 예
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="가로로 긴 버튼" />

</LinearLayout>
중요 — 같은 속성이라도 부모 Layout에 따라 달라진다
ConstraintLayout은 제약조건을 사용하며, LinearLayout은 배치 방향(orientation)이 핵심입니다. 특히 0dp가 항상 동일한 의미를 갖는 것은 아닙니다.

4. ConstraintLayout 배치 규칙

과제 완성 화면
강의자료 p.72 관련 실습·결과 화면

📄 강의자료 51~56, 87~93페이지

4-1. Constraint(제약조건)이란?

View의 연결점(Anchor Point)과 대상(Target)을 연결하여 위치를 정하는 규칙입니다. 대상은 부모(parent), 다른 View, Guideline 등이 될 수 있습니다.

최소한 기억할 것
가로·세로의 위치를 결정하려면 각 축을 구속하는 제약이 필요합니다. 대표적으로 왼쪽(Start) + 위쪽(Top)을 부모에 연결하면 좌상단 기준 배치가 가능합니다.
속성 정확한 의미
Top_toTopOf 내 위쪽을 대상 위쪽에 연결
Top_toBottomOf 내 위쪽을 대상 아래쪽에 연결
Bottom_toBottomOf 내 아래쪽을 대상 아래쪽에 연결
Start_toStartOf 내 시작쪽을 대상 시작쪽에 연결
Start_toEndOf 내 시작쪽을 대상 끝쪽에 연결
End_toEndOf 내 끝쪽을 대상 끝쪽에 연결
baseline_toBaselineOf 글자의 기준선(baseline)을 대상 글자 기준선에 정렬
속성 해석 요령
app:layout_constraintTop_toBottomOf="@id/btn1" → 내 Top을 btn1의 Bottom에 붙인다는 뜻. app: 접두어는 ConstraintLayout 라이브러리 속성에 사용합니다.

4-2. 실습 — 화면 좌상단에서 80dp 떨어진 버튼

activity_main.xml — 부모 Start/Top 기준 80dp
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="버튼 1"
        android:layout_marginStart="80dp"
        android:layout_marginTop="80dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

4-3. 실습 — 첫 버튼 오른쪽에 두 번째 버튼 배치

앞의 코드에서 첫 Button 다음에 두 번째 Button을 추가합니다. 강의에서는 첫 버튼의 오른쪽으로 40dp, 부모 상단에서 80dp 떨어지도록 설정합니다.

첫 Button 뒤에 추가할 XML
<Button
    android:id="@+id/btn2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="버튼 2"
    android:layout_marginStart="40dp"
    android:layout_marginTop="80dp"
    app:layout_constraintStart_toEndOf="@id/btn1"
    app:layout_constraintTop_toTopOf="parent" />

btn1이 Target, btn2가 Source입니다. Start_toEndOf="@id/btn1"를 기억하면 버튼을 나란히 배치하는 문제를 빠르게 풀 수 있습니다.

5. 연결점·마진·바이어스 실습

📄 강의자료 58~77페이지

5-1. Margin: 타깃과의 간격

속성 기능 예시
layout_marginTop 위쪽 거리 80dp
layout_marginBottom 아래쪽 거리 24dp
layout_marginStart 시작 방향 거리 40dp
layout_marginEnd 끝 방향 거리 16dp

강의는 디자인 화면에서 연결선의 숫자를 조절해 마진을 변경합니다. XML에서는 위의 android:layout_margin... 속성을 직접 사용하면 됩니다.

5-2. 부모 화면의 정중앙에 버튼 배치

가로로는 Start·End를, 세로로는 Top·Bottom을 모두 부모에 연결하면 기본 바이어스(0.5) 기준으로 중앙에 배치됩니다.

정중앙에 배치할 버튼 XML
<Button
    android:id="@+id/centerButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="가운데 버튼"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />

5-3. Bias: 중앙에서 얼마나 치우칠지 조정

값 위치 의미
0.0 시작(또는 위쪽) 방향
0.5 중앙 (기본값)
1.0 끝(또는 아래쪽) 방향
중앙보다 조금 위쪽(35% 방향)에 버튼
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="위쪽으로 치우친 버튼"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintVertical_bias="0.35" />
Bias 조건
양쪽 제약이 걸려 있어야 해당 축의 Bias 효과가 나타납니다. Vertical_bias는 위↕아래, Horizontal_bias는 시작↔끝 방향 위치를 조정합니다. 강의 디자인 도구의 35%는 XML에서 0.35입니다.

5-4. match_constraint (0dp)

View의 너비를 0dp로 설정하고 좌우를 부모에 제약하면 그 제약조건 사이의 사용 가능한 가로 공간에 맞게 늘어납니다.

부모 양옆에서 16dp 띄우고 가로로 넓게
<Button
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginEnd="16dp"
    android:text="가로 폭 채우기"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
wrap_content vs match_parent vs 0dp
wrap_content = 내용물 크기 / match_parent = 부모 기준 / 0dp(ConstraintLayout) = 제약조건 사이의 크기. 특히 가운데 빈 공간만 채우는 실습에서는 0dp가 중요합니다.

6. Guideline으로 정렬하기

과제 완성 화면
강의자료 p.84 관련 실습·결과 화면

📄 강의자료 78~86, 94~95페이지

6-1. Guideline의 용도

Guideline은 여러 View를 한 기준선에 정렬하려고 추가하는 보이지 않는 보조선입니다. 디자인 화면에서 위치를 조절할 수 있지만 실행 화면에는 나타나지 않습니다.

  1. res/layout 폴더에서 New → Layout resource file 선택
  2. 예: activity_menu.xml 파일 생성
  3. 디자인 화면에서 Vertical Guideline 또는 Horizontal Guideline 추가
  4. 버튼의 연결점을 Guideline에 연결
  5. 여러 버튼에 같은 Guideline을 적용해 정렬

6-2. 기준선을 지정하는 세 가지 방식

속성 역할
layout_constraintGuide_begin 시작쪽 벽에서 지정 거리만큼
layout_constraintGuide_end 끝쪽 벽에서 지정 거리만큼
layout_constraintGuide_percent 부모 크기의 지정 비율 위치
Guideline — 왼쪽에서 100dp 위치에 세로 기준선
<androidx.constraintlayout.widget.Guideline
    android:id="@+id/guideline"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_begin="100dp" />
Guide를 기준으로 버튼 정렬
<Button
    android:id="@+id/btnMenu"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:text="메뉴 1"
    app:layout_constraintStart_toStartOf="@id/guideline"
    app:layout_constraintTop_toTopOf="parent" />

위 두 코드를 같은 ConstraintLayout의 자식으로 넣으면 버튼의 시작 방향을 Guideline에 맞출 수 있습니다.

자주 틀리는 부분
세로선은 android:orientation="vertical"입니다. 기준선을 @+id/guideline으로 정의했다면, 다른 View에서 참조할 때는 보통 @id/guideline을 씁니다.

7. XML 문법·리소스 ID·크기 단위

📄 강의자료 87~104페이지

7-1. XML 네임스페이스

ConstraintLayout 루트 태그
<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">

    <!-- 이 안에 버튼 등을 배치 -->

</androidx.constraintlayout.widget.ConstraintLayout>
접두어 용도
android: 안드로이드 기본 View 속성 (width, height, id 등)
app: ConstraintLayout 등 라이브러리의 추가 속성
tools: Android Studio의 디자인·미리보기용 속성

7-2. ID 만들기 vs 참조하기

표현 의미
@+id/btn1 btn1이라는 식별자 선언·생성
@id/btn1 이미 만들어 둔 btn1 식별자 참조
parent 현재 부모 레이아웃을 대상(Target)으로 사용

ID는 같은 레이아웃의 View를 구분하고, 다른 View를 연결할 때 Target을 지정하는 데 사용합니다. ID를 바꾸면 해당 ID를 참조하는 곳도 함께 수정해야 합니다.

7-3. 단위: px, dp, sp

단위 용도 기억법
px 실제 픽셀 단위 밀도가 다른 기기에서 체감 크기가 달라질 수 있음
dp / dip 버튼의 크기·마진·여백 UI 크기는 dp
sp 텍스트 크기 글자 크기는 sp
크기와 글자 크기 사용 예
<TextView
    android:layout_width="200dp"
    android:layout_height="wrap_content"
    android:text="안녕하세요"
    android:textSize="18sp" />
태그 닫기 확인
XML에서 <LinearLayout>을 열었다면 마지막에 </LinearLayout>이 필요합니다. 내용이 없는 태그는 />로 끝낼 수 있습니다. 닫는 태그가 없으면 XML 구조 오류로 빌드가 실패합니다.

8. 실습과제 ① 화면 아래쪽에 버튼 2개

과제 완성 화면
강의자료 p.105 관련 실습·결과 화면

📄 강의자료 105~106페이지

강의 과제 원문 요약
새 프로젝트에서 화면 아래쪽에 버튼 두 개가 나란히 보이도록 구성합니다. 강의 이미지는 하단 중앙에 두 버튼이 모인 형태입니다.

완성 XML — 하단 가운데에 두 버튼 나란히 놓기

강의의 결과 형태를 재현하기 위해 수평 Chain을 packed로 설정했습니다. Chain 문법 자체는 과제를 빠르게 구현하기 위한 응용 방법입니다.

activity_main.xml — 완성 예제 1
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:text="버튼 1"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/btn2"
        app:layout_constraintBottom_toBottomOf="parent" />

    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="24dp"
        android:text="버튼 2"
        app:layout_constraintStart_toEndOf="@id/btn1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

왜 이렇게 작성했을까?

필요 조건 속성
아래쪽에 배치 두 버튼 모두 Bottom_toBottomOf="parent"
버튼끼리 나란히 btn1의 End ↔ btn2의 Start 연결
두 버튼 묶음을 중앙으로 수평 Chain + packed
바닥에서 띄우기 layout_marginBottom="24dp"

다른 방법으로는 버튼들을 별도의 가로 LinearLayout에 담은 뒤 그 레이아웃 자체를 하단 중앙에 제약하는 방법도 가능합니다.

9. 실습과제 ② 상단·중앙·하단 3영역

과제 완성 화면
강의자료 p.107 관련 실습·결과 화면

📄 강의자료 107~108페이지

강의 과제 원문 요약
상단과 하단에는 가로로 긴 버튼을 두고, 비어 있는 가운데 공간에는 또 하나의 버튼을 배치합니다. 핵심은 가운데 버튼이 위·아래 버튼 사이 공간을 채우는 구조입니다.

완성 XML — 3개의 영역으로 분할

activity_main.xml — 완성 예제 2
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/topButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="버튼 1"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <Button
        android:id="@+id/bottomButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="버튼 3"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <Button
        android:id="@+id/middleButton"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="버튼 2"
        app:layout_constraintTop_toBottomOf="@id/topButton"
        app:layout_constraintBottom_toTopOf="@id/bottomButton"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

문제를 풀 때 적용할 사고 순서

  1. 상단 버튼: Top_toTopOf="parent" 설정
  2. 하단 버튼: Bottom_toBottomOf="parent" 설정
  3. 상·하단 버튼: 가로 크기 0dp + 부모의 Start/End에 연결
  4. 중앙 버튼: Top을 상단 버튼의 Bottom에 연결
  5. 중앙 버튼: Bottom을 하단 버튼의 Top에 연결
  6. 중앙 버튼: 높이를 0dp로 지정하여 남는 공간 채우기
이 실습의 출제 포인트
중앙 버튼의 layout_height="wrap_content"는 내용물만큼만 차지합니다. 위·아래 사이 공간을 모두 채우려면 layout_height="0dp"와 상하 제약을 함께 사용합니다.

10. 오류 해결·시험 직전 암기표

10-1. 실습하다 막히면 확인할 체크리스트

문제 상황 먼저 확인할 것
XML 빌드 오류 시작·종료 태그 짝, 닫는 />, 속성 따옴표
뷰가 원하는 위치에 안 놓임 가로 제약 1개 이상 + 세로 제약 1개 이상인지 확인
app: 속성 오류 루트에 xmlns:app 선언, ConstraintLayout 사용·의존성 확인
@id/...가 빨간색 대상 View에 android:id="@+id/..."가 있는지 확인
버튼이 안 늘어남 확장할 축의 크기를 0dp로 놓고 양쪽 제약 설정
Bias가 안 먹음 해당 축의 양쪽 제약이 모두 연결되어 있는지 확인
XML 미리보기는 정상인데 실행이 다름 실제 Activity의 setContentView(...) 대상 확인
Java 생성 버튼이 XML 미리보기에 없음 Java에서 런타임 생성한 View는 XML 미리보기에 표시되지 않음
빨간 오류가 아니라 노란 경고 하드코딩 문자열 등 Lint 경고인지 확인

10-2. 시험장에서 바로 보는 1분 암기표

요구사항 바로 쓰는 코드·개념
글자에 맞게 크기 wrap_content
부모에 맞게 크기 match_parent
제약 사이 공간 채우기 0dp + 양방향 Constraint
부모 위쪽에 붙이기 Top_toTopOf="parent"
다른 버튼 아래에 놓기 Top_toBottomOf="@id/btn1"
다른 버튼 오른쪽에 놓기 Start_toEndOf="@id/btn1"
화면 정중앙 Start/End/Top/Bottom 모두 부모에 연결
중앙보다 위로 이동 Vertical_bias="0.35" 같은 값 사용
왼쪽에서 100dp 기준선 layout_constraintGuide_begin="100dp"
화면 비율 30% 기준선 layout_constraintGuide_percent="0.3"
바깥 여백 layout_margin...
뷰 가로 크기 layout_width
뷰 세로 크기 layout_height
UI 크기·간격 dp
글자 크기 sp
한 문장으로 끝내는 Chapter 01
View의 크기는 width·height로 지정하고, ConstraintLayout에서는 연결점과 Target으로 위치를 결정하며, Margin·Bias·Guideline을 이용해 원하는 배치로 조정한다.

학습 범위: 강의자료 「(Part2) Chapter01 — 안드로이드 스튜디오와 친숙해지기」 1~109페이지. 강의의 구성·실습 순서를 기반으로 정리했으며, 시험 과제의 완성 XML과 일부 대체 구현(예: packed Chain)은 이해를 돕기 위해 추가한 응용 예시입니다.

Mobile Programming · Part 2 / Chapter 01 · 실습형 시험 참고 노트

↑ 목차로 이동

PDF 129쪽

Part 2 · Chapter 02 — 레이아웃 익히기

Linear / Relative / Table / Frame / ScrollView의 용도, 구문, 결과를 비교합니다.

1. 레이아웃 5종류 한 번에 비교

📘 강의자료 p.4~15

레이아웃 배치 원리 주요 속성
ConstraintLayout Anchor·제약조건 app:layout_constraint...
LinearLayout 가로 또는 세로로 차례대로 orientation, layout_weight
RelativeLayout 부모 또는 다른 View의 상대 위치 layout_below, layout_alignParent...
TableLayout TableRow로 행/열 구성 stretchColumns, shrinkColumns
FrameLayout 하나의 영역에 여러 View 겹침 visibility, layout_gravity
ScrollView 긴 콘텐츠를 스크롤 ScrollView 안의 하나의 직접 자식 View

강의는 View의 영역과 배경색(background)도 함께 소개합니다. 배경색은 android:background="#EAF2FF"처럼 지정합니다.

2. LinearLayout — orientation, Java 동적 생성

📘 강의자료 p.16~39

실습 / 완성 예제

세로로 버튼 3개 배치

세로 방향이면 위→아래, 가로 방향이면 순서대로 한 줄에 놓입니다.

activity_main.xml — 완성 레이아웃
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="버튼 1" />
    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="버튼 2" />
    <Button android:layout_width="match_parent"
        android:layout_height="wrap_content" android:text="버튼 3" />
</LinearLayout>
세로로 버튼 3개 배치 — 강의자료 속 결과·예시 화면
세로로 버튼 3개 배치 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
수평 방향으로 바꾸려면 orientation="horizontal". 세 버튼이 모두 보이게 하려면 가로폭을 wrap_content 또는 weight를 고려합니다.

Java 코드에서 LinearLayout 생성

LayoutCodeActivity.java — onCreate 내부
LinearLayout mainLayout = new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
        LinearLayout.LayoutParams.MATCH_PARENT,
        LinearLayout.LayoutParams.WRAP_CONTENT);
Button button = new Button(this);
button.setText("Button1");
mainLayout.addView(button, params);
setContentView(mainLayout);
XML 방식 vs Java 방식
setContentView(R.layout.activity_main)은 XML을 표시하지만, setContentView(mainLayout)은 Java에서 생성한 View를 표시합니다. Java로 동적으로 생성한 View는 XML Design 미리보기에서 확인되지 않습니다.

3. gravity와 layout_gravity — 반드시 구별

📘 강의자료 p.40~59

실습 / 완성 예제

텍스트 중앙 정렬 / 뷰 자체 중앙 정렬

같은 center라도 적용 대상이 다릅니다.

LinearLayout 내부에 들어갈 XML
<TextView
    android:layout_width="match_parent"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="내부 글자 중앙" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:text="View 자체 가로 중앙" />
텍스트 중앙 정렬 / 뷰 자체 중앙 정렬 — 강의자료 속 결과·예시 화면
텍스트 중앙 정렬 / 뷰 자체 중앙 정렬 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
gravity는 자신의 내부 내용, layout_gravity는 부모 안에서 자신을 정렬합니다.
속성 대상 자주 쓰는 값
android:gravity View 내부의 내용물 center, left, right, top, bottom
android:layout_gravity 부모 레이아웃에서 View 자신 center, center_horizontal, right 등

4. padding과 layout_margin

📘 강의자료 p.60~67

간격을 만들 때
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    android:padding="12dp"
    android:background="#DDEEFF"
    android:text="여백 비교" />
속성 어디에 생기는가 개별 속성
padding 글자·이미지와 View 테두리 사이의 내부 여백 paddingTop / Bottom / Start / End
layout_margin View 바깥, 인접 View와의 간격 layout_marginTop / Bottom / Start / End
강의 실습 주의
Margin과 Padding을 지나치게 키우면 부모 레이아웃의 공간이 부족해 자식 View가 밀리거나 잘릴 수 있습니다.

5. layout_weight — 남는 공간 비율 분배

📘 강의자료 p.68~78

실습 / 완성 예제

가로폭 1:2 분할

LinearLayout이 horizontal이면 width=0dp, 각 자식의 weight를 1과 2로 설정.

activity_main.xml — 가로 1:2
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <TextView android:layout_width="0dp"
        android:layout_height="60dp" android:layout_weight="1"
        android:gravity="center" android:background="#FFD76A"
        android:text="1" />
    <TextView android:layout_width="0dp"
        android:layout_height="60dp" android:layout_weight="2"
        android:gravity="center" android:background="#8EE3D1"
        android:text="2" />
</LinearLayout>
가로폭 1:2 분할 — 강의자료 속 결과·예시 화면
가로폭 1:2 분할 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
세로 비율 분배라면 orientation="vertical", layout_height="0dp"를 사용. 가로 분배일 때 width=match_parent와 혼용하지 않도록 주의.

6. RelativeLayout — 상대 배치

📘 강의자료 p.79~91

실습 / 완성 예제

다른 버튼 바로 아래 버튼 놓기

이미 존재하는 View의 ID를 참조해 위치를 정합니다.

RelativeLayout 전체 XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button android:id="@+id/first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="첫 번째" />
    <Button android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/first"
        android:layout_alignParentStart="true"
        android:text="두 번째" />
</RelativeLayout>
다른 버튼 바로 아래 버튼 놓기 — 강의자료 속 결과·예시 화면
다른 버튼 바로 아래 버튼 놓기 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
layout_below="@id/first"는 첫 번째 버튼 아래에 배치하라는 뜻.
속성 역할
layout_below / layout_above 다른 View 아래 / 위
layout_toRightOf / layout_toLeftOf 다른 View 오른쪽 / 왼쪽
layout_alignParentTop / Bottom 부모 상단 / 하단 정렬
layout_centerInParent 부모 중앙 정렬

7. TableLayout — 표 형태 레이아웃

📘 강의자료 p.92~102

실습 / 완성 예제

2행 × 3열 버튼 표

TableRow를 2개 배치하고 각 행에 Button 3개를 작성.

activity_main.xml — TableLayout 전체
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:stretchColumns="0,1,2">
    <TableRow>
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="1" />
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="2" />
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="3" />
    </TableRow>
    <TableRow>
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="3" />
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="5" />
        <Button android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:text="6" />
    </TableRow>
</TableLayout>
2행 × 3열 버튼 표 — 강의자료 속 결과·예시 화면
2행 × 3열 버튼 표 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
강의 p.96 TableLayout 실습 화면의 행·열 배치를 참고한 완성 코드입니다.
속성 기능
stretchColumns 지정 열이 남는 폭을 채우도록 확장
shrinkColumns 지정 열이 폭에 맞춰 축소
collapseColumns 지정 열을 숨김
layout_span 셀을 여러 열에 걸치도록 설정

8. FrameLayout — 중첩과 Visibility

📘 강의자료 p.103~114

FrameLayout은 View를 추가한 순서대로 겹치게 합니다. 강의 실습에서는 두 ImageView의 visibility를 전환하는 방식으로 서로 다른 이미지를 보여줍니다.

activity_main.xml — FrameLayout 이미지 중첩
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="300dp">
    <ImageView android:id="@+id/image1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/photo1" />
    <ImageView android:id="@+id/image2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/photo2"
        android:visibility="invisible" />
</FrameLayout>
MainActivity.java — 클릭할 때마다 교대 표시
ImageView image1 = findViewById(R.id.image1);
ImageView image2 = findViewById(R.id.image2);
boolean[] showingFirst = {true};
findViewById(R.id.switchButton).setOnClickListener(v -> {
    showingFirst[0] = !showingFirst[0];
    image1.setVisibility(showingFirst[0] ? View.VISIBLE : View.INVISIBLE);
    image2.setVisibility(showingFirst[0] ? View.INVISIBLE : View.VISIBLE);
});
주의
위 코드는 화면 어딘가에 ID가 switchButton인 버튼이 있다는 전제입니다. FrameLayout에 ImageView를 겹쳐 두고, 버튼은 별도의 부모에 배치하면 편리합니다.
visibility 화면에 보임? 공간 차지?
visible 예 예
invisible 아니요 예
gone 아니요 아니요

9. ScrollView — 수평/수직 스크롤

📘 강의자료 p.115~124

실습 / 완성 예제

큰 이미지를 스크롤해서 보기

강의에서는 큰 이미지와 이미지 교체 버튼을 배치해 수직·수평 스크롤과 이미지 전환을 실습합니다.

activity_main.xml — 세로 스크롤 예제
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <Button android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="이미지 바꾸어 보여주기" />
        <ImageView android:layout_width="match_parent"
            android:layout_height="700dp"
            android:src="@drawable/photo1" />
    </LinearLayout>
</ScrollView>
큰 이미지를 스크롤해서 보기 — 강의자료 속 결과·예시 화면
큰 이미지를 스크롤해서 보기 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
ScrollView의 직접 자식은 하나만 둡니다. 수평 이동이 필요하다면 HorizontalScrollView를 함께 사용하는 방식을 고려하세요.

10. 강의 실습과제 2개 완성 예제

📘 강의자료 p.125~128

실습 / 완성 예제

과제 03 — 두 ImageView 사이에서 이미지 번갈아 보여주기

강의 p.125의 화면처럼 이미지 영역 두 개와 중앙 전환 버튼을 만듭니다.

activity_main.xml — 과제 03 UI
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:padding="16dp" android:orientation="vertical">
    <ImageView android:id="@+id/topImage"
        android:layout_width="match_parent" android:layout_height="180dp"
        android:src="@drawable/photo1" />
    <Button android:id="@+id/moveImage"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" android:text="아래로 이동" />
    <ImageView android:id="@+id/bottomImage"
        android:layout_width="match_parent" android:layout_height="180dp" />
</LinearLayout>
과제 03 — 두 ImageView 사이에서 이미지 번갈아 보여주기 — 강의자료 속 결과·예시 화면
과제 03 — 두 ImageView 사이에서 이미지 번갈아 보여주기 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
실행 코드는 아래에 추가. photo1 이미지 파일을 drawable에 넣어야 합니다.
MainActivity.java — 과제 03, onCreate() 내부
ImageView top = findViewById(R.id.topImage);
ImageView bottom = findViewById(R.id.bottomImage);
Button move = findViewById(R.id.moveImage);
final boolean[] isTop = {true};
move.setOnClickListener(v -> {
    if (isTop[0]) {
        top.setImageDrawable(null);
        bottom.setImageResource(R.drawable.photo1);
        move.setText("위로 이동");
    } else {
        bottom.setImageDrawable(null);
        top.setImageResource(R.drawable.photo1);
        move.setText("아래로 이동");
    }
    isTop[0] = !isTop[0];
});
실습 / 완성 예제

과제 04 — SNS 글 입력 + 글자 수 표시

상단 EditText에 글을 입력하면 글자 수 표시가 변하고 전송·닫기 버튼이 아래에 나타나게 합니다.

activity_main.xml — 과제 04 UI
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:orientation="vertical" android:padding="16dp">
    <EditText android:id="@+id/messageInput"
        android:layout_width="match_parent" android:layout_height="180dp"
        android:gravity="top" android:hint="내용을 입력하세요"
        android:inputType="textMultiLine" android:maxLength="100" />
    <TextView android:id="@+id/countText"
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:gravity="end" android:text="0 / 100" />
    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content" android:orientation="horizontal">
        <Button android:id="@+id/sendBtn" android:layout_width="0dp"
            android:layout_height="wrap_content" android:layout_weight="1"
            android:text="전송" />
        <Button android:id="@+id/closeBtn" android:layout_width="0dp"
            android:layout_height="wrap_content" android:layout_weight="1"
            android:text="닫기" />
    </LinearLayout>
</LinearLayout>
과제 04 — SNS 글 입력 + 글자 수 표시 — 강의자료 속 결과·예시 화면
과제 04 — SNS 글 입력 + 글자 수 표시 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
TextWatcher를 사용하면 글자가 바뀔 때 즉시 길이를 표시할 수 있습니다.
MainActivity.java — 과제 04, onCreate() 내부
EditText input = findViewById(R.id.messageInput);
TextView counter = findViewById(R.id.countText);
input.addTextChangedListener(new TextWatcher() {
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    public void onTextChanged(CharSequence s, int start, int before, int count) {
        counter.setText(s.length() + " / 100");
    }
    public void afterTextChanged(Editable s) {}
});
findViewById(R.id.sendBtn).setOnClickListener(v ->
    Toast.makeText(this, "전송", Toast.LENGTH_SHORT).show());
findViewById(R.id.closeBtn).setOnClickListener(v -> finish());

↑ 목차로 이동

PDF 174쪽

Part 2 · Chapter 03 — 기본 위젯과 드로어블

TextView·Button·EditText부터 Drawable, 이벤트, 사용자 안내 UI, ProgressBar까지.

1. TextView — 글자 표시와 문자열 리소스

📘 강의자료 p.4~20

속성 용도 예
text 표시할 글자 @string/person_name
textColor 글자 색 "#336699"
textSize 글자 크기 "20sp"
textStyle 굵기/기울기 bold / italic
typeface 기본 서체 선택 monospace / serif
maxLines 표시할 최대 행 수 1
ellipsize 길어서 넘치는 글자 처리 end
res/values/strings.xml
<resources>
    <string name="person_name">홍길동</string>
</resources>
activity_main.xml — TextView
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/person_name"
    android:textColor="#336699"
    android:textStyle="bold"
    android:textSize="24sp"
    android:maxLines="1" />
핵심
text 속성에 문자열을 직접 적을 수도 있지만 강의는 strings.xml로 분리해 @string/...으로 참조하는 방법을 권장합니다.

2. Button·CheckBox·RadioButton·RadioGroup

📘 강의자료 p.21~27

위젯 선택 방식 용도
Button 클릭 실행 확인, 실행, 저장
CheckBox 여러 항목 독립적으로 선택 관심사 여러 개 선택
RadioButton + RadioGroup 그룹 안에서 하나 선택 성별·등급 중 하나 선택
실습 / 완성 예제

체크박스 2개 + 라디오 그룹 구성

강의의 버튼 실습은 일반 버튼, 체크박스, 라디오버튼을 함께 사용합니다.

LinearLayout 내부에 넣는 위젯들
<Button android:layout_width="wrap_content"
    android:layout_height="wrap_content" android:text="일반 버튼" />
<CheckBox android:id="@+id/check1"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:text="옵션 A" />
<CheckBox android:id="@+id/check2"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:text="옵션 B" />
<RadioGroup android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <RadioButton android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:text="선택 1" />
    <RadioButton android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:text="선택 2" />
</RadioGroup>
체크박스 2개 + 라디오 그룹 구성 — 강의자료 속 결과·예시 화면
체크박스 2개 + 라디오 그룹 구성 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
RadioButton만 여러 개 두는 것과 달리 RadioGroup으로 묶어야 상호 배타적 선택을 구현하기 쉽습니다.

CheckBox·RadioButton 상태 읽기

Java — CompoundButton 주요 메서드
CheckBox box = findViewById(R.id.check1);
boolean selected = box.isChecked();
box.setChecked(true);
box.setOnCheckedChangeListener((buttonView, isChecked) -> {
    Log.d("CHECK", "selected=" + isChecked);
});

CheckBox와 RadioButton은 CompoundButton의 하위 클래스입니다. isChecked()로 현재 상태를 읽고 setChecked(true/false)로 값을 변경할 수 있습니다.

3. EditText — 입력값, 키보드, 포커스

📘 강의자료 p.28~31, 40~49

activity_main.xml — 문자열 입력
<EditText
    android:id="@+id/nameInput"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="이름을 입력하세요"
    android:inputType="text"
    android:selectAllOnFocus="true" />
MainActivity.java — 입력값 읽기
EditText input = findViewById(R.id.nameInput);
String name = input.getText().toString();
input.setText("기본 이름");
속성/메서드 의미
hint 아무 값도 입력하지 않았을 때 안내 문구
inputType 키보드·입력 유형: text, number 등
selectAllOnFocus 포커스를 받으면 기존 글자 전체 선택
cursorVisible 커서 표시 여부
getText().toString() 문자열 추출
ellipsize 너무 긴 문자의 생략 위치 지정
setText() 표시/입력 값 변경
setSelection() 커서 위치 지정

추가 실습 — 텍스트 커서·말줄임·줄 간격

속성/메서드 강의자료에서의 기능
selectAllOnFocus 포커스 시 전체 텍스트 선택
cursorVisible 커서 표시/숨김
getSelectionStart() / getSelectionEnd() 현재 선택 범위 확인
setSelection(위치) 커서를 특정 위치로 이동
selectAll() 글자 전체 선택
lineSpacingMultiplier 줄 간격의 배수 지정
lineSpacingExtra 줄 간격에 추가 공간 제공
ellipsize 텍스트 생략 위치: start/middle/end
textColorHint hint 문자열 색상
EditText — 입력 길이 제한, 100자
<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="100자 이내로 입력"
    android:maxLength="100"
    android:inputType="textMultiLine" />
EditText — 값이 바뀔 때마다 처리하기(TextWatcher)
input.addTextChangedListener(new TextWatcher() {
    @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
    @Override public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.d("INPUT", "length=" + s.length());
    }
    @Override public void afterTextChanged(Editable s) {}
});
강의 p.48~49
TextWatcher의 핵심 메서드는 beforeTextChanged / onTextChanged / afterTextChanged입니다. 길이 제한은 maxLength 또는 InputFilter.LengthFilter로 지정할 수 있습니다.

4. ImageView·ImageButton

📘 강의자료 p.32~39

구분 ImageView ImageButton
목적 이미지 콘텐츠 표시 이미지로 된 버튼
이벤트 클릭 리스너를 추가하면 처리 가능 버튼처럼 클릭 이벤트 처리에 사용
공통 src / scaleType / background src / scaleType / background
ImageView — res/drawable/flower.png 가정
<ImageView
    android:id="@+id/photo"
    android:layout_width="160dp"
    android:layout_height="160dp"
    android:src="@drawable/flower"
    android:scaleType="centerCrop"
    android:contentDescription="꽃 사진" />
속성 기능
src 또는 app:srcCompat 실제 표시할 이미지 리소스
background View 배경
scaleType="fitCenter" 사진 전체가 보이도록 맞춤
scaleType="centerCrop" 영역을 채우며 넘치는 부분은 잘라냄

5. Drawable — 배경, State, Shape, Layer

📘 강의자료 p.50~74

강의는 res/drawable 폴더에 이미지 또는 Drawable XML을 저장한 다음 android:background="@drawable/..."로 적용하는 방법을 실습합니다.

종류 목적 대표 XML
일반 배경 이미지 이미지를 배경에 설정 android:background="@drawable/..."
State Drawable 버튼을 누르거나 선택한 상태에 따른 이미지 변경 <selector> + <item>
Shape Drawable 사각형·테두리·색상·그라데이션 제작 <shape>, <solid>, <corners>, <stroke>
Layer Drawable 여러 도형/이미지 중첩 <layer-list>
실습 / 완성 예제

손가락 그림 버튼 — 눌렀을 때 이미지 변경

finger.png와 finger_pressed.png 같은 이미지를 drawable에 넣고 상태별로 교체합니다.

res/drawable/finger_drawable.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true"
        android:drawable="@drawable/finger_pressed" />
    <item android:drawable="@drawable/finger" />
</selector>
손가락 그림 버튼 — 눌렀을 때 이미지 변경 — 강의자료 속 결과·예시 화면
손가락 그림 버튼 — 눌렀을 때 이미지 변경 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
상태 조건을 갖는 항목을 기본 항목보다 위에 둡니다.
버튼 XML — 상태 Drawable 연결
<Button android:layout_width="120dp"
    android:layout_height="100dp"
    android:background="@drawable/finger_drawable" />
실습 / 완성 예제

둥근 테두리의 Shape Drawable 버튼

셰이프 드로어블로 색상, 테두리, 둥근 모서리를 직접 정의합니다.

res/drawable/rect_drawable.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#DDEEFF" />
    <stroke android:width="2dp" android:color="#336699" />
    <corners android:radius="12dp" />
    <padding android:left="16dp" android:right="16dp"
        android:top="12dp" android:bottom="12dp" />
</shape>
둥근 테두리의 Shape Drawable 버튼 — 강의자료 속 결과·예시 화면
둥근 테두리의 Shape Drawable 버튼 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
solid=내부 색, stroke=테두리, corners=모서리, gradient=그라데이션. XML 파일을 background로 지정.
그라데이션 Drawable 예시
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient android:startColor="#E2F2FF"
        android:endColor="#587ECA"
        android:angle="90" />
</shape>
Layer-list 예시 — 도형 겹치기
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item><shape><solid android:color="#224488" /></shape></item>
    <item android:left="5dp" android:top="5dp">
        <shape><solid android:color="#FFFFFF" /></shape>
    </item>
</layer-list>

6. 이벤트 — Click / Touch / Gesture / Key

📘 강의자료 p.75~106

이벤트 API 알아야 할 차이
클릭 setOnClickListener 한 번 눌렀다는 동작
터치 setOnTouchListener + MotionEvent DOWN / MOVE / UP 과정
제스처 GestureDetector Scroll / Fling / LongPress 등 해석
키 onKeyDown(keyCode,event) 어떤 키가 눌렸는지 판별
Java — 클릭 리스너
findViewById(R.id.button1).setOnClickListener(v -> {
    Toast.makeText(this, "클릭", Toast.LENGTH_SHORT).show();
});
실습 / 완성 예제

터치 이벤트로 손가락 움직임 감지

MotionEvent.ACTION_DOWN / MOVE / UP를 구분합니다.

MainActivity.java — View 터치 리스너
View touchArea = findViewById(R.id.touchArea);
touchArea.setOnTouchListener((v, event) -> {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.d("TOUCH", "DOWN"); break;
        case MotionEvent.ACTION_MOVE:
            Log.d("TOUCH", "MOVE " + event.getX()); break;
        case MotionEvent.ACTION_UP:
            Log.d("TOUCH", "UP"); break;
    }
    return true;
});
터치 이벤트로 손가락 움직임 감지 — 강의자료 속 결과·예시 화면
터치 이벤트로 손가락 움직임 감지 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
return true는 이 리스너가 이벤트를 처리했다는 뜻. 터치 좌표는 getX() / getY()로 얻습니다.
GestureDetector — 스크롤/플링 감지
GestureDetector detector = new GestureDetector(this,
    new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onDown(MotionEvent e) { return true; }
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            Log.d("GESTURE", "scroll " + distanceX);
            return true;
        }
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2,
                float velocityX, float velocityY) {
            Log.d("GESTURE", "fling " + velocityX);
            return true;
        }
    });
findViewById(R.id.touchArea).setOnTouchListener((v,e) ->
    detector.onTouchEvent(e));
KeyEvent — onKeyDown 재정의
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        Toast.makeText(this, "뒤로가기", Toast.LENGTH_SHORT).show();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
강의 시점과 최신 API 구분
강의는 onKeyDown으로 BACK을 처리합니다. 최신 뒤로가기 구현에는 OnBackPressedDispatcher 계열 API를 권장하지만, 시험에서 강의 예제를 재현할 때는 교수님이 지정한 방식을 우선 확인하세요.

7. 화면 방향 전환과 상태 저장

📘 강의자료 p.107~137

방향 회전 시 기본적으로 Activity가 재생성될 수 있습니다. 강의는 res/layout과 res/layout-land에 같은 이름의 XML을 두는 방식과 onSaveInstanceState()를 통한 상태 저장, configChanges를 통해 직접 구성 변경을 받는 방식을 실습합니다.

개념/파일 역할
res/layout/activity_main.xml 기본 화면 레이아웃
res/layout-land/activity_main.xml 가로 화면 레이아웃
onSaveInstanceState(Bundle) 재생성 전 저장할 상태 기록
onCreate(Bundle) 저장한 상태 복원 등에 활용
android:configChanges 선언한 구성 변경을 Activity가 직접 처리
onConfigurationChanged() 직접 처리하도록 선언한 구성 변경 수신
MainActivity.java — 회전에도 텍스트 값 복원
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putString("saved_name",
            ((EditText)findViewById(R.id.nameInput)).getText().toString());
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState != null) {
        String name = savedInstanceState.getString("saved_name", "");
        ((EditText)findViewById(R.id.nameInput)).setText(name);
    }
}
AndroidManifest.xml — 특정 구성 변경 직접 처리 시 activity 속성 예시
<activity
    android:name=".MainActivity"
    android:configChanges="orientation|screenSize" />
MainActivity.java — Activity 클래스 내부
@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Log.d("ROTATION", "가로 방향");
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Log.d("ROTATION", "세로 방향");
    }
}
주의
configChanges를 지정해 Activity 재생성을 피하는 방식은 모든 회전 처리의 기본 해법이 아닙니다. 상태 유지와 대체 레이아웃이 목적이라면 기본 재생성 + 상태 복원을 먼저 이해하세요.

8. Toast·Snackbar·AlertDialog

📘 강의자료 p.138~158

기능 용도 동작
Toast 간단한 상태 알림 잠시 나타났다가 사라짐
Snackbar 하단 안내 및 실행 취소 액션 action 버튼을 제공할 수 있음
AlertDialog 확인/취소 선택 사용자에게 대화상자 표시
Log.d(...) 개발 디버깅 메시지 Logcat에 출력
실습 / 완성 예제

Toast — 짧은 메시지 띄우기

강의는 기본 Toast와 모양·위치를 바꾸는 실습을 다룹니다.

MainActivity.java — 기본 Toast
Toast.makeText(this, "저장되었습니다.", Toast.LENGTH_SHORT).show();
Toast — 짧은 메시지 띄우기 — 강의자료 속 결과·예시 화면
Toast — 짧은 메시지 띄우기 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
강의의 사용자 정의 Toast는 별도의 레이아웃/Drawable을 사용합니다. 최신 OS에서는 Toast의 위치·외형 사용자 정의에 제약이 있습니다.
실습 / 완성 예제

Snackbar — 화면 아래에서 메시지 표시

Toast와 달리 Snackbar에는 사용자 액션을 연결할 수 있습니다.

MainActivity.java — Snackbar
Snackbar.make(findViewById(android.R.id.content),
    "삭제되었습니다.", Snackbar.LENGTH_LONG)
    .setAction("취소", v -> {
        // 삭제 취소
    }).show();
Snackbar — 화면 아래에서 메시지 표시 — 강의자료 속 결과·예시 화면
Snackbar — 화면 아래에서 메시지 표시 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
com.google.android.material.snackbar.Snackbar 의존성과 import가 필요합니다.
실습 / 완성 예제

AlertDialog — 확인/취소 대화상자

타이틀, 내용, 버튼을 설정해 대화상자를 띄웁니다.

MainActivity.java — AlertDialog
new AlertDialog.Builder(this)
    .setTitle("삭제 확인")
    .setMessage("정말 삭제하시겠습니까?")
    .setPositiveButton("삭제", (dialog, which) -> {
        // 삭제 처리
    })
    .setNegativeButton("취소", null)
    .show();
AlertDialog — 확인/취소 대화상자 — 강의자료 속 결과·예시 화면
AlertDialog — 확인/취소 대화상자 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
setTitle=제목, setMessage=내용, setPositiveButton=긍정 선택, setNegativeButton=취소 버튼.

9. ProgressBar·ProgressDialog·SeekBar

📘 강의자료 p.159~169

기능 역할 관련 API
ProgressBar 작업 진행 정도 또는 진행 중임을 표시 max, progress, setProgress()
ProgressDialog 진행 상태를 대화상자 형태로 표시(강의 실습) show(), dismiss()
SeekBar 사용자가 값을 드래그해서 조절 setOnSeekBarChangeListener()
activity_main.xml — 수평 프로그레스바
<ProgressBar
    android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="100"
    android:progress="40" />
MainActivity.java — 진행값 변경
ProgressBar bar = findViewById(R.id.progressBar);
bar.setMax(100);
bar.setProgress(70);
ProgressDialog 주의
강의 실습에는 ProgressDialog가 등장하지만 현재 Android에서는 deprecated(사용 비권장) 상태입니다. 실제 신규 개발에서는 ProgressBar와 Dialog를 조합하거나 현대적인 대체 UI를 고려합니다. 시험에서는 강의의 의미·역할을 알아두세요.

ProgressBar 관련 메서드 추가

Java — ProgressBar 값을 조금씩 증가/감소
ProgressBar bar = findViewById(R.id.progressBar);
bar.setProgress(20);
bar.incrementProgressBy(10); // 20 -> 30
bar.incrementProgressBy(-5); // 30 -> 25

강의에는 ProgressDialog.STYLE_SPINNER로 원형 진행 대화상자를 띄우고 dismiss()로 종료하는 실습도 있습니다. 최신 개발에서는 사용 비권장(deprecated)이므로 신규 앱 구현과 시험 내용은 구별해야 합니다.

10. 강의 실습과제 완성 예제

📘 강의자료 p.170~173

실습 / 완성 예제

과제 05 — 모양이 서로 다른 버튼 2개

각 버튼에 다른 Shape Drawable 배경을 지정합니다.

res/drawable/button_blue.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#235CAD" />
    <corners android:radius="12dp" />
    <stroke android:width="2dp" android:color="#10386B" />
</shape>
과제 05 — 모양이 서로 다른 버튼 2개 — 강의자료 속 결과·예시 화면
과제 05 — 모양이 서로 다른 버튼 2개 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
두 번째 버튼용 Drawable에서는 색상과 모서리를 달리합니다.
res/drawable/button_orange.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#F08B21" />
    <corners android:radius="2dp" />
    <stroke android:width="2dp" android:color="#A4510B" />
</shape>
LinearLayout 내부 — 다른 배경 적용
<Button android:layout_width="150dp"
    android:layout_height="wrap_content" android:text="버튼 1"
    android:background="@drawable/button_blue" />
<Button android:layout_width="150dp"
    android:layout_height="wrap_content" android:text="버튼 2"
    android:background="@drawable/button_orange" />
실습 / 완성 예제

과제 06 — SeekBar 값으로 ProgressBar 조절

SeekBar를 움직이면 ProgressBar 진행 값도 즉시 바뀝니다.

activity_main.xml — LinearLayout 내부
<SeekBar android:id="@+id/seekBar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" android:max="100" />
<ProgressBar android:id="@+id/progressBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" android:max="100" />
과제 06 — SeekBar 값으로 ProgressBar 조절 — 강의자료 속 결과·예시 화면
과제 06 — SeekBar 값으로 ProgressBar 조절 — 강의자료 속 결과·예시 화면 (강의 PDF에서 발췌)
구현 포인트
두 위젯의 max를 똑같이 맞춰야 값이 그대로 대응합니다.
MainActivity.java — 과제 06, onCreate() 내부
SeekBar seekBar = findViewById(R.id.seekBar);
ProgressBar progressBar = findViewById(R.id.progressBar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        progressBar.setProgress(progress);
    }
    @Override public void onStartTrackingTouch(SeekBar seekBar) {}
    @Override public void onStopTrackingTouch(SeekBar seekBar) {}
});

↑ 목차로 이동

6개 강의 종합

시험 직전 빠른 검색표

문제 유형에 따라 가장 먼저 찾을 속성과 API입니다.

실습에서 특히 많이 발생하는 빌드·레이아웃 오류

증상 원인 / 해결
XML 문서 구조 오류 <LinearLayout>을 열었으면 </LinearLayout>로 닫기
cannot find symbol 변수 이름·ID·클래스 이름 오타 확인 (savedInstanceState 등)
Java에서 만든 Button이 Preview에 안 보임 XML Preview는 Java onCreate 실행 결과가 아님. 앱을 실행해야 함
빌드는 되는데 다른 화면이 나옴 AndroidManifest.xml의 MAIN / LAUNCHER Activity 확인
앱이 실행하자마자 종료 Logcat에서 Exception과 실패한 Java 줄 확인
이미지가 안 나옴 res/drawable 리소스와 @drawable/파일명 확인
ConstraintLayout에서 위치가 이상함 가로·세로 제약조건 확인
문제 표현 바로 찾아볼 속성·메서드
버튼을 화면 가운데 ConstraintLayout 4방향 제약 or LinearLayout gravity
View 내부 글자를 가운데 android:gravity="center"
버튼 자체를 가운데 android:layout_gravity 또는 ConstraintLayout 제약
가로 세로 배열 LinearLayout orientation
두 영역 1:2 비율 layout_weight / 크기 0dp
버튼을 특정 View 아래 RelativeLayout layout_below / ConstraintLayout Top_toBottomOf
여백이 너무 붙음 padding / layout_margin
위치 비율 기준 정렬 Guideline percent / bias
이미지 겹침 / 교대 FrameLayout / View.INVISIBLE, VISIBLE
스크롤 가능한 화면 ScrollView / HorizontalScrollView
손가락 DOWN / MOVE / UP setOnTouchListener / MotionEvent
빠르게 튕김 감지 GestureDetector.onFling
입력 문자열 읽기 EditText.getText().toString()
글자 길이 실시간 TextWatcher.onTextChanged
버튼 눌림 그래픽 Drawable selector / state_pressed
버튼 모서리·테두리 Shape Drawable: solid / corners / stroke
짧은 알림 Toast.makeText(...).show()
취소 가능한 하단 메시지 Snackbar.make().setAction().show()
선택을 요구하는 팝업 AlertDialog.Builder
작업 진행 막대 ProgressBar.setProgress
드래그로 진행값 바꾸기 SeekBar.OnSeekBarChangeListener
화면 회전 상태 유지 onSaveInstanceState / layout-land / configChanges
강의 출처와 구현 범위
업로드된 Part 1: Ch.01(7쪽)·Ch.03(55쪽)·Ch.04(9쪽) 및 Part 2: Ch.01(109쪽)·Ch.02(129쪽)·Ch.03(174쪽)를 기준으로 작성했습니다. 강의 본문의 개념·실습 요구를 중심으로 구성했고, 일부 완성코드·라이브러리/API 최신 주의사항은 학습을 위해 보충한 내용입니다. 실행 전 프로젝트의 이미지 리소스, import, ID, 의존성을 확인하세요.

END — Mobile Programming · Full Course Practice Reference