[Kotlin] 명언 앱 만들기

이상목·2024년 5월 23일
0

Kotlin

목록 보기
10/20

오늘은 이전 시간에 연습해본 리스트뷰를 활용하여 간단한 명언 앱을 생성해보겠습니다.

1. gradle에 바인딩 추가

plugins {
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.jetbrainsKotlinAndroid)
}

android {
    namespace = "com.sangmoki.lifequotes"
    compileSdk = 34

    defaultConfig {
        applicationId = "com.sangmoki.lifequotes"
        minSdk = 24
        targetSdk = 34
        versionCode = 1
        versionName = "1.0"

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
    // 데이터 바인딩을 위한 라이브러리 추가
    dataBinding {
        isEnabled = true
    }
}

dependencies {

    implementation(libs.androidx.core.ktx)
    implementation(libs.androidx.appcompat)
    implementation(libs.material)
    implementation(libs.androidx.activity)
    implementation(libs.androidx.constraintlayout)
    testImplementation(libs.junit)
    androidTestImplementation(libs.androidx.junit)
    androidTestImplementation(libs.androidx.espresso.core)
}
  • 기본 제공되는 binding 라이브러리를 추가하여 사용할 수 있게 준비한다.

2. main activity layout 구성

<?xml version="1.0" encoding="utf-8"?>

<layout>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/black"
        tools:context=".MainActivity">

        <Button
            android:id="@+id/showAllSentenceBtn"
            android:layout_width="150dp"
            android:layout_height="50dp"
            android:layout_margin="20dp"
            android:text="전체 명언 보기"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/sentenceTextView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp"
            android:gravity="center"
            android:text="명언이 들어갈 위치입니다 !"
            android:textColor="@color/white"
            android:textSize="30sp"
            android:fontFamily="@font/bmjua"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>
  • 추후 목록을 보여줄 수 있는 Button과 랜덤으로 보여질 명언 layout 구성을 위한 TextView을 추가하였습니다.
  • 기본 레이아웃으로 ConstraintLayout으로 크게 덮여있지만, binding을 이용하려면 더 상위에 layout으로 감싸주어야 합니다.

3. Main Activity 구성

package com.sangmoki.lifequotes

import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.databinding.DataBindingUtil
import com.sangmoki.lifequotes.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding : ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)

        // String 타입 하나만을 가진 리스트 생성
        var sentenceList = mutableListOf<String>()

        // 리스트에 명언 추가
        sentenceList.add("검정화면에 대충 흰글씨 쓰면 명언같다.")
        sentenceList.add("사람에게 하나의 입과 두 개의 귀가 있는 것은 말하기보다 듣기를 두 배로 하라는 뜻이다.")
        sentenceList.add("결점이 없는 친구를 사귀려고 한다면 평생 친구를 가질 수 없을 것이다.")
        sentenceList.add("자기 아이에게 육체적 노동을 가르치지 않는 것은 약탈과 강도를 가르치는 것과 마찬가지다.")
        sentenceList.add("승자는 눈을 밟아 길을 만들지만 패자는 눈이 녹기를 기다린다.")
        sentenceList.add("두 개의 화살을 갖지 마라. 두 번째 화살이 있기 때문에 첫 번째 화살에 집중하지 않게 된다.")
        sentenceList.add("그 사람 입장에 서기 전까지 절대 그 사람을 욕하거나 책망하지 마라.")
        sentenceList.add("뛰어난 말에게도 채찍이 필요하다.")

        // DataBinding을 사용하여 레이아웃과 연결
        binding = DataBindingUtil.setContentView(this, R.layout.activity_main)

        // 전체 명언 보기 버튼 클릭 시 SentenceActivity로 이동
        binding.showAllSentenceBtn.setOnClickListener {
            var intent = Intent(this, SentenceActivity::class.java)
            startActivity(intent)
        }

        // 명언 텍스트뷰에 랜덤으로 선택된 명언을 보여줌
        binding.sentenceTextView.setText(sentenceList.random())

    }
}
  • ActivityMainBinding 를 통하여 구성한 레이아웃을 binding 변수에 담아 레이아웃과 연결합니다.
  • 전체 명언 보기 버튼 클릭 시 리스트 뷰를 구성한 sentenceActivity로 이동합니다.
  • 명언 텍스트뷰에 랜덤한 명언을 보여줍니다.
  • binding을 통하여 sentenceTextView라는 Id를 가진 TextView의 text 부분에 sentenceList라는 String 타입의 명언 목록을 가진 리스트를 랜덤으로 뿌려줍니다.

