본문 바로가기
Project/Android

[Android] [팁 계산기] 3. XML로 레이아웃 만들기

by eoieiie 2024. 3. 26.

 

드디어 설레는 실습입니다. 들어가기에 앞서, 안스(안드로이드 스튜디오) 안에서 XML파일은 Split View로 지정하고 보시는  걸 추천드립니다. XML과 UI레이아웃을 동시에 볼 수 있습니다. 

 

split view 설정방법

 

XML파일에서 각 요소를 클릭해 보면 상응하는 뷰가 디자인 에디터에서 선택됩니다. 반대의 경우도 마찬가지입니다. 수정되는 내용을 한눈에 확인할 수 있습니다. 

 

이제 한번 레이아웃을 맛깔나게 만들어 봅시다.

 

TextView 삭제


를 하면 아래 부분만 남습니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
	
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

</androidx.constraintlayout.widget.ConstraintLayout>

 

여기다가 16px 패딩을 추가합니다. 이는 UI가 화면 가장자리에서 비좁아지지 않도록 합니다. 패딩은 여백이랑 비슷하지만, 외부에 공간을 추가하는 대신 레이아웃 내부에 공간을 추가합니다. 참고로 16px은 UI디자인에서 자주 사용되는 일반적인 패딩 값 중 하나이며 여러 가이드라인에서 자주 권장되는 디폴트 패딩 값입니다. 화면 가장자리와 너무 가깝지도, 너무 멀지도 않게 위치하도록 하는 최적의 값이랄까...

 

근데 안드로이드는 요즘 px대신에 dp를 사용하도록 권장합니다. dp는 디바이스의 화면 밀도(density)에 따라 크기가 조정되는 단위로, 높은 밀도의 디바이스에서는 더 많은 픽셀로 변환하고 작아 보이게 하여 다양한 해상도의 디바이스에서 일관된 UI 크기와 레이아웃을 제공해서 그렇답니다. 하라면 해야죠 뭐 

<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:padding="16dp"
    
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

</androidx.constraintlayout.widget.ConstraintLayout>

 

비용 입력란 추가


이제 사용자가 비용을 입력할 수 있는 UI요소를 추가해 보도록 하겠습니다. 여기서는 EditText요소를 사용합니다. 

 

위와 같이 EditText에는 빨간색으로 밑줄이 그어져 있는데, 제약 조건이 없어서 그렇습니다. ConstraintLayout의 하위 요소에는 레이아웃이 정렬 방법을 알 수 있도록 제약 조건이 필요합니다. 제약 조건과 몇 가지 요소를 더 추가하고 각 요소를 설명해보자면, 

 

<EditText
    android:id="@+id/cost_of_service"
    android:layout_width="160dp"
    android:layout_height="wrap_content"
    android:hint="@string/cost_of_service_hint"
    android:inputType="numberDecimal"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

 

  • android:id="@+id/cost_of_service": 요소의 고유한 리소스 이름이며 모두 소문자에 밑줄로 구분되어야 합니다.
  • android:layout_width="match_parent": EditText의 너비를 부모 요소의 너비와 일치시킨다는 뜻입니다.
  • android:layout_height="wrap_content": 이는 높이가 내부 콘텐츠의 높이와 같다는 의미입니다. 텍스트 한 줄만 있을 것이므로 괜찮습니다.
  • android:hint="Cost of Service" 이렇게 사용하면 안 되고 안스의 res -values - strings.xml 파일로 가서  <string name="cost_of_service_hint">Cost of Service</string>라고 추가해 줘야 사용가능합니다. 이는 문자열을 하드코딩(변하지 않는 값을 코드에 포함시키는 것) 하지 않고 문자열 리소스를 통해 참조하기 위함입니다. (유지보수와 번역, 다국어 지원 등에 유리함.)
  • android:inputType="numberDecimal": 사용자가 화면의 입력란에 소숫점이 있는 숫자를(숫자만) 입력할 수 있습니다.

