이 튜토리얼에서는 Android 앱에서 뷰(View)를 동적으로 추가하고 제거하는 방법을 단계별로 살펴봅니다. 사용자가 전화번호 목록처럼 반복되는 입력 필드를 필요할 때마다 자유롭게 늘리거나 줄일 수 있는 UI를 만들 때 이 기법이 유용하게 활용됩니다.
1단계 — 새 프로젝트 생성
Android Studio에서 File ⇒ New Project를 선택해 새 프로젝트를 만들고, 프로젝트 생성에 필요한 모든 정보를 입력합니다.
2단계 — res/layout/activity_main.xml 작성
메인 화면 레이아웃 파일에 아래 코드를 추가합니다. 상위 LinearLayout 안에는 초기 입력 행(EditText + Spinner + 삭제 버튼)과 '필드 추가' 버튼이 배치됩니다.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" xmlns:tools="https://schemas.android.com/tools" xmlns:app="https://schemas.android.com/apk/res-auto" android:id="@+id/parent_linear_layout" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:layout_margin="5dp" android:orientation="vertical"> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal" > <EditText android:id="@+id/number_edit_text" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="5" android:inputType="phone"/> <Spinner android:id="@+id/type_spinner" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:entries="@array/types" android:gravity="right" /> <Button android:id="@+id/delete_button" android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" android:background="@android:drawable/ic_delete" android:onClick="onDelete"/> </LinearLayout> <Button android:id="@+id/add_field_button" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:layout_marginLeft="5dp" android:layout_marginRight="5dp" android:background="#555" android:layout_gravity="center" android:onClick="onAddField" android:textColor="#FFF" android:text="Add Field" android:paddingLeft="5dp"/> </LinearLayout>
3단계 — res/layout/field.xml 작성
동적으로 추가할 개별 행(row)의 레이아웃 파일입니다. 메인 레이아웃의 첫 번째 행과 동일한 구조로 구성되어 있습니다.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="50dp" android:orientation="horizontal"> <EditText android:id="@+id/number_edit_text" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="5" android:inputType="phone"/> <Spinner android:id="@+id/type_spinner" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="3" android:entries="@array/types" android:gravity="right" /> <Button android:id="@+id/delete_button" android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" android:background="@android:drawable/ic_delete" android:onClick="onDelete"/> </LinearLayout>
4단계 — res/values/strings.xml 작성
Spinner에서 사용할 항목 배열(휴대폰/회사/집)과 앱 이름을 정의합니다.
<resources> <string name="app_name">Sample</string> <string-array name="types"> <item>Mobile</item> <item>Office</item> <item>Home</item> </string-array> </resources>
5단계 — res/values/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> <item name="actionBarSize">36dip</item> </style> </resources>
6단계 — src/MainActivity.java 작성
핵심 로직은 크게 두 부분으로 나뉩니다. onAddField() 메서드는 LayoutInflater를 이용해 field.xml 레이아웃을 인플레이트한 뒤, '필드 추가' 버튼 바로 앞 위치에 새 행을 삽입합니다. onDelete() 메서드는 클릭된 버튼의 부모 뷰(즉, 해당 행 전체)를 상위 LinearLayout에서 제거합니다.
package com.example.sample;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
private LinearLayout parentLinearLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
parentLinearLayout=(LinearLayout) findViewById(R.id.parent_linear_layout);
}
public void onAddField(View v) {
LayoutInflater inflater=(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View rowView=inflater.inflate(R.layout.field, null);
// 새 행을 '필드 추가' 버튼 앞에 추가합니다.
parentLinearLayout.addView(rowView, parentLinearLayout.getChildCount() - 1);
}
public void onDelete(View v) {
parentLinearLayout.removeView((View) v.getParent());
}
}참고: 최신 Android Studio 프로젝트(AndroidX 적용 환경)에서는 import android.support.v7.app.AppCompatActivity; 대신 import androidx.appcompat.app.AppCompatActivity;를 사용해야 합니다.
7단계 — manifests/AndroidManifest.xml 작성
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="https://schemas.android.com/apk/res/android" package="com.example.sample"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
앱 실행하기
이제 애플리케이션을 실행해 보겠습니다. 실제 Android 스마트폰이 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 도구 모음의 Run 아이콘을 클릭하세요. 실행 옵션에서 자신의 모바일 기기를 선택하면, 기기 화면에 다음과 같은 기본 화면이 표시됩니다.


'Add Field' 버튼을 누를 때마다 새로운 입력 행이 추가되고, 각 행의 삭제 버튼을 누르면 해당 행이 즉시 사라지는 것을 확인할 수 있습니다. 이 방식은 연락처 등록, 주문 항목 입력 등 사용자가 항목 수를 직접 조절해야 하는 다양한 화면에 응용할 수 있습니다.