4. list_view_item 구성

<?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="match_parent">

    <TextView
        android:id="@+id/listViewItemTextView"
        android:layout_margin="10dp"
        android:textSize="30sp"
        android:text="textArea"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>
  • 기본 제공되는 Constrant Layout을 사용해도 상관 없다. 하지만 필자는 LinearLayout을 이용하였습니다.

5. Adapter 생성

package com.sangmoki.lifequotes

import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView

class ListViewAdapter(val List: MutableList<String>) : BaseAdapter() {
    override fun getCount(): Int {
        return List.size
    }

    override fun getItem(position: Int): Any {
        return List[position]
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        var convertView = convertView

        if (convertView == null) {
            convertView = View.inflate(parent!!.context, R.layout.list_view_item, null)
        }

        val listviewText = convertView?.findViewById<TextView>(R.id.listViewItemTextView)
        listviewText!!.text = List[position]

        return convertView!!
    }

}
  • BaseAdaptor 인터페이스를 상속받습니다.
  • 오버라이드 하여 리턴해줄 convertview를 설정해줍니다.

6. sentence activity layout 구성

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SentenceActivity">

    <ListView
        android:id="@+id/sentenceListView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • 화면에 뿌려줄 layout을 간단하게 구성해주고 리스트뷰에서 사용할 수 있게 id를 지정해줍니다.

7. SentenceActivity 구성

package com.sangmoki.lifequotes

import android.content.Intent
import android.os.Bundle
import android.widget.ListView
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.databinding.DataBindingUtil

class SentenceActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_sentence)

        // String 타입 하나만을 가진 리스트 생성
        var sentenceList = mutableListOf<String>()

        // 리스트에 명언 추가
        sentenceList.add("검정화면에 대충 흰글씨 쓰면 명언같다.")
        sentenceList.add("사람에게 하나의 입과 두 개의 귀가 있는 것은 말하기보다 듣기를 두 배로 하라는 뜻이다.")
        sentenceList.add("결점이 없는 친구를 사귀려고 한다면 평생 친구를 가질 수 없을 것이다.")
        sentenceList.add("자기 아이에게 육체적 노동을 가르치지 않는 것은 약탈과 강도를 가르치는 것과 마찬가지다.")
        sentenceList.add("승자는 눈을 밟아 길을 만들지만 패자는 눈이 녹기를 기다린다.")
        sentenceList.add("두 개의 화살을 갖지 마라. 두 번째 화살이 있기 때문에 첫 번째 화살에 집중하지 않게 된다.")
        sentenceList.add("그 사람 입장에 서기 전까지 절대 그 사람을 욕하거나 책망하지 마라.")
        sentenceList.add("뛰어난 말에게도 채찍이 필요하다.")

        // sentenceList를 ListViewAdapter에 연결
        val sentenceAdapter = ListViewAdapter(sentenceList)

        // ListView에 Adapter 연결
        val listview = findViewById<ListView>(R.id.sentenceListView)

        listview.adapter = sentenceAdapter
    }
}
  • 리스트뷰 목록에 item을 추가하고, Adaptor에 연결합니다.

8. 실행 결과

  • 메인 화면

  • 명언 리스트 뷰 화면



간단한 글귀만 보이는 앱이다 보니 이번에도 String 타입으로 해결했지만, 좀 더 익숙해 진 후 Model을 이용하여 더 많은 데이터를 수용할 수 있게 해보아야겠다.

profile
기록은 기억을 지배한다.

0개의 댓글