Android

안드로이드 앱개발 뽀개기 씨리즈 – 개발하는 정대리

 

https://www.youtube.com/watch?v=32SGwgbUSYw&list=PLgOlaPUIbynrDSTJxS8AaE-2zYvPCjWtF&index=1

 

 


 

  1. 안드로이드개발 시작하기 / 초보개발자 / 기본 튜토리얼 / 코틀린 / 앱만들기
  2. 안드로이드개발 시작하기 #2 / 초보개발자 / 안드로이드 스튜디오 설치 / 기본 튜토리얼 / 코틀린
  3. 안드로이드개발 시작하기 #3 / 초보개발자 / 생명주기 / 그라데이션 뷰 / custom background / livetemplate / 기본 튜토리얼 / 코틀린
  4. 안드로이드개발 시작하기 #4 / 초보개발자 / 레이아웃 / LinearLayout / RelativeLayout / Constraint / 앱 만들기 / 코틀린 / kotlin
  5. 안드로이드개발 시작하기 / 초보개발자 / 레이아웃 실전 / figma / Linear Layout / 앱 만들기 / 코틀린 / kotlin
  6. 안드로이드개발 시작하기 / 초보개발자 / 클릭이벤트 / listener / method / 앱 만들기 / 코틀린 / kotlin
  7. 안드로이드개발 시작하기 / 초보개발자 / 커스텀 로티애니메이션 / 앱 만들기 / 코틀린 / kotlin
  8. 0
  9. 0
  10. 0
  11. 0
  12. 0
  13. 취준생을 위한 리사이클러뷰 만들기 #1 – 개념설명, 레이아웃 그리기 – [안드로이드] 코틀린
  14. 취준생을 위한 리사이클러뷰 만들기 #2 – 커스텀 뷰홀더 만들기 – [안드로이드] 코틀린
  15. 취준생을 위한 리사이클러뷰 만들기 #3 – 커스텀 어답터, 클릭리스너 설정 – [안드로이드] 코틀린

 

 


 

2. 안드로이드개발 시작하기 #2 / 초보개발자 / 안드로이드 스튜디오 설치 / 기본 튜토리얼 / 코틀린

 

1. 구글에서 안드로이드 스튜디오 검색
2. Android 스튜디오 설치 | Android 개발자 클릭
3. 최신 버전의 Android 스튜디오를 다운로드해야 합니다. 클릭
4. 다운로드 받아서 설치

 

  1. 프로젝트 만들기
  2. Empty Activity
  3. MyFirstAndroid
  4. Kotlin
  5. 미니멈 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)

}

 

 

 

Related posts

Leave a Comment