애플리케이션 구성하기
레이아웃 인플레이션 이해
전체화면 중에서 일부분만을 XML 레이아웃으로 정의한 후 보여주는 과정
- 일부화면을 분리하여
/res/layout/button.xml
파일에 정의
- 이 파일의 내용은
LayoutInflater
객체를 사용해 뷰그룹 객체로 객체화(인플레이션)한다
- 그 후 메인 레이아웃에 추가 한다
- 먼저
activity_menu.xml
을 생성한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="버튼을 눌러 부분 화면을 추가하세요"
android:textSize="20dp" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="추가하기" />
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
|
- 부분화면으로 추가할 XML 레이아웃
sub1.xml
을 생성한다
sub1.xml
은 activity_menu.xml
파일에 들어있는 버튼을 클릭했을 때 그 레이아웃에 들어있는 리니어 레이아웃 안에 추가되도록 만들어준다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| <?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:background="#ffaaccff">
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="부분화면1"
android:textSize="30dp" />
<CheckBox
android:id="@+id/checkBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="동의합니다" />
</LinearLayout>
|
MenuActivity.java
를 수정해준다
getSystemService()
메소드를 사용해 LayoutInflater
객체를 참조하고 있다
- 그리고 그 객체의
inflate()
메소드를 호출하면서 파라미터로 R.layout.sub1
과 container
객체를 전달
- 이는 리니어 레이아웃 객체에 sub1.xml 파일의 레이아웃을 설정하라는 의미이다
inflate()
메소드가 사용되면 레이아웃에 정의된 뷰들은 내부적으로 객체화 과정을 거친다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| package com.example.samplelayoutinflater;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
public class MenuActivity extends AppCompatActivity {
LinearLayout container;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
// 리니어 레이아웃의 id는 container
container = (LinearLayout) findViewById(R.id.container);
Button button = (Button) findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view){
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// inflate() 메소드가 사용되면 레이아웃에 정의된 뷰들은 내부적으로 객체화 과정을 거친다
inflater.inflate(R.layout.sub1, container, true);
// sub1.xml파일이 메모리에 객체화 되었기 때문에 그 안에 들어있던 체크박스가 참조 가능
CheckBox checkbox = (CheckBox) container.findViewById(R.id.checkBox);
checkbox.setText("로딩되었어요.");
}
});
}
}
|
- 매니페스트 파일을 수정한다
1
2
3
4
5
6
7
8
| <activity android:name=".MainActivity"></activity>
<activity android:name=".MenuActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
|
- 레이아웃을 객체화 하는 과정은 매우 중요 !!
화면 구성과 화면 간 전환
일반적으로 안드로이드는 하나의 화면을 하나의 액티비티라고 생각할 수 있다
따라서 앱을 구성하는 각 화면은 액티비티로 구현되며 이러한 액티비티끼리 전환하는 과정은 각각의 액티비티를 필요에 따라 띄우거나 닫는 과정과 같다
화면 구성과 화면 간 전환
- 두 액티비티간 전환을 위해 새로운 액티비티를 생성(menu_activity)
- main_activity에서 띄워줄 액티비티를 선언
-
새로 띄운 액티비티로부터 받은 응답을 처리
- 새로운 액티비티를 생성한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| <?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"
tools:context=".MenuActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="돌아가기"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| package com.example.sampleintent;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MenuActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
Button button = findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("name", "mike");
setResult(RESULT_OK, intent);
finish();
}
});
}
}
|
onClick()
메소드 안에서는 Intent 클래스를 사용해 intent 객체를 만들어서 setResult()
메소드를 호출한다
setResult()
- 새로 띄운 액티비티에서 이전 액티비티로 인텐트를 전달하고 싶을 때 사용되는 메소드
setResult(응답 코드, 인텐트)
- 현재 액티비티를 띄웠던 액티비티로 응답 코드와 인텐트가 전달된다
- 메인 액티비티에서 새로 액티비티 띄우기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| package com.example.sampleintent;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
public static final int REQUEST_CODE_MENU = 101;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onButton1Clicked(View v) {
Intent intent = new Intent(getApplicationContext(), MenuActivity.class);
startActivityForResult(intent, REQUEST_CODE_MENU);
}
}
|
- 새로운 액티비티를 띄울 때
startActivityForResult()
메소드를 호출
startActivity()
메소드처럼 새로운 화면을 띄우는데 사용하지만
- 새로 띄운 액티비티로부터 응답을 받을 수 있다
- 첫번째 파라미터로는 컨텍스트 객체가 전달되는데, 액티비티 객체는 컨텍스크가 될 수 있기 때문에 일반적으로 this 변수를 사용
- 하지만 여기서는 이벤트 처리 메소드 안에서 this 변수로 MainActivity 객체를 참조할 수 없으므로
getApplicationContext()
메소드를 사용해 해당 애플리케이션의 Context 객체를 참조한다
REQUEST_CODE_MENU
는 새로운 액티비티를 띄울 때 보낼 요청 코드로 정의
- 이 값은 마음대로 지정할 수 있은 ㅏ앱에 들어갈 액티비티가 여러개 있을 수 있으므로 서로 중복되지 않게 지정한다
- 여기서 인텐트 객체는 액티비티를 띄울 목적으로 사용되며, 액티비티 간에 데이터를 전달하는 데에도 사용될 수 있다
- 새로띄운 액티비티로부터 받은 응답을 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| ...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_MENU) {
Toast.makeText(getApplicationContext(),
"onActivityResult 메소드 호출, 요청코드 : " + requestCode + ", 결과코드 : " + resultCode,
Toast.LENGTH_LONG).show();
if (resultCode == RESULT_OK) {
String name = data.getExtras().getString("name");
Toast.makeText(getApplicationContext(), "응답으로 전달된 name : " + name,
Toast.LENGTH_LONG).show();
}
}
}
|
본 문서는 Do it! 안드로이드 앱 프로그래밍 책을 보고 작성하였습니다.