이 글은 이것이 안드로이드다 with 코틀린(개정판)를 참고하여 작성하였습니다.
작성자 : 김예진
개발환경은 Windows, Android Studio입니다.
1. 배치를 담당하는 레이아웃 다루기
* 레이아웃
안드로이드 스튜디오를 실행했을 때 마주하게 되는 화면 중 레이아웃(xml 파일)을 살펴보도록 합니다. 우측 상단에서 Design을 선택해 기기 디스플레이에 띄워질 화면을 직접 볼 수도 있고, Code를 선택해 시각적으로 볼 수 있던 UI들을 코드로 살펴볼 수도 있습니다. Split을 골라 디자인 화면과 코드 화면을 동시에 띄워 작업하는 것도 가능합니다.


코드 모드에서 직접 코드를 작성하여 UI를 생성하고 설정할 수도 있고, 디자인 모드에서 직관적으로 오브젝트들을 배치하고 오른쪽의 Attributes 탭을 이용해 설정값을 줄 수도 있습니다.
디자인 모드의 왼쪽 상단에 위치한 팔레트에서는 화면에 배치할 수 있는 다양한 UI 요소들을 선택할 수 있습니다.

Common 카테고리에서는 "Hello World!" 를 출력하고 있는 TextView 위젯, 버튼을 구현하는 Button 위젯 등등 우리가 가장 자주 사용하는 위젯들을 볼 수 있고, 다른 카테고리에서는 용도에 맞는 더 다양한 종류의 위젯들을 살펴볼 수 있습니다. Layouts 카테고리에서는 여러 형태의 레이아웃들을 제공하고 있는데, 이 중 ConstraintLayout은 우리가 xml 파일에 처음 들어왔을 때부터 만들어져 있다는 것을 Component Tree를 통해 알 수 있습니다. 여기서 ConstraintLayout은 레이아웃 파일의 최상위에 자동으로 생성되는 위젯이며, 앞으로 우리가 한 화면에 생성하고 배치할 모든 UI 요소들이 담길 틀 정도로 이해해주면 됩니다.
이제 위젯을 직접 생성해봅시다. 편의를 위해 "Hello World!" 텍스트뷰는 삭제하고, Common > TextView 를 선택한 뒤 드래그하여 화면에 가져옵니다.

처음 위젯을 생성하면 자동으로 오류가 뜨게 되는데, 오른쪽에 뜬 메시지를 읽어보면 "Not Horizontally Constrained", "Not Vertically Constrained" 라는 오류가 발생했음을 알 수 있습니다. 우리가 방금 생성한 위젯과 레이아웃 간의 관계를 설정해주지 않아 위젯이 붕 떠있는 상태 정도로 이해해주면 되겠습니다.
오류를 해결하는 방법으로, 텍스트뷰 위젯의 상하좌우의 하얀 동그라미를 드래그해 각 화면의 변에 맞춰주는 것이 있습니다. 이렇게 하면 자동으로 Constraint 값이 설정됩니다. 또 다른 방법으로 첨부한 캡처 화면 속에서도 볼 수 있듯 오류 메시지 위의 Constraint Widget 에서 파란 + 동그라미들을 클릭하여 자동으로 가장 가까이 있는 곳에 Constraint를 연결해줄 수 있습니다. 직접 숫자를 지정해 Constraint 값을 줄 수도 있습니다. 상하좌우 가운데로 배치하고 싶은 경우에는 전부 0으로 설정하면 됩니다.
지정한 Contraint 값을 해제하고 싶을 때는 화면에서 ctrl을 누른 채 동그라미를 클릭하거나, 오른쪽 Constraint Widget 탭에서 사각형 변의 동그라미를 클릭하여 해제해줄 수 있습니다.

이제 위젯을 생성하여 사용자로부터 아이디와 비밀번호를 입력 받는 간단한 화면을 구성해보겠습니다.

텍스트뷰의 Constraint를 설정하고 난 뒤에 오른쪽 Attributes 탭에서 text의 내용을 변경해줍니다. 해당 포스팅에서는 ID로 설정해주었습니다.

