[Android] 여러 화면 간 전환
처음 안드로이드 프로젝트를 생성하면, XML파일(activity_main.xml)과 자바 소스 파일(MainActivity.java)이 생성된다.
자바 소스코드의 R.layout.activity_main 코드는 이 두 파일을 연결해준다. (R은 res폴더를, layout은 res폴더 안의 layout폴더를 의미함)
인플레이션은 XML 레이아웃에 정의된 내용(디자인도구를 이용해 만든 버튼, 텍스트뷰 등..)이 메모리에 객체화 되는 과정을 말한다. (버튼의 상태를 정의)
자바 코드에 정의하고, 실제로 객체가 되려면 메모리에 기억장소를 할당받아야 한다. 그 역할을 인플레이션이라고 한다.
MainActivity 코드에서 setContentView가 인플레이션 과정을 수행한다.
위의 코드에서 setContentView가 버튼의 생성보다 나중에 위치하는데, 이런 경우 에러가 나타난다.
setContentView 메서드를 먼저 수행한 후에 버튼을 생성하거나, 이벤트 처리 코드를 작성하거나 해야 한다.
정리하면 setContentView() 메서드는 화면에 나타낼 뷰를 지정하는 역할을 하고, XML레이아웃의 메모리 상에 객체화하는 역할을 한다.
전체 화면 중에서 일부분만을 차지하는 화면 구성요소를 XML레이아웃에서 로딩해서 보여줄 수 있을까? (부분화면)
setContentView 메서드는 액티비티의 화면 전체를 설정하는 역할만 수행할 수 있다.
LayoutInflater 클래스를 사용해서 위를 해결할 수 있다. (시스템 서비스로 제공되는 클래스이다)
activity_main 에서 setContentView 메서드로 activity_main XML파일을 받고, 부분 화면은 LayoutInflater 객체를 사용해 인플레이션 한 후 메인 레이아웃에 추가할 수 있다.
안드로이드에서 화면은 소스코드와 화면의 구성이 분리돼있다.
화면 전체는 MainActivity에서 setContentView 메서드를 통해 인플레이션 과정을 거치는데,
부분 화면을 다룰 경우에는 수동으로 인플레이션 과정을 수행해야 한다.
(AndroidManifest.xml : 이 앱이 어떤 액티비티로 구성돼있는지 알려줌)
위의 코드를 살펴보자.
전체 레이아웃의 안쪽 리니어 레이아웃의 ID는 container이다. (레이아웃 안에 리니어 레이아웃을 겹쳐서 만들었다)
부분 화면의 xml레이아웃의 이름을 sub1로 설정하고 새로 만들었다.
setContentView메서드의 인자로 activity_main 대신 다른 액티비티를 받았다.
밑의 LayoutInflater 부분을 살펴보자.
getSystemService의 반환타입은 Object라서 형변환을 해 준 것이 보인다.
inflater는 레이아웃을 받아들이고 특정 위젯에 바로 보여주는 메서드인 inflate를 가진다.
inflate 메서드를 이용해 container를 ID로 가지는 리니어 레이아웃 객체에 sub1 파일의 레이아웃을 설정한다. (객체화)
이제 객체화한 container를 사용해 버튼을 눌렀을 때 text를 설정하도록 했다.
부분 레이아웃은 container 객체에 설정돼있으므로 container 객체의 findViewById메서드를 사용해야 한다. (container.findViewById)
코드를 짠 후 AndroidManifest 파일에서 추가한 액티비티 태그를 추가해 줘야 한다.
사실 XML레이아웃을 새로 만들지 않고 코드에서 직접 Button과 같은 뷰들을 부모 컨테이너에 추가할 수 있다. 하지만, 소스코드가 복잡해지는 문제가 발생하니 되도록 XML레이아웃을 사용하자.
메인 액티비티에서 띄워야 할 화면이 많아지면 이렇게 하나하나 부분 레이아웃을 보여주는 방식으로 처리하기 어려운 문제가 생기고, 화면을 닫고 원래의 메인 화면으로 돌아올 때 데이터를 새로 적용해야 하는 경우가 생긴다.
이 문제를 해결하기 위해 액티비티에 대해 자세히 알아보자.
안드로이드 앱을 구성하는 요소 중 하나인 액티비티는 여러 가지로 존재할 수 있다.
여러 가지 액티비티를 담아놓는 그릇을 액티비티 스택이라고 한다.
하나의 태스크는 스택에 있는 액티비티들로 구성된다.
핸드폰의 하드웨어 버튼인 BACK버튼을 누르면 현재 액티비티를 제거하고 이전 액티비티로 돌아간다.
이 기능을 활용해 프로그래밍하면 여러 화면간 전환을 구현할 수 있지 않을까?
(사용자가 방문한 액티비티는 어딘가에 기억함)
바로 코드를 통해 알아보자.
버튼을 눌렀을 때, 다른 액티비티에 정보를 전달하게 하기 위해 Intent객체를 만들었다. (다른 액티비티를 호출하려면 Intent 객체가 필요하다.)
putExtra 메서드로 key값과 그에 해당하는 value를 넣고
setResult 메서드로 새로 띄운 액티비티에서 이전 액티비티로 인텐드를 전달한다. (응답을 보낸다)
finish 메서드로 현재 액티비티를 없앴다.
이 앱의 MainActivity 코드를 살펴보자.
현재 컨텍스트의 MenuActivity를 지정해 인텐트 객체를 만들었다. (인텐트 객체는 액티비티를 띄울 목적으로 이용된다)
메인 액티비티에서 이전에 본 액티비티를 띄워야 한다.
startActivity 메서드는 새로운 액티비티를 띄울 때 사용하고, startActivvityForResult 메서드는 새로운 액티비티를 띄우고 띄웠던 액티비티로부터 원래의 액티비티로 돌아오면서 응답을 받는 역할을 한다.
지금같은 경우는 startActivityForResult 메서드로 응답까지 받도록 했다.
startActivityForResult메서드를 사용해 액티비티를 띄울 때 요청 코드인 REQUEST_CODE_MENU와 intent객체를 이용해 값을 받아와 처리한다.
하지만 이거로는 부족하다. 다른 액티비티로부터 응답을 처리하는 부분을 작성해야 한다.
onActivityResult 메서드를 통해 응답받는다. (단축키 Ctrl + o)
REQUEST_CODE_MENU 코드로 호출했기 때문에 REQUEST_CODE_MENU코드로 받아온 정보를 검사한다.
어떤 액티비티로부터 응답을 받은 것인지 구분하고 새 액티비티에서 처리한 결과가 정상인지 아닌지를 구분한다. (Activity.RESULT_OK 상수를 전달하는 방법을 사용했는데, 임의로 만든 코드를 전달할 수도 있다.)
지금까지 한 가지 화면을 더 추가할 때와, 여러 가지 액티비티를 사용해 여러 가지 화면을 전환할 때를 알아봤다.
인텐트는 기존에 만들어진 요소를 가져다가 사용하는 역할을 한다고 배웠다.
(지도 서비스가 필요하면 지도를 구현한 서비스를 불러오고, 전화 걸기 서비스가 필요하면 전화걸기를 구현한 서비스를 불러오는 등)
물론, 이것 말고도 내가 만든 액티비티간의 전환이 필요할 때도 인텐트를 사용한다.
이렇게 인텐트는 앱 구성요소가 해야 할 일을 지정한다.
(인텐트 생성 -> 메서드를 통해 인텐트를 시스템에 전달 -> 시스템이 명령을 확인하고 그에 따라 행동)
명시적 인텐트 : 호출한 대상을 확실히 알 수 있는 경우 ex.앱 A의 B컴포넌트를 구동시켜라.
암시적 인텐트 : 호출할 대상이 달라질 수 있는 경우 (MIME 타입에 따라 시스템에서 적절한 다른 앱의 액티비티를 찾고 그 액티비티를 활용. MIME은 특정 포맷으로 MIME타입을 구분하는걸 말함) ex. 지도를 보여줄 수 있는 컴포넌트이면 아무거나 오케이.
'Mobile > Android' 카테고리의 다른 글
[Android] 서비스와 브로드캐스트 수신자 (0) | 2021.11.06 |
---|---|
[Android] 인텐트와 프로그레스바 사용하기 (0) | 2021.10.28 |
[Android] 대화상자 사용하기 (0) | 2021.10.18 |
[Android] 간단한 계산기 만들기 (0) | 2021.10.18 |
[Android] 이벤트 처리 (0) | 2021.10.18 |
댓글
이 글 공유하기
다른 글
-
[Android] 서비스와 브로드캐스트 수신자
[Android] 서비스와 브로드캐스트 수신자
2021.11.06 -
[Android] 인텐트와 프로그레스바 사용하기
[Android] 인텐트와 프로그레스바 사용하기
2021.10.28 -
[Android] 대화상자 사용하기
[Android] 대화상자 사용하기
2021.10.18 -
[Android] 간단한 계산기 만들기
[Android] 간단한 계산기 만들기
2021.10.18