이외 기타 참고자료: 링크
[이 포스팅에서 다루는 내용]
레이아웃 개념
Activity에서 레이아웃 리소스를 로드하기
ID
생성한 레이아웃(View)를 앱에서 참조하기
1. findByViewId()
2. View binding
레이아웃 개념
레이아웃은 앱에서 사용자 UI를 위한 구조를 정의한다.
View나 ViewGroup 객체들이 레이아웃 요소를 구성한다.
View 객체는 widgets라고도 불리며, Button, TextView같은 것이 있다.
ViewGroup 객체는 layouts이라고 불리며, 예를 들어 LinearLayout, ConstraintLayout와 같은 레이아웃 구조가 있다.
각 레이아웃 파일은 View 또는 ViewGruop객체를 가진다. '루트 요소'라고 한다. 이러한 루트 요소를 정의한 후에 더 많은 레아아웃 객체 또는 위젯을 하위 요소로 추가할 수 있다. 그러면 계층 구조를 가지게 되는 것이다.
사용 예를 들면, 어떤 XML파일은 LinearLayout을 사용하고, 그 안에 TextView, Button 등을 가질 수 있다.
태그에 대한 간단한 설명이 필요한 분들께
시작 태그와 종료 태그 개념
<name>
<first>John</first>
<middle>Fitzgerald Johansen</middle>
<last>Doe</last>
</name>
태그는 전달하는 정보를 감싼다
<first>: 시작 태그
</first>: 종료 태그
<first>Jone</first>: 하나의 엘리먼트
단일 태그는 <태그이름/>의 형식을 가지고 있다.
위 예제를 가져온 곳: 링크
레이아웃 리소스를 로드하기
각 레이아웃 XML파일은 View 레이아웃 리소스 안에 컴파일된다.
[MainActivity에서 레이아웃 리소스를 로드하기]
setContentView() 메서드를 통해서 레아아웃 리소스를 부를 수 있다.
레아아웃 리소스 로드는 onCreate() 콜백 메서드에서 이루어진다.
주의점: 자동으로 생성된 XML이 아니라 사용자가 추가적으로 만든 XML을 객체화시키려면 inflate()를 사용해야 한다. 다음은 setContentView()에 대한 추가설명이다.
" 기본적으로, 안드로이드에서는 화면(Activity 단위)을 하나 만들면
소스 코드 하나와 화면을 구성하는 XML 하나 이렇게 2개가 생성된다.
이때, setContentView() 함수가 바로 자동으로 만들어진 XML을 객체화시키는 Inflate 동작이다. "
출처: https://soo0100.tistory.com/1017 [Thank you for everything in the world]
그러나 setContentView()에서도 내부적으로 layout inflater가 실행된다고 한다.
" LayoutInflater이란?
LayoutInflater은 XML에 미리 정의해둔 틀을 실제 메모리에 올려주는 역할을 한다.
Inflater 단어의 뜻이 부풀리다라는 의미로써 LayoutInflater라는 단어에서도 유추가 가능하다.
즉, LayoutInflater는 XML에 정의된 Resource를 View 객체로 반환해주는 역할을 한다.
우리가 매번 사용하는 onCreate() 메서드에 있는 setContentView(R.layout.activity_main) 또한 Inflater 역할을 한다.
(이 함수의 내부에서 layout inflater가 실행되어 view들을 객체화한다.)
출처: https://www.crocus.co.kr/1584 [Crocus] "
<setContentView()의 레아아웃 리소스 로드 예시>
만약 XML 레이아웃 이름이 main_layout.xml 이라면
ID
TextView같은 View객체에는 id를 지정할 수 있다.
xml파일의 Design창의 속성에서 이렇게 id를 text1로 지정해보자.
그리고, 코드창에서 xml코드릃 확인해보자. 빨간 밑줄 친 부분이 ID구문이다.
ID구문에 대한 추가설명..
XML 태그 내에서 ID의 구문은 다음과 같습니다.
android:id="@+id/my_button"
문자열 시작 부분에 있는 앳 기호(@)는 XML 파서가 ID 문자열의 나머지를 파싱하고 확장하여 ID 리소스로 식별해야 한다는 것을 나타냅니다. 더하기(+) 기호는 이것이 새 리소스 이름이며, 이것을 반드시 생성하여 리소스에 추가해야 한다는 것을 뜻합니다(R.java 파일에서).
Android 프레임워크는 다른 ID 리소스도 아주 많이 제공합니다.
Android 리소스 ID를 참조할 때에는 더하기 기호는 필요하지 않지만 android 패키지 네임스페이스를 다음과 같이 반드시 추가해야 합니다.
android:id="@android:id/empty"
android 패키지 네임스페이스가 들어가면 이제 로컬 리소스 클래스에서가 아니라 android.R 리소스 클래스에서 ID를 참조하게 됩니다.
생성한 View(레이아웃)를 앱에서 참조하기
View(Wegets)을 생성하고, ID에 할당했다면
일반적으로 MainActivity의 onCreate() 메서드에서 View 객체의 인스턴스를 생성한다.
바로 아래 사진처럼 findViewById()메서드를 사용하여 해당 ID를 가진 View를 참조할 수 있지만, Android Studio 3.6 이상에서 'View binding'을 이용할 수 있다. (View binding이 findViewById()를 대체한다. )
1. findViewById() 메서드 이용
참고: 4.1버전부터 kotlin extension 플러그인이 디폴트에서 해제되었다. 많은 문제점을 가지고 있다고 한다. 이로써 findViewById()도 권장사항이 아니다. 2번에 소개하는 VIew binding이 권장사항이다.
findViewById의 문제점을 알고 싶다면
서로 다른 두 View의 ID가 동일하다면, 한 View의 ID를 다른 View에서 참조할 수 있고, 이는 에러를 일으킬 수 있다. 그러므로 ID는 고유하게 사용해야 한다.
이 말은 즉, 유효하지 않은 뷰 ID를 참조할 수 있다. null의 가능성이 있고, 유형이 맞지 않을 수 있다.
그래서 2번에 안내하는 View binding을 권장한다.
2. View binding (Android Studio 3.6 이상) - 안드로이드문서참조
ㅡ모듈에 추가해야 한다:
모듈 수준의 그레이들 파일에서 android{...} 내부에 다음 내용을 추가한다.
이렇게 모듈에 추가하고 나면 XML 레이아웃 파일의 바인딩 클래스가 생성된다.
바인딩 클래스 이름은 xml파일 이름을 카멜 표기법으로 변환하고 끝에 Binding을 붙인 이름으로 생성된다.
예를들어 activity_main.xml의 바인딩 클래스 이름은 ActivityMainBinding이다.
바인딩 클래스가 생성되고 나서야 해당 레이아웃의 View의 id에 접근할 수 있다
이제 이 생성된 바인딩 클래스를 Activity에 연결해보자.
ㅡView Binding을 사용하고자 하는 Activity에 Binding 클래스 변수를 선언한다.
ㅡ그리고 onCreate() 콜백 메서드에서 Binding 클래스 변수를 초기화한다.
변수에 Binding 클래스 객체를 담는 거다. inflate()메서드를 통해서!
ㅇinflate() 메서드 : xml에 쓰여 있는 view(layout)의 정의를 실제 view객체로 만드는 역할을 한다. 즉, 인스턴스화.
ㅡ그리고나서 레이아웃 리소스를 로드하자. onCreate() 단계에서 로드했었다.
"레이아웃 리소스 로드하기" 기억 안나면 여기..
binding변수의 root뷰를 가져온다. 이것이 레이아웃 리소스(View)이고, 이를 아까처럼 setContentView()의 인자로 넘기면 된다. 그럼 화면상의 활성 뷰로 만들 수 있다.
이제 다음과 같이 View 객체를 id로 참조할 수 있다. Binding 클래스 객체를 통해서 접근해야 한다.
+
+
Activity에서가 아닌 Fragment에서 View binding을 사용하고 싶으면, onCreate() 콜백이 아니라 onCreateView() 콜백에서 위와 같은 단계를 거치면 된다.
예시 보기는..
생성된 binding 클래스를 인스턴스화하기 위해서 마찬가지로 inflate()를 이용한다. 즉, Fragment에서 사용할 binding클래스 객체를 얻는다.
그리고 역시 해당 binding 클래스의 root를 가져온다. 그럼 루트 뷰를 가져오게 되고, 이것을 onCreateView() 메서드에서 return하면 화면상의 활성 뷰로 만들 수 있다.
그럼 역시 이제 binding 클래스 객체를 통해서 View를 참조할 수 있다. 즉, 아래 사진과 같이 해당 뷰의 id에 접근 가능하다.
프래그먼트를 끝내도 binding객체는 살아있으니 꼭 onDestroyView() 단계에서 객체 참조를 정리하자.
'JAVA' 카테고리의 다른 글
안드로이드 생존코딩(오준석) - 챕터9 전자액자 Fragment 상세설명 - 안드로이드 스튜디오 4.1 (0) | 2021.01.25 |
---|---|
동반객체와 팩토리 패턴 | companion object, Factory Method Pattern (0) | 2021.01.24 |
안드로이드 - ViewPager2를 이용한 슬라이더 학습 (0) | 2021.01.19 |
쓰다 만 전자액자 포스팅 with 감격의 순간 ㅠㅅㅠ (0) | 2021.01.18 |
[안드로이드] ViewPager, ViewPager2, RecyclerView, Fragment [작성중] (0) | 2021.01.18 |