설정이 완료되면 Palette > Text > Plain Text를 생성하여 텍스트뷰 아래쪽에 배치합니다. Plain Text는 사용자로부터 입력값을 받아오는 위젯입니다. 위젯을 간편하게 다루기 위해 id를 editText로 변경하고 Constraint는 좌측을 텍스트뷰에, 상단은 화면 위에 고정시켜주었습니다. 이렇게 하면 텍스트뷰를 이동시킬 때마다 에디트텍스트로 함께 움직여 하나의 그룹처럼 사용할 수 있습니다. 또한 입력창의 크기를 조절할 때는 우측 Attributes > layout_width/layout_height 를 이용합니다. wrap_content를 선택하여 주어진 규격대로 사용할 수도, 직접 값을 입력하여 사용할 수도 있습니다. (300dp로 설정)

위와 같은 방법으로 텍스트뷰와 에디트텍스트를 하나씩 더 생성하여 비밀번호를 입력창까지 만들어주겠습니다.
이렇게 화면 구성이 완료된 경우, 레이아웃 설정에 오류가 없는지 점검하고 싶을 때는 가로로 화면을 전환해보는 것이 간단한 확인 방법입니다.

Orientation for Preview (사진 속 아이콘) > Landscape를 선택합니다.

레이아웃이 가로 모드에서도 깨지지 않고 잘 설정되었음을 확인 가능합니다.
* Constraint Chain
Constraint chain은 여러 개의 UI 요소들을 화면 비율에 맞춰 채워넣기 위해 사용합니다.

버튼 9개를 화면에 대강 배치한 뒤 가로로 세 줄과 세로로 세 줄을 체인으로 연결하여 배치해보겠습니다.


첫 줄의 버튼 세 개를 드래그하여 선택하고 마우스 우클릭 > Chains > Create Horizontal Chain 을 선택하면 세 개의 버튼들이 체인으로 연결됩니다. 같은 방법으로 아래의 두 줄을 체인으로 연결하고, 세로 세 줄은 Create Vertical Chain으로 연결해줍니다.

모든 연결이 끝나면 9개의 버튼들이 가로와 세로 간격이 일정한 비율로 화면에 배치되는 것을 확인할 수 있습니다. 만약 화면에 빈 공간이 없도록 버튼들의 크기 비율 역시 조절해주고 싶다면 모든 버튼들을 선택한 뒤 우측 Attributes 탭에서 layout_width와 layout_height를 wrap_content에서 0dp (match constraint)로 바꿔주면 됩니다.

설정을 마치면 9개의 버튼들이 화면에 가득 차도록 constrain 되었음을 확인할 수 있습니다.
* LinearLayout / FrameLayout
LinearyLayout과 FrameLayout은 화면 구성에 있어 자주 사용되는 레이아웃 형태입니다.
Linear layout은 horizontal과 vertical로 나뉘는데, UI 요소들을 가로로 정렬할지, 세로로 정렬할지에 따라 원하는 레이아웃을 골라 사용할 수 있습니다. Linear layout을 드래그해 배치하면 기본적으로 화면에 꽉 차도록 레이아웃이 생성됩니다. 생성된 레이아웃 내에 위젯을 배치해보겠습니다.

세 개의 버튼을 순서대로 레이아웃에 끌어다 놓으면, 어디에 배치하든 상단에 버튼이 하나씩 가로로 정렬되는 것을 확인할 수 있습니다. 이처럼 Linear layout은 스택처럼 한 방향에 위젯들이 쌓이도록 설정되어있습니다.

같은 방법으로 vertical 레이아웃에 위젯을 배치시키면, 역시 동일하게 작동합니다.
이렇게 간단하지만 깔끔하게 위젯들을 배치시킬 때 Linear layout을 단독으로 사용하기도 하지만, 그렇지 않은 경우가 다수 존재합니다. 예컨대 Linear layout (vertical)을 사용할 때 설정해야 할 버튼의 수가 많아져 버튼 수 X 버튼의 높이 > 화면의 세로 길이가 된다면, 우리는 Linear layout을 단독으로 사용할 수 없습니다. Linear layout에는 스크롤 기능이 없기 때문에 버튼의 수가 많아지면 많아지는대로 화면 아래로 사라져버리게 됩니다. 이런 상황에서 Linear layout과 함께 사용할 수 있는 기능이 Containers 카테고리의 ScrollView입니다.


