- 앱의 기본 기능 구현하기
화면을 구성하고 사용자 이벤트를 처리하는 방법, 안드로이드 리소스를 활용하는 방법, 알림을 띄우는 방법 등을 다룹니다.
06-1 화면을 구성하는 방법
액티비티-뷰 구조
안드로이드 앱은 액티비티, 서비스, 브로드캐스트 리시버, 콘텐츠 프로바이더 같은 컴포넌트를 조합해 만들지만, 화면을 출력하는 컴포넌트는 액티비티 뿐입니다.
(화면을 제공하지 않는 앱이라면 액티비티가 없어도 됩니다.)
(화면이 10개여도 액티비티 1개로 만들 수 있습니다. 프래그먼트(Fragment)나 컴포즈(Compose)를 이용하면 됩니다.)
액티비티는 화면을 출력하는 컴포넌트일 뿐 그 자체가 화면은 아닙니다.
액티비티만을 실행하면 텅 빈 흰색 화면만 보이므로 내용을 표시하려면 뷰(View)클래스를 사용해 구성합니다.
예를들어, 문자열을 출력하려면 TextView클래스를, 이미지는 ImageView 클래스를 이용합니다.
이런 클래스를 뷰 클래스라고 합니다.
액티비티 코드로 화면 구성하기
뷰로 화면을 구성하는 방법은 2가지 입니다.
액티비티 코드로 작성하는 방법과 레이아웃 XML파일로 작성하는 방법입니다.
액티비티 코드로 작성하는 방법은 뷰 클래스를 액티비티 코드에서 직접 생성합니다.
class MainActivity : AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
// 이름 문자열 출력 TextView 생성
val name = TextView(this).apply{
typeface = Typeface.DEFAULT_BOLD
text = "Lake Louise"
}
// 이미지 출력 ImageView 생성
val image = ImageView(this).also{
it.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.lake_1))
}
// 주소 문자열 출력 TextView 생성
val address = TextView(this).apply{
typeface = Typeface.DEFAULT_BOLD
text = "Lake Louise, AB, 캐나다"
}
val layout = LinearLayout(this).apply{
orientation = Linear?Layout.VERTICAL
gravity = Gravity.CENTER
// LinearLayout 객체에 TextView, ImageView, TextView 객체 추가
addView(name, WRAP_CONTENT, WRAP_CONTENT)
addView(image, WRAP_CONTENT, WRAP_CONTENT)
addView(address, WRAP_CONTENT, WRAP_CONTENT)
}
// LinearLayout 객체를 화면에 출력
setContentView(layout)
}
}
필요한 뷰 객체 코드를 직접 생성해 크기, 출력 데이터 등도 일일이 객체에 대입했습니다.
그리고 TextView 2개와 ImageView 1개를 추가한 LinearLayout객체를 setContentView() 액티비티 컴포넌트 함수로 전달해 화면을 출력했습니다.
apply{}: 함수를 초훌하는 구문, 함수 호출문운 apply()처럼 소괄호를 써야하나 호출하려는 함수가 고차함수(함수를 값처럼 취급해 매개변수로 반환값으로 주고받는 함수)이고 마지막 전달 인자가 람다 함수이면 소괄호를 생략합니다.
레이아웃 XML로 화면 구성하기
같은 화면 구성을 레이아웃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="wrap_content"
android:textStyle="bold"
android:text="Lake Louise"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
anroid:text="Lake Louise/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/lake_1"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:text="Lake Louise, AB, 캐나다"/>
</LinearLayout>
XML을 이용하면 액티비티 코드에 내용을 작성하지 않아도 되지만, 코드에서 화면을 구현한 XML을 명시해 출력하도록 해야합니다.
class MainActivity: AppComaptActivity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
// 화면 출력 XML 명시
setContentView(R.layout.activity_main)
}
}
06-2 뷰 클래스
뷰 클래스의 기본 구조
안드로이드는 TextView, ImageView, EditText, Button, Spinner, ListView등 많은 뷰 클래스를 제공합니다.
뷰의 구조를 이해하면 여러 가지 뷰를 사용할 때 많은 도움이 됩니다.
뷰 객체의 계층 구조
액티비티 화면으 구성할 때 사용하는 클래스는 모두 View의 하위 클래스 입니다.
View: 모든 뷰 클래스의 최상위 클래스입니다. 액티비티는 View의 서브 클래스만 화면에 출력합니다.
ViewGroup: View의 하위 클래스지만 자체 UI는 없어서 화면에 출력해도 아무것도 나오지 않고, 다른 뷰 여러개를 묶어서 제어할 목적으로 사용합니다. 컨테이너 기능을 담당한다고 이야기하고 실제로는 ViewGroup의 서브 클래스의 레이아웃 클래스 등을 사용합니다.
TextView: 특정 UI를 출력할 목적으로 사용하는 클래스, 문자열을 출력하는 뷰 입니다.이 외에도 ImageView등 다양한 클래스가 있습니다.
레이아웃 중첩
뷰의 계층 구조는 레이아웃 객체를 중첩해서 복잡하게 구성할 수도 있습니다.
<LinearLayout xmlns:android="..."
...
<Button
android:layout_wdth"wrap_content"
.../>
<Button
android:layout_wdth"wrap_content"
.../>
<LinearLayout
...
<Button
android:layout_wdth"wrap_content"
.../>
<Button
android:layout_wdth"wrap_content"
.../>
</LinearLayout>
</LinearLayout>
이처럼 객체를 계층 구조로 만들어 이용하는 패턴을 컴포지트 패턴(Composite Pattern)또는 문서 객체 모델(Document Object Model)이라고 합니다.
레이아웃 XML의 뷰를 코드에서 사용하기
화면 구성을 XML 파일에 작성하고 액티비티에서 setContentView() 함수로 XML파일을 지정하면 화면을 출력합니다.
그런데 XML에 선언한 객체를 코드에서 사용할 때가 있습니다.
문제는 직접 생성한 객체가 아니므로 이름이 없어서 지칭할 수가 없다는 것입니다. 이때 id속성을 부여해 사용합니다.
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello"/>
이처럼 id 속성은 android:id="@+id/text1"형태로 추가합니다. text1이 id 값이고 식별자로 이용할 것이므로 앱에서 유일해야 합니다.
id속성을 추가하면 자동으로 R.java파일에 상수 변수로 추가됩니다.
XML속성값이 @로 시작하면 R.java파일을 의미하므로 R.java파일에 text1이라는 상수 변수를 추가하라는 의미입니다.
이제 코드에서 R.java파일의 상수변수로 객체를 얻을 수 있습니다. findViewById()함수를 이용합니다.
// XML 화면 출력
setContentView(R.layout.activity_main) // 액티비티 화면 출력(뷰 객체 생성)
// id값으로 뷰 객체 획득
val textView1: TextView = findViewById(R.id.text1)
findViewById()함수로 얻은 뷰 객체의 타입을 제네릭으로 명시해도 됩니다.
'findViewById<TextView>(R.id.text1)'
뷰의 크기를 지정하는 방법
뷰를 레이아웃 XML에 등록해 화면을 구성할 때 생략할 수 없는 속성이 크기입니다.
뷰가 화면에 나올 때 어떤 크기로 보여야 하는지는 필수 정보이며 이 크기를 설정하는 속성은 layout_width, layout_height입니다.
그리고 이 속성값은 다음 3가지 중 하나를 선언합니다.
1. 구체적 수치: 100px처럼 수치로 지정할 수 있습니다. px, dp등의 단위를 사용합니다.
2. match_parent: 부모의 크기 전체를 뜻합니다. 뷰 객체는 계층 구조를 이용하므로 자신보다 상위 계층의 크기를 의미합니다.
3. wrap_content: 화면에 출력할 수 있는 적절한 크기를 의미합니다. 문자열의 경우 길이나 글꼴 크기에 따라 문자열이 출력될 정도의 크기로 설정됩니다.
뷰의 간격 설정
뷰의 간격은 margin과 padding으로 설정합니다. margin은 뷰와 뷰 사이의 간격, padding은 뷰의 콘텐츠와 테두리 사이 간격입니다.
paddingLeft, paddingRight... layout_marginLeft, layout_marginRight ... 등을 이용할 수 있습니다.
뷰의 표시 여부 설정
visibility 속성은 뷰가 화면에 출력되어야 하는지를 설정합니다.
값을 visible, invisible, gone으로 설정합니다.
이때 invisible은 뷰가 화면에 보이지 않지만 자리는 차지하고, gone은 자리조차 차지하지 않습니다.
(invisible이나 gone을 사용하는 이유는 처음에는 화면에 보이지 않다가 어떤 순간이 되면 보이게 처리하기 위함입니다.)
코드에서 visibility 속성을 조정하려면 뷰의 visibility속성값을 View.VISIBLE이나 View.INVISIBLE로 설정하면 됩니다.
visibleBtn.setOnClickListener(){
targetView.visibility = View.VISIBLE
}
visibleBtn.setOnClickListener(){
targetView.visibility = View.INVISIBLE
}
(자바에서는 속성값을 변경하기 위해 setVisibility(View.Visible)로 사용하나, 코틀린은 자바와 다르게 필드가 아니라 프로퍼티 임으로 세터와 게터가 내장되어있습니다.)
06-3 기본적인 뷰 살펴보기
텍스트 뷰
TextView는 문자열을 화면에 출력하는 뷰 입니다.
android:text속성
TextView에 출력할 문자열을 지정합니다. android:text="helloworld"처럼 문자열을 대입해도 되고 android:text="@string/hello"처럼 문자열 리소르를 지정해도 됩니다.
android:textColor속성
문자열의 색상을 지정합니다. android:textColor="#FF0000"처럼 16진수 RGB형식을 사용합니다.
android:textSize속성
문자열의 크기를 지정합니다. android:textSize="20sp"처럼 값은 숫자를 사용하며 단위 생략은 불가능합니다.(px, dp, sp 등)
android:textStyle속성
문자열의 스타일을 지정합니다. android:textStyle="bold"처럼 이용합니다. (bold, italic, normal)
android:autoLink속성
TextView에 출력할 문자열을 분석해 특정 형태의 문자열에 자동 링크를 추가합니다.
android:autoLink"web"으로 설정하면 문자열에 웹 주소가 포함됐을 때 해당 문자열을 링크모양으로 표시합니다.
(web, phone, email 등 사용가능, 여러개를 함께 설정하려면 | 기호로 연결)
android:maxLines속성
긴 문자열의 자동 줄바꿈을 하거나 특정 줄까지만 나오도록 합니다.
android:maxLines="3"으로 설정하면3행 까지만 출력됩니다.
android:ellipsize속성
maxLines 속성을 이용할 때 출력되지 않은 문자열이 더 있다는 것을 표시하기위해 줄임표(...)를 넣습니다.
end, middle, start 등의 값이 있습니다. start와 middle은 앞이나 중간에 추가되는데 signleLine="ture" 속성으로 문자열을 한 줄로 출력했을 때만 적용됩니다.
이미지 뷰
ImageView는 이미지를 화면에 출력합니다.
android:src속성
ImageView에 출력할 이미지를 설정합니다. 리소스 이미지, 파일 이미지, 네트워크 이미지 등을 출력할 수 있습니다.
src 속성으로 android:src="@drawable/image3"처럼 설정합니다.
android:maxWidth, maxHeight, adjustViewBounds속성
이미지의 최대 크기를 지정합니다. 뷰의 크기는 layout_width, height 속성으로 설정하지만 이 크기는 고정되어있어서 뷰에 넣을 이미지 크기가 다양하다면 이미지 뷰와 뷰의 크기가 맞지 않는 상황이 발생할 수 있습니다.
maxWidth, maxHeight 속성은 adjustViewBounds속성과 함게 사용해야 하며, 이 속성을 true로 설정하면 이미지의 가로 세로 길이와 비례해 뷰의 크기를 맞춥니다.
버튼, 체크박스, 라디오 버튼
Button은 사용자 이벤트를 처리하고 CheckBox는 다중 선택을, RadioButton은 단일 선택을 제공하는 뷰입니다.
체크박스는 다중 선택을 제공하나 라디오 버튼은 하나만 선택할 수 있는 단일 선택이므로 묶어서 처리해야합니다.
RadioGgroup과 함께 사용하며 그룹으로 묶은 라디오 버튼 중 하나만 선택할 수 있습니다.
에디트 텍스트
EditText는 사용자가 글을 입력할 수 있는 뷰입니다.
adnroid:lines, maxLines속성
EditText는 한줄 크기로 출력 되었다가 사용자가 키보드에서 엔터를 누르면 아래로 늘어나서 여러 줄 입력 크기가 됩니다.
처음부터 여러줄 입력 크기로 나오게 하는것이 android:lines입니다. android:lines="3"과 같이 사용합니다.
maxLines="3"으로 지정하면 처음에는 한줄 크기로 입력이 되고, 사용자의 엔터입력에 따라 3줄까지만 늘어납니다.
android:inputType속성
글을 이볅할 때 올라오는 키보드를 지정하는 속성입니다. 예를들어 키보드로 한줄 입력을 강제하거나, 전화번호 입력 모드로 지정하고 싶을 때 사용합니다. android:inputType="phone"과 같이 사용합니다.
자주 사용하는 inptuType의 속성값은 아래와 같습니다.
| 속성값 | 설명 |
| none | 지정X, 모든 문자 입력 가능하며 줄바꿈 가능 |
| text | 문자열 한 줄 입력 |
| textCapCharacters | 대문자 입력 모드 |
| textCapWords | 각 단어의 첫 글자 입력 시 키보드가 자동으로 대문자 입력 모드 |
| textCapSentences | 각 문단의 첫 글자 입력 시 키보드가 자동으로 대문자 입력 모드 |
| textMultiLine | 여러 줄 입력 가능 |
| textNoSuggestions | 단어 입력 시 키보드의 추천 단어를 보여 주지 않음 |
| textUri | URL 입력 모드 |
| textEmailAddress | 이메일 주소 입력 모드 |
| textPassword | 비밀번호 입력 모드로 입력한 문자를 점으로 표시. 키보드는 영문자, 숫자, 특수 키만 표시 |
| textVisiblePassword | textPassword와 같으며 입력한 문자 표시 |
| number | 숫자 입력 모드 |
| numberSigned | number와 같으며 부호 키인 마이너스(-)입력 가능 |
| numberDecimal | number와 같으며 소숫점 입력 가능 |
| numberPassword | 숫자 키만 입력 가능, 입력한 문자는 점으로 표시 |
| phone | 전화번호 입력 모드 |
(inputType속성을 지원하지 않는 기기가 있을수도 있음)
06-4 뷰 바인딩
뷰 바인딩은 레이아웃 XML파일에 선언한 뷰 객체를 코드에서 쉽게 이용하는 방법입니다.
findViewById()함수로 얻어 사용하는 방법 대신 레이아웃 XML파일에 등록된 뷰 객체를 쉽게 사용하는 방법입니다.
<LinearLayout ...
...>
<Button
android:id="@+id/visibleBtn"
.../>
<TextView
android:id="@+id/targetView"
.../>
<Button
android:id="@+id/invisibleButton"
.../>
</LinearLayout>
이처럼 작성한 레이아웃 XML파일이 있다고 가정하겠습니다.
이곳에서 선언한 뷰 3개를 코드에서 id값을 얻어서 사용할 수도 있으나, 뷰 바인딩 기법을 이용해 코드에서 더 간편하게 이용할 수 있습니다.
뷰 바인딩을 사용하려면 그래들 파일에 다음처럼 선언해야 합니다.
android{
(...생략...)
viewBinding.isEnabled=true
}
build.gradle 파일을 열고 android 영역에 buildFeatures를 선언합니다.
그 안에 뷰 바인딩을 적용하라는 의미로 viewBinding=true를 설정합니다.
이러면 레이아웃 XML 파일에 등록된 뷰 객체를 포함하는 클래스가 자동으로 만들어집니다.
자동으로 만들어지는 클래스의 이름은 레이아웃 XML파일명을 따릅니다.
첫 글자를 대문자로 하고 밑줄(_)은 빼고 뒤에 오는 단어를 대문자로 만든 후 Binding을 추가합니다.
activity_main.xml → ActivityMainBinding
자동으로 만들어진 클래스의 inflate()함수를 호출하면 바인딩 객체를 얻을 수 있습니다.
이때 인자로 layoutInflater를 전달합니다. 그리고 바인딩 객체의 root 프로퍼티에는 XML의 루트 태그 객체가 자동으로 등록되므로 액티비티 화면 출력은 setCOntentView()함수에 binding.root를 전달하면 됩니다.
class MainActivity: AppCompatActivity(){
override fun onCreate(savedInstanceState: Bundle?){
super.onCreate(savedInstanceState)
// 바인딩 객체 등록
val binding = ActivityMainBinding.inflate(layoutInflater)
// 액티비티 화면 출력
setContentView(binding.root)
// 뷰 객체 이용
binding.visibleBtn.setOnClickListener{
binding.targetView.visibility = View.VISIBLE
}
binding.invisibleBtn.setOnClickListenere{
binding.targetView.visibility = View.INVISIBLE
}
}
}
바인딩 객체에 등록된 뷰 객체명은 XML파일에 등록된 id 값을 따릅니다.
뷰 바인딩 이용을 build.gradle에 선언하면 레이아웃 XML하나당 바인딩 클래스가 자동으로 만들어지는데, 어떤 것들은 제이외하고 싶을 수도 있습니다. 이때는 해당 XML파일의 루트 태그에 tools:viewBindingIgnore="ture"라는 속성을 추가합니다.
'Java > Kotlin' 카테고리의 다른 글
| Kotlin Programming Study - 08 (0) | 2025.12.17 |
|---|---|
| Kotlin Programming Study - 07 (0) | 2025.12.16 |
| Kotlin Programming Study - 04 (0) | 2025.12.10 |
| Kotlin Programming Study - 03 (0) | 2025.12.09 |
| Kotlin Programming Study - 02 (0) | 2025.12.09 |