안드로이드 앱개발 뽀개기 씨리즈 – 개발하는 정대리
https://www.youtube.com/watch?v=32SGwgbUSYw&list=PLgOlaPUIbynrDSTJxS8AaE-2zYvPCjWtF&index=1
- 안드로이드개발 시작하기 / 초보개발자 / 기본 튜토리얼 / 코틀린 / 앱만들기
- 안드로이드개발 시작하기 #2 / 초보개발자 / 안드로이드 스튜디오 설치 / 기본 튜토리얼 / 코틀린
- 안드로이드개발 시작하기 #3 / 초보개발자 / 생명주기 / 그라데이션 뷰 / custom background / livetemplate / 기본 튜토리얼 / 코틀린
- 안드로이드개발 시작하기 #4 / 초보개발자 / 레이아웃 / LinearLayout / RelativeLayout / Constraint / 앱 만들기 / 코틀린 / kotlin
- 안드로이드개발 시작하기 / 초보개발자 / 레이아웃 실전 / figma / Linear Layout / 앱 만들기 / 코틀린 / kotlin
- 안드로이드개발 시작하기 / 초보개발자 / 클릭이벤트 / listener / method / 앱 만들기 / 코틀린 / kotlin
- 안드로이드개발 시작하기 / 초보개발자 / 커스텀 로티애니메이션 / 앱 만들기 / 코틀린 / kotlin
- 0
- 0
- 0
- 0
- 0
- 취준생을 위한 리사이클러뷰 만들기 #1 – 개념설명, 레이아웃 그리기 – [안드로이드] 코틀린
- 취준생을 위한 리사이클러뷰 만들기 #2 – 커스텀 뷰홀더 만들기 – [안드로이드] 코틀린
- 취준생을 위한 리사이클러뷰 만들기 #3 – 커스텀 어답터, 클릭리스너 설정 – [안드로이드] 코틀린
2. 안드로이드개발 시작하기 #2 / 초보개발자 / 안드로이드 스튜디오 설치 / 기본 튜토리얼 / 코틀린
1. 구글에서 안드로이드 스튜디오 검색
2. Android 스튜디오 설치 | Android 개발자 클릭
3. 최신 버전의 Android 스튜디오를 다운로드해야 합니다. 클릭
4. 다운로드 받아서 설치
- 프로젝트 만들기
- Empty Activity
- MyFirstAndroid
- Kotlin
- 미니멈 API Level (내가 만든 앱이 최소 지원 사양) – 킷캣
3. 안드로이드개발 시작하기 #3 / 초보개발자 / 생명주기 / 그라데이션 뷰 / custom background / livetemplate / 기본 튜토리얼 / 코틀린
# 프로젝트 만들기
androidLifecycle
# 라이브 템플릿 추가하기
File – Settings – Editor – Live Templates
# logd
Log.d(TAG, content)
Log.d(TAG, “$CLASS_NAME$ – $METHOD_NAMES$() called”)
Edit variables 클릭
– CLASS_NAME : kotlinClassName()
– METHOD_NAME : kotlinFunctionName()
하단 Change 클릭하고 kotlin 체크한 후 Apply
logt
val TAG: String = “로그”
val TAG: String = “로그
# 구글 검색 : android lifecycle
메모리 관리를 위해 생명주기가 존재한다.
# 구글 검색 : splash screen
# 구글 검색 : icon
www.flaticon.com
cat 검색 svg로 다운
# 다운받은 SVG 파일
res – drawable – 마우스 오른쪽 버튼 – New – Vector Asset – Local file (SVG, PSD)
# 다운받은 PNG 파일
res 폴더 -> new -> Image Asset
Icon Type -> Action Bar and Tab Icons
Asset type -> Image
Pat -> 이미지 경로
# 구글 검색 : android docs gradient
GradientDrawable (Android Developers)
# 그라데이션 넣기 : 구글 검색 : android xml gradient
res – drawable – 마우스 오른쪽 버튼 – New – Drawable resource file
파일 이름 : splash_bg_gradient
https://stackoverflow.com/questions/13929877/how-to-make-gradient-background-in-android
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<gradient
android:angle="135"
android:endColor="#1c8bd8"
android:startColor="#8AD0CC"
android:type="linear" />
<corners
android:radius="0dp"/>
</shape>
# 코틀린에서 컨트롤이 자동 인식이 안되면..
1. build.gradle(:app) 파일 수정 후 Sync Now 누룬다.
plugins {
id ‘com.android.application’
id ‘kotlin-android’ // 추가
id ‘kotlin-android-extensions’ // 추가
}
# import kotlinx.android.synthetic.main.activity_main is not working
https://stackoverflow.com/questions/52271521/import-kotlinx-android-synthetic-main-activity-main-is-not-working
# import kotlinx.android.synthetic.main.activity_main.* 이 안될 경우 해결 방법
https://ku-hug.tistory.com/61
// MainActivity.kt
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
val TAG: String = "로그"
// 액티비티가 생성되었을때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 레이아웃을 설정
setContentView(R.layout.activity_main)
Log.d(TAG, "MainActivity - onCreate() called")
}
override fun onStart() {
super.onStart()
Log.d(TAG, "MainActivity - onStart() called")
}
override fun onResume() {
super.onResume()
Log.d(TAG, "MainActivity - onResume() called")
}
override fun onPause() {
super.onPause()
text_view.visibility = View.VISIBLE
text_view.setText("onPause()")
Log.d(TAG, "MainActivity - onPause() called")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "MainActivity - onStop() called")
}
override fun onDestroy() {
super.onDestroy()
Log.d(TAG, "MainActivity - onDestroy() called")
}
}
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="@drawable/splash_bg_gradient"
android:id="@+id/relative_layout"
>
<ImageView
android:id="@+id/image_view"
android:layout_width="120dp"
android:layout_height="120dp"
android:src="@drawable/ic_pawprint"
android:layout_centerInParent="true"
/>
<TextView
android:visibility="invisible"
android:id="@+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/image_view"
android:layout_centerHorizontal="true"
android:text="라이프사이클 메소드"
android:textColor="#000000"
android:textSize="30dp"
android:textStyle="bold"
/>
</RelativeLayout>
4. 안드로이드개발 시작하기 #4 / 초보개발자 / 레이아웃 / LinearLayout / RelativeLayout / Constraint / 앱 만들기 / 코틀린 / kotlin
1. 리니어 레이아웃
– (Linear) 선
– Orientation – 방향
– Weight – 가중치 (weightSum : 총 가중치)
– gravity – 정렬
– 3개의 view에 1번:50dp, 2번:weight:1,
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="horizontal"
android:weightSum="3" // 가중치 3
android:gravity="center" // 가로 세로 가운데 정렬
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</LinearLayout>
<View
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#F44336"
/>
<View
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#FFEB3B"
/>
<View
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#3F51B5"
/>
</LinearLayout>
// 3개의 뷰
// 왼쪽뷰: 50dp, 오른쪽뷰: 50dp, 가운데뷰: 남은 공간 모두 차지
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="1" // 가중치 합: 1
tools:context=".MainActivity">
<View
android:layout_width="50dp" // 왼쪽 뷰: 50dp
android:layout_height="50dp"
android:background="#F44336"
/>
<View
android:layout_weight="1" // 가중치: 1
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#FFEB3B"
/>
<View
android:layout_width="50dp" // 오른쪽 뷰: 50dp
android:layout_height="50dp"
android:background="#3F51B5"
/>
</LinearLayout>
2. 레러티브 레이아웃
– (Relative) 관계, 상대
– 뷰끼리 겹칠 수 있다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RelativeLayout">
<View
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#FF5722"
/>
<View
android:id="@+id/blue_view"
android:layout_alignParentLeft="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#3F51B5"
/>
<View
android:id="@+id/green_view"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#4CAF50"
android:layout_toRightOf="@id/blue_view"
/>
</RelativeLayout>
3. 콘스트레인트 레이아웃
– (Constraint) 강제, 앵커, 제약조건
– 계층이 하나
– 화면 전환이 이루어졌을 때 그 비율을 유지한다.
– 가로, 세로 최소 두 개 이상의 제약조건이 있어야 한다.
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintLayout">
<View
android:id="@+id/orange_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#FF9800"
/>
<View
android:id="@+id/blue_view"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#2196F3"
app:layout_constraintTop_toBottomOf="@id/orange_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#E91E63"
app:layout_constraintTop_toBottomOf="@id/blue_view"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
5. 안드로이드개발 시작하기 / 초보개발자 / 레이아웃 실전 / figma / Linear Layout / 앱 만들기 / 코틀린 / kotlin
# 구글 검색 : free figma
# res – drawable 폴더 : 이미지 폴더
// AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.layoutpractice">
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<!-- 메인화면 -->
<activity android:name=".MainActivity">
<!-- 어플이 실행될때 가장 먼저 실행하도록 하는 코드 -->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
// activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
android:background="@drawable/bg"
android:weightSum="1"
android:paddingHorizontal="20dp"
>
<TextView
android:layout_marginTop="70dp"
android:layout_gravity="center_horizontal"
android:layout_width="wrap_content"
android:textAlignment="center"
android:layout_height="wrap_content"
android:text="Get the life you want!\n
Save more money."
android:textColor="#ffffff"
android:textSize="20dp"
android:textStyle="bold"
/>
<View
android:layout_weight="0.85"
android:layout_width="0dp"
android:layout_height="0dp"
/>
<Button
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Create free account"
android:textAllCaps="false"
android:textColor="#fff"
android:textSize="20dp"
android:background="@drawable/rounded_corner"
/>
<Button
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Continue with facebook"
android:textAllCaps="false"
android:textColor="#fff"
android:textSize="20dp"
android:background="@drawable/rounded_corner_blue"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Already have an account?"
android:textColor="#fff"
android:layout_gravity="center_horizontal"
android:textSize="20dp"
android:layout_marginTop="20dp"
/>
<Button
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Login"
android:textStyle="bold"
android:textAllCaps="false"
android:textColor="#fff"
android:textSize="20dp"
android:background="@drawable/rounded_corner_white_transparent"
/>
</LinearLayout>
// values/styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowTranslucentStatus">true</item> // 상태바 투명하게
<item name="android:windowTranslucentNavigation">true</item> // 상태바 투명하게
</style>
</resources>
// drawable/rounded_corner.xml
// 라운드 버튼
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="45"
android:endColor="#2DC897"
android:startColor="#7EF192"
android:type="linear" />
<!-- <solid android:color="#7EF192"/>-->
<!-- <stroke android:width="3dp"-->
<!-- android:color="#E91E63" />-->
<!-- <padding android:left="1dp"-->
<!-- android:top="1dp"-->
<!-- android:right="1dp"-->
<!-- android:bottom="1dp" />-->
<corners android:bottomRightRadius="30dp"
android:bottomLeftRadius="30dp"
android:topLeftRadius="30dp"
android:topRightRadius="30dp" />
</shape>
// rounded_corner_blue.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4666D5"/>
<corners android:bottomRightRadius="30dp"
android:bottomLeftRadius="30dp"
android:topLeftRadius="30dp"
android:topRightRadius="30dp" />
</shape>
// rounded_corner_white_transparent.xml
// stroke : 윤곽선
// solid : 배경색
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4DFFFFFF"/>
<stroke android:width="1dp"
android:color="#979797" />
<!-- <padding android:left="1dp"-->
<!-- android:top="1dp"-->
<!-- android:right="1dp"-->
<!-- android:bottom="1dp" />-->
<corners android:bottomRightRadius="30dp"
android:bottomLeftRadius="30dp"
android:topLeftRadius="30dp"
android:topRightRadius="30dp" />
</shape>
// MainActivity.kt
package com.example.layoutpractice
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
// 메인화면
class MainActivity : AppCompatActivity() {
// 뷰가 생성되었을때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 그릴 xml 뷰 파일을 연결 시켜준다. 즉 설정한다.
setContentView(R.layout.activity_main)
}
}
6. 안드로이드개발 시작하기 / 초보개발자 / 클릭이벤트 / listener / method / 앱 만들기 / 코틀린 / kotlin
// 메인화면
class MainActivity : AppCompatActivity() {
val TAG: String = "로그"
// 뷰가 생성되었을때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 그릴 xml 뷰 파일을 연결 시켜준다. 즉 설정한다.
setContentView(R.layout.activity_main)
// 로그인 버튼 뷰에 클릭 리스너를 설정하였다.
// login_btn.setOnClickListener(View.OnClickListener {
// onLoginButtonClicked()
// })
// 람다 방식
login_btn.setOnClickListener {
onLoginButtonClicked()
}
}
fun onLoginButtonClicked(){
Log.d(TAG, "MainActivity - onLoginButtonClicked() called")
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/login_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Login"
android:textSize="20dp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
class SecondActivity : AppCompatActivity() {
val TAG: String = "로그"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
}
fun onBackButtonClicked(view: View){
Log.d(TAG, "SecondActivity - onBackButtonClicked() called")
finish()
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<Button
android:onClick="onBackButtonClicked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50dp"
android:textColor="#000"
android:text="뒤로가기"
android:layout_centerInParent="true"
/>
</RelativeLayout>
# alt+enter 로 import가 안되시는 분들은 gradle (app) 에 추가하시면 됩니다
plugins {
id 'kotlin-android-extensions'
}
7. 안드로이드개발 시작하기 / 초보개발자 / 커스텀 로티애니메이션 / 앱 만들기 / 코틀린 / kotlin
# 구글 검색 : lottieanimation
https://lottiefiles.com/
# 구글 검색 : lottieanimation git
https://github.com/airbnb/lottie-android
# 설명서
https://airbnb.io/lottie/
# lottiefiles.com 회원 가입 후 JSON 으로 다운로드
new – folder – assets folder
# 자바 코드를 붙여넣으면 자동으로 코틀린으로 변환됨
class MainActivity : AppCompatActivity() {
val TAG: String = "로그"
var isLiked: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
isLiked = false
// 좋아요 버튼에 클릭 리스너를 달아준다.
like_btn.setOnClickListener {
// 좋아요 상태가 아닐때
if (isLiked == false){
// 애니메이션의 커스텀
// Custom animation speed or duration.초
// 0f = 0퍼센트, 1f = 100퍼센트
// ofFloat(시작지점, 종료지점). setDuration(지속시간) 1000 = 1
val animator = ValueAnimator.ofFloat(0f, 0.5f).setDuration(1000)
animator.addUpdateListener { animation: ValueAnimator ->
like_btn.setProgress(
animation.getAnimatedValue() as Float
)
}
animator.start()
isLiked = true
} else { // 좋아요 상태일때
// 애니메이션의 커스텀
// Custom animation speed or duration.초
// 0f = 0퍼센트, 1f = 100퍼센트
// ofFloat(시작지점, 종료지점). setDuration(지속시간) 1000 = 1
val animator = ValueAnimator.ofFloat(0.5f, 1f).setDuration(500)
animator.addUpdateListener { animation: ValueAnimator ->
like_btn.setProgress(
animation.getAnimatedValue() as Float
)
}
animator.start()
isLiked = false
}
Log.d(TAG, "MainActivity - onCreate() / 좋아요 버튼이 클릭되었다. isLiked : ${isLiked}")
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="@android:color/white"
>
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/like_btn"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@android:color/white"
android:layout_centerInParent="true"
app:lottie_fileName="heart.json"
app:lottie_autoPlay="false"
app:lottie_loop="false"
/>
</RelativeLayout>
// build.gradle (app)
plugins {
id 'kotlin-android-extensions' // 추가
}
// 외부 오픈소스를 가져온다.
dependencies {
def lottieVersion = '5.2.0'
implementation "com.airbnb.android:lottie:$lottieVersion"
}
13. 취준생을 위한 리사이클러뷰 만들기
# 라이브러리 추가
리사이클러뷰, 카드뷰, 글라이드
# AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jeongdaeri.myrecyclerview">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".App"
...
#activity_main.xml
<LinearLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
# layout_recycler_item.xml
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_margin="20dp"
app:cardCornerRadius="20dp"
app:cardElevation="20dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="20dp"
>
<ImageView
android:id="@+id/profile_img"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher"
/>
<TextView
android:id="@+id/user_name_txt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="쩡대리"
android:textSize="30sp"
android:layout_marginStart="20dp"
android:layout_gravity="center_vertical" />
</LinearLayout>
</androidx.cardview.widget.CardView>
# MainActivity.kt
class MainActivity : AppCompatActivity(), MyRecyclerviewInterface {
val TAG: String = "로그"
// 데이터를 담을 그릇 즉 배열
var modelList = ArrayList<MyModel>()
private lateinit var myRecyclerAdapter: MyRecyclerAdapter
// 뷰가 화면에 그려질때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG, "MainActivity - onCreate() called")
Log.d(TAG, "MainActivity - 반복문 돌리기 전 this.modelList.size : ${this.modelList.size}")
// 10번 반복한다.
for (i in 1..10){
val myModel = MyModel(name = "쩡대리 $i", profileImage = "https://img1.daumcdn.net/thumb/C100x100.mplusfriend/?fname=http%3A%2F%2Fk.kakaocdn.net%2Fdn%2FIxxPp%2FbtqC9MkM3oH%2FPpvHOkfOiOpKUwvvWcxhJ0%2Fimg_s.jpg")
this.modelList.add(myModel)
}
Log.d(TAG, "MainActivity - 반복문 돌린 후 this.modelList.size : ${this.modelList.size}")
// 어답터 인스턴스 생성
myRecyclerAdapter = MyRecyclerAdapter(this)
myRecyclerAdapter.submitList(this.modelList)
// 리사이클러뷰 설정
my_recycler_view.apply {
// 리사이클러뷰 방향 등 설정
layoutManager = LinearLayoutManager(this@MainActivity, LinearLayoutManager.VERTICAL, false)
// 어답터 장착
adapter = myRecyclerAdapter
}
}
override fun onItemClicked(position: Int) {
Log.d(TAG, "MainActivity - onItemClicked() called / position: $position")
var name: String? = null
// 값이 비어있으면 ""를 넣는다.
// unwrapping - 언랩핑
val title: String = this.modelList[position].name ?: ""
// val title: String = name ?: "호호호"
AlertDialog.Builder(this)
.setTitle(title)
.setMessage("$title 와 함께하는 빡코딩! :)")
.setPositiveButton("오케이") { dialog, id ->
Log.d(TAG, "MainActivity - 다이얼로그 확인 버튼 클릭했음")
}
.show()
}
}
# App.kt
// context 를 가져오기 위해서
class App : Application() {
companion object {
lateinit var instance: App
private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
# MyModel.kt
class MyModel(var name: String? = null, var profileImage: String? = null) {
val TAG: String = "로그"
// 기본 생성자
init {
Log.d(TAG, "MyModel - init() called")
}
}
# MyRecyclerAdapter.kt
class MyRecyclerAdapter(myRecyclerviewInterface: MyRecyclerviewInterface): RecyclerView.Adapter<MyViewHolder>() {
val TAG: String = "로그"
private var modelList = ArrayList<MyModel>()
private var myRecyclerviewInterface :MyRecyclerviewInterface? = null
// 생성자
init {
this.myRecyclerviewInterface = myRecyclerviewInterface
}
// 뷰홀더가 생성 되었을때
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
// 연결할 레이아웃 설정
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_recycler_item, parent, false), this.myRecyclerviewInterface!!)
}
// 목록의 아이템수
override fun getItemCount(): Int {
return this.modelList.size
}
// 뷰와 뷰홀더가 묶였을때
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
Log.d(TAG, "MyRecyclerAdapter - onBindViewHolder() called / position: $position")
holder.bind(this.modelList[position])
}
// 외부에서 데이터 넘기기
fun submitList(modelList: ArrayList<MyModel>){
this.modelList = modelList
}
}
# MyViewHolder.kt
// 커스텀 뷰홀더
class MyViewHolder(itemView: View,
recyclerviewInterface: MyRecyclerviewInterface):
RecyclerView.ViewHolder(itemView),
View.OnClickListener
{
val TAG: String = "로그"
private val usernameTextView = itemView.user_name_txt
private val profileImageView = itemView.profile_img
private var myRecyclerviewInterface : MyRecyclerviewInterface? = null
// 기본 생성자
init {
Log.d(TAG, "MyViewHolder - init() called")
itemView.setOnClickListener(this)
this.myRecyclerviewInterface = recyclerviewInterface
}
// 데이터와 뷰를 묶는다.
fun bind(myModel: MyModel){
Log.d(TAG, "MyViewHolder - bind() called")
// 텍스트뷰 와 실제 텍스트 데이터를 묶는다.
usernameTextView.text = myModel.name
// 이미지뷰와 실제 이미지 데이터를 묶는다 .
Glide
.with(App.instance)
.load(myModel.profileImage)
// .centerCrop()
.placeholder(R.mipmap.ic_launcher)
.into(profileImageView)
}
override fun onClick(p0: View?) {
Log.d(TAG, "MyViewHolder - onClick() called")
this.myRecyclerviewInterface?.onItemClicked(adapterPosition)
}
}
# MyRecyclerviewInterface.kt
// 커스텀 인터페이스
interface MyRecyclerviewInterface {
fun onItemClicked(position: Int)
}