스크롤뷰를 하나 생성하게 되면, Linear layout을 추가했을 때 자동으로 스크롤뷰 하위에 레이아웃이 위치하게 됩니다. 그 안에 버튼들을 배치하게 되면 화면 밖을 벗어나게 될 버튼들이 스크롤뷰 내부 아래에 계속하여 배치되어 1번부터 19번까지의 버튼들을 스크롤만으로 확인할 수 있게 됩니다.
즉, 위젯들의 사이즈가 특정될 때 화면을 넘어가지 않는 범위라면 Linear Layout을 단독으로 사용할 수 있지만 그렇지 않은 경우에는 ScrollView를 함께 써주어야 합니다.
그 다음으로 살펴볼 FrameLayout은 같은 카테고리의 레이아웃 중 가장 빠른 속도를 가지고 있습니다. 그 이유는 레이아웃 내에 특별한 기능이 구현되어있지 않기 때문인데, 직접 생성하여 확인하면 이해가 쉽습니다.

Frame layout을 하나 생성한 뒤 하위에 버튼, 텍스트뷰, 이미지뷰를 하나씩 배치시켜 보았습니다. 이 위젯들은 자동으로 상단 좌측에 정렬이 되고, 중첩되어 배치됩니다. 이렇게 여러 위젯들을 겹쳐서 배치할 수 있는 특성을 가지고 있어 게임에서 자주 사용되는 레이아웃이기도 합니다. 게임에서는 배경, 캐릭터, 오브젝트 등등 여러 레이어를 중첩 배치하는 경우가 아주 많기 때문입니다.

프레임 레이아웃은 Constraint 기능이 제공되지 않기 때문에 정렬을 위해서는 위젯 자체의 기능을 이용해야 합니다. 정렬을 원하는 위젯을 선택한 뒤 오른쪽 Attributes에서 layout_gravity 탭을 눌러보면 해당 위젯을 포함하고 있는 상위 레이어 내에서 특정 위치에 위젯을 배치할 수 있도록 하는 기능을 제공하고 있습니다. 원하는 위치를 체크하여 활성화해주면 위젯이 정렬되는 것을 확인할 수 있습니다.
2. 리스너 이해하기
* 리스너
리스너는 이벤트가 발생할 때마다 호출되어 신호를 전달하는 역할을 수행합니다.
간단한 코드와 함께 설명하기 위해 xml 파일에서 버튼 하나를 생성합니다. id는 button으로 지정하였습니다.

버튼 생성이 완료되면, 코틀린 익스텐션 플러그인을 통해 xml의 버튼 UI와 메인 액티비티 백엔드 코드를 연결해줍니다. (뷰바인딩 개념을 배우기 이전에 잠깐 활용하는 것입니다!) 첫번째로 체크해줄 부분은 프로젝트 폴더 탭의 app > manifest입니다.

manifests를 더블클릭하면 위와 같은 코드 창이 뜨는데, android:exported="true"로 설정되어있는지 확인해야 합니다. 두번째로 Gradle Scripts > build.gradle (Module: prac.app) 파일을 확인하겠습니다.

최상단의 plugins 에서 id 'kotlin-android-extensions'를 추가해주어야 xml 파일과의 연결이 가능하게 됩니다. 마지막으로 다시 메인 액티비티 파일로 넘어와 아래의 코드를 작성하겠습니다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listener = object : View.OnClickListener {
override fun onClick(p0: View?) {
Log.d("리스너", "클릭되었습니다.")
}
}
button.setOnClickListener(listener)
}
}
코드를 작성하게 되면 마지막 button.setOnClickListener(listener) 부분에서 오류가 발생하게 됩니다.

빨간 button 글자를 클릭하고 마우스를 올리면 사진과 같이 오류 해결 메시지가 뜨는데, Alt+Enter를 눌러 import를 선택해주면 상단에 자동으로 import kotlinx.android.synthetic.main.activity_main.* 가 추가되어 오류가 사라집니다. 이제 코드를 살펴보겠습니다.
val listener = object : View.OnClickListener {
override fun onClick(p0: View?) {
Log.d("리스너", "클릭되었습니다.")
}
}
button.setOnClickListener(listener)
첫 줄에서 listener 객체를 선언하고 리스너를 달아줍니다. OnClickListener는 View 클래스 아래에 정의된 인터페이스입니다. 따라서 인터페이스 내부의 함수를 직접 구현해주어야 하고, 그 함수가 바로 onClick 함수입니다. 또한 리스너 함수를 구현할 때는 object 키워드를 사용하여 인터페이스를 작성해주도록 합니다. onClick 함수의 구현 내용은 우리가 logcat에서 리스너의 실행 여부를 확인할 수 있도록 로그를 남기는 한 줄을 추가해줍니다.
xml 파일에서 생성해주었던 버튼 위젯의 id인 button 뒤에 setOnClickListener 를 붙여 버튼 객체에 리스너를 달아줍니다. 그리고 우리가 선언하였던 listener 객체를 파라미터로 넘겨주면 버튼 위젯에 리스너를 다는 작업이 완료됩니다. 이제 코드를 실행하고 logcat에서 '리스너'를 검색한 상태에서 에뮬레이터에서 버튼을 눌러주면 다음과 같이 로그가 출력되는 것을 확인할 수 있습니다.

