예를 들어서 메인 레이아웃 안에 부분 화면을 띄워본다고 가정하자. 기본적으로 메인 레이아웃은 setContentView()메소드를 사용해서, 인플레이션 과정을 거친다. 그렇다면 부분화면은 어떻게 띄워야할까? 처음에 setContentView()로 부분화면을 객체화할 수 있지 않을까? 생각해 봤지만, 부분화면을 인플레이션하지 못한다고 한다. 이 이유는 setContentView()메소드는 Activity에 보일 View를 지정할 때 사용하는 메소드이기 때문이라고 한다.
부분화면이 메인 액티비티에 띄워지는 과정은 아래 과정과 같다(소스코드 관점)
- 부분화면 레이아웃 인플레이션
- 부분화면 레이아웃이 담길 ViewGroup지정
- ViewGroup을 메인 레이아웃에 띄운다.
우선 activity_menu.xml, sub1.xml, ActivityMenu.java 파일을 생성하자
< activity_menu.xml >
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:hint="@string/textt"/>
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@string/btn_default"
/>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
< sub1.xml >
<?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="@string/sub_view_name"
android:textSize="28sp"/>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/checkBox"
android:text="@string/Check_box"/>
</LinearLayout>
< ActivityMenu.java >
package com.example.menuactivity;
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;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class ActivityMenu extends AppCompatActivity {
LinearLayout container;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
container = findViewById(R.id.container);
Button btn = findViewById(R.id.btn1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LayoutInflater inflater = LayoutInflater.from(ActivityMenu.this);
// LayoutInflater.inflate(int resource(constant),ViewGroup root, Boolean attachToRoot)
inflater.inflate(R.layout.sub1,container,true);
TextView t = container.findViewById(R.id.textView);
t.setText("Loading Complete");
}
});
}
}
위 예제 코드는 Activity화면에 있는 버튼을 클릭하면 빈 LinearLayout에 부분화면이 나타나는 예시이다. 핵심 부분 몇가지를 살펴보자
부분화면 인플레이션
부분 화면을 인플레이션 하기 위해서는 LayoutInflator라는 클래스를 사용해야한다. LayoutInflator객체는 기본적으로 시스템 서비스 클래스이다. 가장 기본적으로 (LayoutInflator)getSystemService(Context.LAYOUT_INFLATE_SERVICE) 방법을 사용해서 LayoutInflator객체를 참조할 수 있다. 하지만 LayoutInflator클래스의 클래스 메소드인 from(Context context)을 사용해도 괜찮다. from()메소드 또한 내부적으로 getSystemService()를 호출하기 때문이다.
LayoutInflater inflater = LayoutInflater.from(ActivityMenu.this);
- (LayoutInflator) getSystemService(Context.LAYOUT_INFLATER_SERVICE)
- from(Context context)
여기서는 from()메소드를 사용해 보았으며, Context로는 현재 클래스의 컨텍스트를 전달하였다.
그 다음 인플레이션 된 부분화면의 ViewGroup을 지정해 주어야한다. View 그룹을 지정해 주기 위해서는 LayoutInflater클래스의 inflate메소드를 사용해야한다.
inflater.inflate(R.layout.sub1,container,true);
inflate 메소드의 parameter를 살펴보자
- param1 : XML 레이아웃 리소스
- param2 : ViewGroup 지정(부모 컨테이너)
- param3 : 부모 컨테이너에 붙일것인지를 결정한다
- true : 즉시 부모컨테이너에 해당 레이아웃을 붙인다
- false : 부모컨테이너에 바로 붙이지 않는다. 나중에 뷰를 붙이는 코드를 실행하면 붙일 수 있다.
이 inflate메소드는 View객체를 반환한다.
이제 앱을 실행시켜 보자. 다만 주의할 점은 이 예시는 따로 XML레이아웃 파일과 소스코드 파일을 만들어서 했기 때문에, 앱이 처음으로 시작됐을때 이 예시에서 만든 레이아웃을 나오게끔 해야한다. 이를 설정하기 위해서는 AndroidManifest 파일을 수정해 주어야 한다. <activity> 태그의 android:name 속성을 .ActivityMenu(혹은 자신이 작성한 소스코드 파일 명)로 바꿔준다
<activity
android:name=".ActivityMenu"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
바꿔준 후 실행되면 첫 실행시 방금 작성했던 레이아웃이 나오는것을 볼 수 있다.
번외 : attatchToRoot를 false로 설정한 부분화면 처리하기
위에서 LayoutInflater 객체의 inflate메소드의 attatchToRoot 속성을 False로 지정하면, 바로 부모 컨테이너( = 뷰그룹)에 붙지 않는다고 하였다. 그리고 이는 나중에 뷰를 붙이는 코드를 이용해서 부모 컨테이너에 붙일 수 있다고 하였다. 부모 컨테이너에 뷰를 붙이기 위해서는 ViewGroup클래스의 addView(View child) 메소드를 이용해 주면 된다. 위에서 말했듯이, LayoutInflater의 inflate메소드는 View객체를 반환한다. 그렇기 때문에, 이 인플레이션된 부분화면 View객체를 부모 컨테이너의 addView()메소드를 이용하여 붙이면 되는것이다. 예시를 조금 변형하여 왼쪽 버튼을 누르면 부분화면을, 인플레이션하고, 오른쪽 버튼을 누르면 부모 컨테이너에 부착되었다는 알림 Toast가 나오며, 부모 컨테이너에 부분화면을 보여준다고 가정하자. 그럼 아래와 같이 코드를 작성할 수 있다.
< activity_menu.xml >
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:hint="@string/textt"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_weight="1"
android:text="@string/btn_default"
/>
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:text="Add to parent"/>
</LinearLayout>
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
< sub1.xml >
<?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="@string/sub_view_name"
android:textSize="28sp"/>
<CheckBox
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/checkBox"
android:text="@string/Check_box"/>
</LinearLayout>
< ActivityMenu.java >
package com.example.menuactivity;
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;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class ActivityMenu extends AppCompatActivity {
LinearLayout container;
View v;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
container = findViewById(R.id.container);
Button btn = findViewById(R.id.btn1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//LayoutInflater inflater = LayoutInflater.from(ActivityMenu.this);
// LayoutInflater.inflate(int resource(constant),ViewGroup root, Boolean attachToRoot)
v = inflater.inflate(R.layout.sub1,container,false);
TextView t = v.findViewById(R.id.textView);
t.setText("Loading Complete");
}
});
Button btn2 = findViewById(R.id.btn2);
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ActivityMenu.this, "Attach To Parent ViewGroup!", Toast.LENGTH_SHORT).show();
container.addView(v);
}
});
}
}
'Android' 카테고리의 다른 글
[Android] 앱 내에서 다크모드 비활성화하기 (0) | 2022.05.09 |
---|---|
[Android] 여러 화면간 전환하기 (0) | 2022.04.08 |
[Android] Inflation이란? (0) | 2022.04.08 |
[Android] Progressbar 사용하기 (0) | 2022.04.07 |
[Android] Snackbar사용하기 (0) | 2022.04.07 |