안드로이드 애플리케이션의 가장 기본적인 소프트웨어 아키텍처(architecture)는 컴포넌트(component) 기본의 개발인 것이다.
앞에서 다뤄 본 것처럼 안드로드에서는 '액티비티', '서비스', '콘텐츠 프로바이더', '브로드캐스트 리시버' 등 4개의 컴포넌트를 취사선택해서 앱을 구성한다.
이 중 화면을 출력하는 컴포넌트는 액티비티(activity)뿐이다.
결국, 안드로이드에서 화면을 출력하려면 액티비티를 만들어야 하고, 이 액티비티가 런타임 때 실행되어야 한다.
앱의 실행 단위인 컴포넌트인 액티비티는 버튼, 문자열, 이미지 등을 출력해주어야만 화면이 나온다. 이러한 클래스를 뷰(View) 클래스라고 부른다.
결국, 안드로이드 UI프로그램은 다양한 뷰를 화면에 출력하는 구조이다.
🟥 Activit 화면
🟦 View
위 그림은 페이스북 메신저 앱의 첫 화면이다.
하나의 액티비티 클래스에 5개의 뷰 클래스로 화면을 구성하여 출력한 결과이다.
액티비티에서 뷰를 출력하는 기능을 제공하는 함수는 setContentView()이다.
이 함수는 두가지 형태로 제공한다.
▪︎ public void setContentView(View view)
▪︎ public void setContentView(int layoutResId)
액티비티 내에서 화면 출력을 위한 setContentView() 함수를 실행하지 않는다면 에러는 발생하지 않지만 화면에는 아무것도 나오지 않는다. 액티비티가 화면이고, 액티비티 화면의 내용이 뷰라고 보면 된다.
안드로이드에서 UI를 작성하는 방법은 액티비티의 자바코드로 작성하는 방법과 레이아웃 XML을 작성하는 방법이 있다.
다음 버튼 2개가 있는 화면을 자바 코드와 레이아웃 XML으로 각각 출력해보자.
자바 코드로 모든 뷰를 직접 생성하며, 메서드를 이용하여 뷰 설정을 일일이 지정하는 방법이다. 이렇게 준비한 뷰를 setContentView() 함수의 매개변수로 넘겨서 화면을 출력한다.
새로 생성한 모듈에 자동으로 만들어진 MainActivity.java 파일을 작성했다. 위의 코드는 LinearLayout에 버튼 2개를 생성해서 추가한 다음, 화면에 출력하는 코드다. 버튼 2개가 LinearLayout에 포함되었으므로 setContentView() 함수에 linear만 전달해도 버튼 2개가 함께 출력된다.
안드로이드 스튜디오에서 레이아웃 XML 파일을 작성하는 방법은 두 가지이다. 하나는 디자인(Design)모드로서 개발자가 필요한 뷰를 마우스로 끌어놓기(Drag & Drop)하는 방법이고, 다른 하나는 텍스트(Text)모드로 직접 XML 코드를 작성하는 방법이다. 여기서는 직접 XML 코드를 작성할 것이다.
레이아웃 XML 파일에서 작성할 때는 뷰 클래스명을 XML의 태그명으로 작성하고, 필요한 속성을 XML attribute로 지정하여 작성하면 된다.
UI 구성을 레이아웃 XML로 작성할 때 뷰 태그에 다양한 속성을 추가할 수 있으며, 속성들은 뷰에 따라 다르다. 모든 뷰에 공통으로 지정할 수 있는 중요 속성들에 대해 알아보자.
안드로이드에서 가장 많이 이용되는 뷰 중 하나는 TextView이며, 화면에 문자열을 출력하는 뷰이다. 레이아웃 XML에 TextView를 사용하는 예를 통해 뷰의 중요 속성을 알아보자.
뷰의 식별자 속성으로 필수 속성은 아니며 필요할 때 추가할 수 있다.
<TextView
android:layout_width="wrap_contnet"
android:layout_height="wrap_contnet"
android:text="hello" />
화면에 뷰의 내용을 출력만 하는 목적이라면 id 속성을 생략해도 화면 출력에는 문제가 없지만 이렇게 하면 레이아웃 XML에 등록하여 자동으로 생성된 뷰 객체를 자바 코드에서 이용할 수 없다.
뷰 객체를 자바 코드에서 직접 생성한게 아니기 때문에 객체명을 알 수 없기 때문이다.
이때, 이용하는 속성이 id이다.
<TextView
android:id="@+id/myText"
android:layout_width="wrap_contnet"
android:layout_height="wrap_contnet"
android:text="hello" />
위 코드처럼 android:id="@+id/myText"라고 설정하면 개발자가 임의의 이름으로 id 값을 하나 부여한 것이 된다. 이렇게 지정한 id값은 앱의 R.java 파일에 등록된다.
이제 자바 코드에서 뷰 객체를 획득해서 이용할 수 있다.
자바 코드에서 findViewById() 함수를 사용한다.
TextView myTextView=findViewById(R.id.myText);
정리하자면, 자바 코드에서 setContentView() 함수를 호출하면 레이아웃 XML 파일의 내용을 화면에 출력하고, XML에 정의한 객체가 자동으로 생성된다. 이렇게 생성된 객체는 R.java의 변수, 즉 XML에서 등록한 id값을 매개변수로 하여 findViewById() 함수로 획득해서 사용할 수 있다.
뷰 크기를 지정하는 속성으로 가로, 세로 크기를 결정하며, 선언하지 않으면 빌드할 때 에러가 발생한다.
<TextView
android:layout_width="wrap_contnet"
android:layout_height="wrap_contnet"
android:text="hello"
android:background="#0000FF"
android:textColor="#FFFFFF"/>
위의 코드는 layout_width, layout_height를 이용하여 "hello"라는 문자열이 화면에 보일 때, 뷰가 화면에서 차지해야 하는 크기를 지정하는 예이다.
크기 속성값은 다음 4가지로 지정할 수 있다.
▪︎ wrap_contnet
▪︎ match_parent
▪︎ fill_parent
▪︎ 100px
match_parent와 fill_parent는 의미상 동일하므로 어떤 속성값을 주더라도 결과는 같다. 이 값의 의미는 해당 뷰의 크기를 부모 계층의 뷰가 지정한 크기에 꽉 들어차게 자동으로 결정하라는 의미다.
wrap_content는 해당 뷰의 내용을 화면에 보이기 위한 적절한 크기를 계상해서 결정하라는 의미다. 문자열 폰트 크기를 늘리면 그만큼 뷰의 크기도 늘어난다.
또는 100xp처럼 수치로 뷰의 크기를 직접 설정할 수도 있다.
위의 코드는 LinearLayout 하위에 TextView 두 개가 있다.
결과는 다음과 같다.
margin은 뷰와 뷰 사이의 간격을 지정하는 속성이며, padding은 뷰 내부에서 내용과 뷰의 테두리 간의 간격을 지정하는 속성이다.
뷰의 기본 margin과 padding 값이 있는데, 이를 증감하고자 할 때 사용하는 속성이다.
margin과 padding 속성을 이용하면 간격이 네 방향 모두 같은 크기로 설정되며, 단일 방향의 간격만 조정하고 싶다면 다음 속성을 이용하면 된다.
▪︎ 단일 방향 margin 속성
: layout_marginleft, layout_marginRight, layout_marginTop, layout_marginBottom
▪︎ 단일 방향 padding 속성
: paddingLeft, paddingRight, paddingTop, paddingBottom
안드로이드의 모든 뷰는 기본적으로 clickable 속성을 지정하지 않아도 사용자의 클릭 이벤트나 롱클릭 이벤트에 반응하지만 TextView, ImageView은 명시적으로 지정(true)하지 않으면 클릭 이벤트가 발생하지 않는데, 이때 사용되는 것이 clickable 속성이다.
뷰를 화면에 출력할지를 지정하는 속성이다. 기본값은 "true"이며, "invisible", "gone"으로 지정하면 화면에 안 보이게 할 수 있다.
gone과 invisible의 차이점은 둘 다 화면에 출력은 안 되지만, gone은 확보하지 못하고 invisible은 크기 확보가 가능하다.
visibility 속성은 액티비티 화면을 레이아웃 XML로 구성할 때 초기에 특정 뷰를 화면에 출력하지 않으려는 의도로 사용한다. 이때 자바 코드에서는 setVisibility() 함수를 이용하여 뷰의 표시 상채를 조정한다.
※ visibility = "gone"
✏️ 하나는 이론을 정리하고 다음 글에 여기서 다루었던 뷰와 속성을 이용해 작은 활용을 해 볼 생각이다. 초반이라 이론적인 내용을 많이 쓰게되는데 시간이 너무 들어서 다음부터는 실습위주의 글을 쓰려고 한다.
그래도 어제 오늘 기록할 수 있어서 너무 다행이고 뿌듯하다.