3. 버튼 및 스트링 소스
안드로이드에서 자주 사용하는 버튼 위젯에 대해 조금 더 알아보겠습니다.

xml 파일에서 Common > Button 을 하나 생성합니다. 버튼에 적혀있는 글자는 오른쪽 Attributes > text 에서 변경할 수 있습니다. 또 하나 눈 여겨볼 속성은 gravity인데, 직접 하나씩 눌러보면 이해가 편합니다.

기본적으로 상하좌우 가운데에 위치되어있던 글자가 bottom가 left를 true로 변경하자 왼쪽과 아래쪽으로 정렬되는 것을 볼 수 있습니다. 디폴트 값으로 설정되어 있는 정렬은 전체 가운데 정렬입니다.
또한 alpha 속성을 이용해 0부터 1까지의 값을 입력해 버튼의 투명도를 조절할 수 있습니다.
이제 스트링 소스에 대해 이야기해보겠습니다. 안드로이드 개발 실전 프로젝트에서 위젯의 내용을 변경할 때, 해당 위젯의 Attribute에서 text의 내용을 바꾸는 경우는 없습니다. 매번 위젯에서 직접 텍스트를 작성하게 되면 리소스 관리자가 아닌 개발자에 의해 텍스트가 입력되고, 이 경우에는 오타가 발생해도 간과될 가능성이 높기 때문입니다. 또 하나의 큰 이유는 스트링 소스에서는 다국어를 지원한다는 점입니다. 여러 국가의 언어로 앱을 개발할 때, 기본 스트링 소스를 작성해준 뒤 언어에 따라 새로운 리소스 공간을 만들어 기존의 리소스들을 번역해주기만 하면 앱 내 언어 설정 기능에서 간편하게 모든 기능들을 새로운 언어로 바꾸어 사용할 수 있습니다. 이처럼 실제 개발에서 필수적으로 사용되는 스트링 소스의 사용법에 대해 알아보겠습니다.

왼쪽의 프로젝트 메뉴에서 res > values > strings.xml 로 들어오면 우측의 화면과 같은 리소스 코드창이 뜹니다. 이 공간에서는 사용하고 싶은 텍스트값을 미리 아이디로 정의할 수 있습니다.
<string name="button1_text">나는 버튼</string> 이라는 새로운 리소스를 작성해보았습니다. 이 리소스에서 button1_text는 리소스의 아이디, 나는 버튼은 리소스가 가진 문자열 값을 의미합니다.

다시 xml 파일로 넘어와 버튼 위젯의 text에 아까 지정했던 스트링 리소스의 아이디 일부만 입력해도 자동으로 그 값이 완성되어 뜨는 것을 확인할 수 있습니다. @string/button1_text를 선택하고 엔터를 치면 해당 아이디에 정의된 텍스트 값이 버튼의 텍스트로 지정됩니다.

지정했던 리소스의 값대로 버튼의 텍스트가 변경되었음을 확인할 수 있습니다. 이러한 스트링 소스는 버튼뿐만이 아닌 모든 위젯에 사용 가능합니다.
4. Dimen과 color 리소스
리소스 파일의 사용을 위해 텍스트뷰의 속성들을 조금 활용해보겠습니다.

텍스트뷰를 하나 생성한 뒤 Attributes 탭에서 text~로 시작하는 속성들을 찾아봅시다. 텍스트뷰의 기본적이고 빈번하게 사용되는 속성이 이러한 속성들입니다.