제약 조건은 다음과 같습니다:

  • app:layout_constraintStart_toStartOf="parent": UI 요소의 시작 부분(왼쪽)을 부모 뷰의 시작 부분(왼쪽)에 맞춤(UI 요소가 화면의 가장 왼쪽에 배치되도록 함)
  • app:layout_constraintTop_toTopOf="parent": UI 요소의 상단 부분을 부모 뷰의 상단 부분에 맞춥니다(UI 요소가 화면의 상단에 배치되도록 함)

참고로 제약 조건의 이름은 layout_constraint<Source>_to<Target>Of 형식을 따릅니다. Sourse는 현재 뷰를, Target은 현재 뷰가 제한되는 타겟 뷰의 가장자리를 나타냅니다. 즉 Start뷰는 parent요소의 가장자리로 제한되어 있다는 말이 됩니다. 

 

팁을 드리자면 한줄한줄 지우고 추가하면서 디자인 에디터가 어떻게 변하는지 이해하려고 해 보세요!

 

이제 EditText요소는 다음과 같습니다:

<EditText
    android:id="@+id/cost_of_service"
    android:layout_width="160dp"
    android:layout_height="wrap_content"
    android:hint="@string/cost_of_service_hint"
    android:inputType="numberDecimal"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

 

서비스 질문 추가

 


이제 서비스가 어땠나요? 라는 질문을 추가해 보겠습니다. 질문은 텍스트니까, 질문 프롬프트에 TextView를 추가합니다. 

 <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/How_was_the_service" />

 

 

이렇게 보일겁니다. 이제 필요한 것들을 더 추가할 겁니다. 조건은 다음과 같습니다:

 

  1. How was the service는 서비스 비용 입력란 아래에 둘 것
  2. 가로 방향으로는 상위 요소의 시작 가장자리에 맞게 정렬할 것(상위 요소는 constraintlayout입니다.)

그래서 아래와 같은 내용을 추가했습니다. 

app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cost_of_service"

 

여기서 잠시 layout_constraint에 대해서 설명을 하고 넘어가겠습니다. 

 

  1. app:layout_constraintStart_toStartOf: 해당 요소의 시작 부분을 다른 요소의 시작 부분과 연결합니다.
  2. app:layout_constraintTop_toTopOf: 해당 요소의 상단을 다른 요소의 상단과 연결합니다.
  3. app:layout_constraintStart_toEndOf: 해당 요소의 시작 부분을 다른 요소의 끝 부분과 연결합니다.
  4. app:layout_constraintTop_toBottomOf: 해당 요소의 상단을 다른 요소의 하단과 연결합니다.

그래서 위 코드블록은

"How was the service?"의 시작 부분을 부모 요소(ConstraintLayout)의 시작 부분(왼쪽 가장자리)에 위치하도록 하고,

상단 부분은 "@id/cost_of_service"의 하단과 연결하라는 뜻이 되겠네요!

 

마지막으로 리소스 ID를 추가합니다. 방금 전 app:layout_constraintTop_toBottomOf="@id/cost_of_service" 에서 "@id/cost_of_service"가 바로 리소스 ID입니다. 나중에 뷰를 더 추가하여 서로에게 맞게 제한할 때 이 뷰를 참조할 수 있으니까, ID는 항상 생성하는 것이 좋습니다. 

android:id="@+id/service_question"

 

최종적으로 XML은 다음과 같이 표시됩니다. 

<?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:padding="16dp"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/cost_of_service"
        android:hint="Cost of Service"
        android:layout_height="wrap_content"
        android:layout_width="160dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:inputType="numberDecimal"/>

    <TextView
        android:id="@+id/service_question"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="How was the service?"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/cost_of_service"/>

</androidx.constraintlayout.widget.ConstraintLayout>

 

다음 포스팅에서는 팁 옵션을 추가해 보도록 하겠습니다.

 

댓글