textColor에서는 글자의 색깔을 변경할 수 있고, textSize에서는 글자의 크기를 변경할 수 있으며 textStyle에서는 볼드와 이탤릭 같은 글자의 스타일 변경이 가능합니다. 그 외의 속성들은 하나씩 눌러 값을 변경해보면 직관적으로 이해할 수 있습니다.
그리고 이러한 속성들에서, 우리가 이전에 학습했던 스트링 소스처럼 저장된 값을 불러와 지정할 수도 있습니다. 아까 보았던 res > values 폴더에는 strings.xml뿐만이 아니라 colors.xml도 정의되어 있었습니다. 물론 글자와 색깔뿐만이 아니라 다른 값에도 스트링 소스를 정의하여 지정할 수 있습니다.
위젯의 크기를 조절하는 사이즈를 리소스로 정의하여 사용하는 작업을 해보겠습니다. 사이즈를 정의해놓는 리소스 파일을 dimens.xml라고 하는데, values 폴더 내에 미리 생성되어있지 않아 직접 생성해야 합니다.

values (마우스 우클) > New > Values Resource File로 새로운 리소스 파일을 생성합니다.

파일 이름을 다음과 같이 설정해주고 새로 만들어진 리소스 파일에 사이즈 리소스를 저장해보겠습니다.

버튼 높이에 설정해줄 리소스와 텍스트 사이즈에 설정해줄 리소스를 각각 100dp와 50sp로 정의하고 다시 메인 액티비티로 돌아가 스트링 소스를 다룰 때와 같은 방식으로 속성에 아이디를 입력해주면 원하는 사이즈로 버튼과 텍스트를 지정할 수 있습니다.
이번에는 색깔 리소스를 한 번 살펴보겠습니다.

colors.xml 파일을 열어보면, 미리 정의되어있는 색깔 리소스와 좌측의 컬러 커스텀 기능을 확인할 수 있습니다. 줄마다 색깔이 표시된 사각형을 누르면 바로 해당 줄에 정의된 리소스의 색깔을 바꿀 수도 있습니다. 컬러 리소스 역시 내가 사용하고자 하는 아이디를 지정한 뒤 위젯의 color 속성에서 아이디를 입력하면 그대로 리소스를 적용시킬 수 있습니다.
5. 텍스트뷰 다루기
스트링 소스와 연결되어있는 텍스트뷰를 조작해보겠습니다. strings.xml에 들어가 다음처럼 세번째 줄을 추가해줍니다.


Hello \n Nice to meet u에서 중간에 삽입된 \n은 줄바꿈 역할을 합니다. 메인 액티비티로 넘어가 해당 리소스 아이디를 텍스트뷰에 입력하면 텍스트가 \n을 기준으로 두 줄이 되어있는 것을 확인할 수 있습니다.
또 다른 Attributes 중 하나로 maxLines과 minLines을 활용할 수 있습니다. maxLines는 최대 몇 줄까지의 텍스트를 띄울지, minLines는 최소 몇 줄부터 텍스트를 띄울지 값을 지정합니다. 만약 세 줄짜리 텍스트를 입력한 뒤 maxLines를 2로 설정하면 셋째 줄은 화면에 나타나지 않고, 동일한 텍스트를 입력한 뒤 minLines를 4로 설정하면 세 줄의 텍스트 밑에 비어있는 한 줄까지 화면에 나타나게 됩니다.
singleLine 속성은 여러 줄의 글자가 한 줄로 출력되도록 하기 위해 사용하고, ellipsize는 화면의 길이보다 길어진 문자들의 말줄임표를 어디에 적용할지 결정하는 데에 사용합니다. ellipsize > marquee 를 선택하면 앱을 실행했을 때 문자가 흐르는 효과를 나타낼 수 있습니다. marquee를 사용할 때는 singLine이 반드시 true로 체크되어 있어야 합니다.
fonrFamily에서는 폰트 변경 기능을 지원합니다. 기존 폰트에서 안드로이드에서 지정한 폰트로 변경할 수 있습니다. maxLength에서는 화면에 노출하고 싶은 최대 글자수를 지정할 수 있습니다.
'GDSC HUFS 3기 > Android with Kotlin Team 4' 카테고리의 다른 글
| [4팀]14-2~3. 화면구성하기:스피너 (0) | 2021.11.08 |
|---|---|
| [4팀]14-1. 화면 구성하기:액티비티 값 주고받기, 뷰바인딩 (0) | 2021.11.08 |
| [4팀] 11. (2) Kotlin을 위한 기본 문법 : 화면에 그려지는 디자인 요소 위젯 (0) | 2021.10.29 |
| [4팀] 11. (1) Kotlin을 위한 기본 문법 : 스코프 함수 (0) | 2021.10.26 |
| [4팀] Section 7 - (2) : Kotlin - Object Oriented Programming (0) | 2021.10.05 |