20231110_TIL

이상훈·2023년 11월 9일

TIL

목록 보기
78/83

최종 프로젝트

build.gradle.kts(:app)

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("kotlin-kapt")
}

android {
namespace = "com.example.moving"
compileSdk = 34

defaultConfig {
    applicationId = "com.example.moving"
    minSdk = 29
    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"
}
buildFeatures {
    viewBinding = true
}

}

dependencies {

// Support
// https://developer.android.com/jetpack/androidx/versions
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.recyclerview:recyclerview:1.3.2")
implementation("androidx.cardview:cardview:1.0.0")

// ViewModel and LiveData
// https://developer.android.com/jetpack/androidx/releases/lifecycle
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")

// Retrofit
// https://github.com/square/retrofit
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")

// Gson
// https://github.com/google/gson
implementation("com.google.code.gson:gson:2.10.1")

// Glide
// https://github.com/bumptech/glide
implementation("com.github.bumptech.glide:glide:4.16.0")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.3")
implementation("androidx.navigation:navigation-ui-ktx:2.7.3")
kapt("com.github.bumptech.glide:compiler:4.10.0")

// Testing
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test:runner:1.5.2")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")

implementation("com.google.android.material:material:1.10.0")
implementation("com.github.antonKozyriatskyi:CircularProgressIndicator:1.3.0")
androidTestImplementation("androidx.test.ext:junit:1.1.5")

}

AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:fullBackupContent="@xml/backup_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.Moving"
    tools:targetApi="31">
    <activity
        android:name=".SplashActivity"
        android:exported="true" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name=".detail.MovieDetailsActivity"></activity>
    <activity
        android:name=".MainActivity"
        android:exported="true" />
    <activity
        android:name=".signUp.SignUpActivity"
        android:exported="true" />
    <activity
        android:name=".signIn.SignInActivity"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

colors.xml

#FF000000 #FFFFFFFF #B3B2B2 #4CAF50 #F44336 #CCFFFFFF #3F51B5 #212121 #000000 #FF5252 #1F63AA #FFBB86FC #FF6200EE #FF3700B3 #FF03DAC5 #FF018786

strings.xml

Moving Movie Popular 인기 가장 인기있는 영화 Top Rated 평점 최고 평점 영화 Upcoming 가장 인기있는 TV 최고 평점 TV On The Air Airing Today TV Now Playing Discover Please check yout internet connection Top Rated Highest rated movies of all time Stay updated with the latest movies
<string name="main_fab_btn_description">FabBtn to add contact</string>
<string name="main_tab_title_contact">CONTACT</string>
<string name="main_tab_title_mypage">MY PAGE</string>
<string name="main_toolbar_title">무빙 출연진 연락처</string>

<string name="mypage_todo_edittext_hint">할일 추가하기</string>
<string name="mypage_todo_textview_title">할일 목록</string>
<string name="button_done">Log In</string>
<string name="button_done2">SIGN UP</string>
<string name="butotn_input">입력</string>
<string name="mypage_overlap_todo">이미 등록된 할일이 목록에 존재합니다.</string>
<string name="mypage_edittext_null">할일을 추가하시려면 텍스트를 입력해주세요!</string>

<string name="intent_userImage">userImage</string>
<string name="intent_userNameText">userName</string>
<string name="intent_userPositionText">userPosition</string>
<string name="intent_userTelText">userTel</string>


<string name="_5_10">5~10자의 영어(대소문자)와 숫자만 입력하세요.</string>
<string name="_8_15">8~15자의 영어(대소문자), 숫자, 특수문자를 포함하세요.</string>
<string name="_10_11">10~11자의 숫자만 입력하세요.</string>
<string name="kor">한글 또는 영어만 입력하세요.</string>
<string name="info">입력되지 않은 정보가 있습니다</string>

<string name="signup_cancel1">취소 되었습니다.</string>

//detail
<string name="warningBack">작성 중인 내용이 삭제될 수도 있습니다.</string>
<string name="warningNull">입력된 값이 없습니다.</string>
<string name="noticeComment">댓글을 입력하세요.</string>
<string name="comment">댓글</string>

//signIn
<string name="noticeTeam">Welcome Back!</string>
<string name="name">Full Name</string>
<string name="emailaddress">Email</string>
<string name="password">Password</string>
<string name="tel">TelPhone</string>
<string name="logIn">LOGIN</string>
<string name="signUp">SIGN UP</string>
<string name="checkNameLocale">이름/암호명을 확인해주세요</string>
<string name="successLogin">로그인 성공</string>

//writePage
<string name="subject">제목</string>
<string name="inputContents">내용을 입력해주세요</string>
<string name="cancel">취소</string>

//main
<string name="nameColon">이름 : </string>
<string name="position">Ability</string>
<string name="positionColon">직책 : </string>
<string name="teamMember">팀 멤버</string>
<string name="teamNoticeBoard">팀 게시판</string>

//signUp
<string name="notice2Team">SIGN UP</string>
<string name="inputName">이름을 입력하세요.</string>
<string name="inputID">이메일을 입력하세요.</string>
<string name="inputPassword">비밀번호를 입력하세요.</string>
<string name="inputPosition">(입력 안해도 됨)</string>
<string name="inputTel">전화번호를 입력하세요.</string>
<string name="locale">Locale</string>
<string name="inputLocale">지역명</string>

//dialog
<string name="dialog_name_edt">이름*</string>
<string name="dialog_phone_edt">전화번호*</string>
<string name="dialog_email_edt">이메일*</string>
<string name="dialog_locale_edt">지역*</string>
<string name="dialog_ability_edt">능력</string>
<string name="dialog_chip_off">OFF</string>
<string name="dialog_chip_5_minutes">5분 뒤 알림</string>
<string name="dialog_chip_10_minutes">10분 뒤 알림</string>
<string name="dialog_chip_30_minutes">30분 뒤 알림</string>
<string name="dialog_cancel_btn">취소</string>
<string name="dialog_add_btn">등록</string>
<string name="dialog_no_info_toast">* 표시가 있는 항목은 전부 입력해주세요.</string>

<string name="noti_title">연락처 알림</string>
<string name="noti_message">에게 연락을 할 시간입니다.</string>
<string name="title_activity_home">HomeActivity</string>
<string name="title_home2">Home</string>
<string name="title_dashboard">Dashboard</string>
<string name="title_notifications">Search</string>
<string name="title_activity_main">MainActivity</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>

themes.xml

mobile_navigation.xml

<fragment
    android:id="@+id/navigation_home"
    android:name="com.example.moving.ui.home.HomeFragment"
    android:label="@string/title_home"
    tools:layout="@layout/fragment_home" />

<fragment
    android:id="@+id/navigation_dashboard"
    android:name="com.example.moving.ui.dashboard.DashboardFragment"
    android:label="@string/title_dashboard"
    tools:layout="@layout/fragment_dashboard" />

<fragment
    android:id="@+id/navigation_notifications"
    android:name="com.example.moving.ui.notifications.NotificationsFragment"
    android:label="@string/title_notifications"
    tools:layout="@layout/fragment_notifications" />

<fragment
    android:id="@+id/navigation_movie"
    android:name="com.example.moving.ui.movie.MovieFragment"
    android:label="@string/title_movie"
    tools:layout="@layout/fragment_movie" />

bottom_nav_menu.xml

<item
    android:id="@+id/navigation_home"
    android:icon="@drawable/ic_tv_black_24dp"
    android:title="@string/title_home" />

<item
    android:id="@+id/navigation_dashboard"
    android:icon="@drawable/ic_dashboard_black_24dp"
    android:title="@string/title_dashboard" />

<item
    android:id="@+id/navigation_notifications"
    android:icon="@drawable/ic_search_black_24dp"
    android:title="@string/title_notifications" />

<item
    android:id="@+id/navigation_movie"
    android:icon="@drawable/ic_movie_black_24dp"
    android:title="@string/title_movie" />

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/nav_view"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="0dp"
    android:layout_marginEnd="0dp"
    android:background="?android:attr/windowBackground"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:menu="@menu/bottom_nav_menu" />

<fragment
    android:id="@+id/nav_host_fragment_activity_main"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toTopOf="@id/nav_view"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/mobile_navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_movie_details.xml

<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/movie_backdrop"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="@+id/backdrop_guideline"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.cardview.widget.CardView
        android:id="@+id/movie_poster_card"
        android:layout_width="128dp"
        android:layout_height="172dp"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="8dp"
        app:cardCornerRadius="4dp"
        app:layout_constraintBottom_toBottomOf="@+id/backdrop_guideline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/backdrop_guideline">

        <ImageView
            android:id="@+id/movie_poster"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </androidx.cardview.widget.CardView>

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/backdrop_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.4" />

    <TextView
        android:id="@+id/movie_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:textColor="@android:color/white"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/movie_poster_card"
        app:layout_constraintTop_toBottomOf="@+id/backdrop_guideline" />

    <TextView
        android:id="@+id/movie_release_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#757575"
        android:textSize="12sp"
        app:layout_constraintStart_toStartOf="@+id/movie_title"
        app:layout_constraintTop_toBottomOf="@+id/movie_title" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/movie_poster_title_barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="movie_rating,movie_release_date" />

    <TextView
        android:id="@+id/movie_overview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/movie_poster_title_barrier" />

    <RatingBar
        android:id="@+id/movie_rating"
        style="@style/Widget.AppCompat.RatingBar.Small"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="@+id/movie_poster_card"
        app:layout_constraintStart_toStartOf="@+id/movie_poster_card"
        app:layout_constraintTop_toBottomOf="@+id/movie_poster_card" />
</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.core.widget.NestedScrollView>

activity_sign_in.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#212832"
android:orientation="vertical"
android:padding="0dp">

<ImageView
    android:id="@+id/login_glide"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="centerCrop"
    app:layout_constraintTop_toTopOf="parent" />

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
            android:id="@+id/logo_login"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="0dp"
            android:gravity="center"
            android:padding="20dp"
            android:src="@drawable/login_moving_logo"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/txt_login_name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="start"
            android:layout_marginHorizontal="20dp"
            android:layout_marginTop="26dp"
            android:text="이름"
            android:textColor="#8CAAB9"
            android:textSize="18sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/logo_login" />

        <EditText
            android:id="@+id/et_login_name"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:layout_marginHorizontal="20dp"
            android:background="#4D455A64"
            android:hint="@string/inputName"
            android:inputType="text"
            android:padding="16dp"
            android:textColor="#FFFFFF"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/txt_login_name" />

        <TextView
            android:id="@+id/txt_login_locale"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="start"
            android:layout_marginHorizontal="20dp"
            android:layout_marginTop="26dp"
            android:text="지역명"
            android:textColor="#8CAAB9"
            android:textSize="18sp"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/et_login_name" />

        <EditText
            android:id="@+id/et_login_locale"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:layout_marginHorizontal="20dp"
            android:layout_marginBottom="32dp"
            android:background="#4D455A64"
            android:hint="지역명을 입력해주세요."
            android:inputType="textPassword"
            android:padding="16dp"
            android:textColor="#FFFFFF"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/txt_login_locale" />

        <TextView
            android:id="@+id/buttonLogin"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:layout_marginHorizontal="20dp"
            android:layout_marginTop="60dp"
            android:background="#99FED36A"
            android:gravity="center"
            android:text="@string/logIn"
            android:textSize="20dp"
            android:textStyle="bold"
            app:layout_constraintBottom_toTopOf="@id/buttonSignUp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/et_login_locale" />

        <TextView
            android:id="@+id/buttonSignUp"
            android:layout_width="match_parent"
            android:layout_height="55dp"
            android:layout_marginHorizontal="20dp"
            android:layout_marginTop="26dp"
            android:layout_marginBottom="26dp"
            android:background="#991F63AA"
            android:gravity="center"
            android:text="@string/signUp"
            android:textSize="20dp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/buttonLogin" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

activity_sign_up.xml

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="@string/notice2Team"
        android:textColor="#FFFFFF"
        android:textSize="35sp"
        android:textStyle="bold"
        tools:layout_editor_absoluteX="-24dp"
        tools:layout_editor_absoluteY="16dp" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="24dp"
        android:layout_marginEnd="24dp"
        android:text="@string/name"
        android:textColor="#8CAAB9"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <EditText
        android:id="@+id/et_name"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="4dp"
        android:layout_marginEnd="24dp"
        android:background="#455A64"
        android:ems="10"
        android:hint="@string/inputName"
        android:inputType="text"
        android:padding="12dp"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_name" />

    <TextView
        android:id="@+id/tv_locale"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="24dp"
        android:text="@string/locale"
        android:textColor="#8CAAB9"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_pw" />

    <EditText
        android:id="@+id/et_locale"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="3dp"
        android:layout_marginEnd="24dp"
        android:background="#455A64"
        android:ems="10"
        android:hint="@string/inputLocale"
        android:inputType="text"
        android:padding="12dp"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_locale" />

    <TextView
        android:id="@+id/tv_ability"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="24dp"
        android:text="@string/position"
        android:textColor="#8CAAB9"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_locale" />

    <EditText
        android:id="@+id/et_ability"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="3dp"
        android:layout_marginEnd="24dp"
        android:background="#455A64"
        android:ems="10"
        android:hint="@string/inputPosition"
        android:inputType="text"
        android:padding="12dp"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_ability" />

    <TextView
        android:id="@+id/tv_emailaddress"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="24dp"
        android:text="@string/emailaddress"
        android:textColor="#8CAAB9"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_name" />

    <EditText
        android:id="@+id/et_emailaddress"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="3dp"
        android:layout_marginEnd="24dp"
        android:background="#455A64"
        android:ems="10"
        android:hint="@string/inputID"
        android:inputType="text"
        android:padding="12dp"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_emailaddress" />

    <TextView
        android:id="@+id/tv_pw"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="24dp"
        android:text="@string/password"
        android:textColor="#8CAAB9"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_emailaddress" />

    <EditText
        android:id="@+id/et_pw"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="3dp"
        android:layout_marginEnd="24dp"
        android:background="#455A64"
        android:ems="10"
        android:hint="@string/inputPassword"
        android:inputType="textPassword"
        android:padding="12dp"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_pw" />

    <TextView
        android:id="@+id/tv_tel"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="24dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="24dp"
        android:text="@string/tel"
        android:textColor="#8CAAB9"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_ability" />

    <EditText
        android:id="@+id/et_tel"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="3dp"
        android:layout_marginEnd="24dp"
        android:background="#455A64"
        android:ems="10"
        android:hint="@string/inputTel"
        android:inputType="number"
        android:padding="12dp"
        android:textColor="#FFFFFF"
        android:textSize="18sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_tel" />

    <TextView
        android:id="@+id/btn_signupOk"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginStart="24dp"
        android:layout_marginTop="26dp"
        android:layout_marginEnd="24dp"
        android:background="#FED36A"


        android:gravity="center"
        android:text="@string/button_done2"

        android:textSize="20dp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_tel" />

    <TextView
        android:id="@+id/btn_signupcancel"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:layout_marginTop="26dp"
        android:background="@color/login_blue"

        android:gravity="center"
        android:text="Already have an account? LOGIN"
        android:textSize="20dp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="@+id/btn_signupOk"

        app:layout_constraintStart_toStartOf="@+id/btn_signupOk"
        app:layout_constraintTop_toBottomOf="@+id/btn_signupOk" />

</androidx.constraintlayout.widget.ConstraintLayout>

activity_splash.xml

<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=".SplashActivity">

<ImageView
    android:id="@+id/image_splash"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:scaleType="centerCrop"/>

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_dashboard.xml

<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=".ui.dashboard.DashboardFragment">

<TextView
    android:id="@+id/text_dashboard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    android:textAlignment="center"
    android:textSize="20sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_home.xml

<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=".ui.home.HomeFragment">

<TextView
    android:id="@+id/text_home"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    android:textAlignment="center"
    android:textSize="20sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">


        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toTopOf="parent">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/popular"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/most_popular_tv" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/popular_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/toprated"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/most_toprated_tv" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/top_rated_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout2">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/on_the_air"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/on_the_air" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/on_the_air_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout3">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/airing_today"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/airing_today" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/airing_today_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout5"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout4">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/discover"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/discover" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/discover_tv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout6"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout5">

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="\n\n\n\n"
                tools:layout_editor_absoluteX="9dp" />

        </LinearLayout>
    </LinearLayout>
</ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_movie.xml

<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=".ui.movie.MovieFragment">

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <LinearLayout
            android:id="@+id/linearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toTopOf="parent">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/popular"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/most_popular" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/popular_movies"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/toprated"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/most_toprated" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/top_rated_movies"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout3"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout2">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/upcoming"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/upcoming" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/upcoming_movies"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout4"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout3">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/now_playing"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/now_playing" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/nowplaying_movies"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout5"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout4">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginTop="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/discover"
                android:textSize="18sp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="16dp"
                android:layout_marginEnd="16dp"
                android:text="@string/discover" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/discover_movies"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:clipToPadding="false"
                android:paddingStart="16dp"
                android:paddingEnd="16dp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/linearLayout6"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintTop_toBottomOf="@+id/linearLayout5">

            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="\n\n\n\n"
                tools:layout_editor_absoluteX="9dp" />

        </LinearLayout>

    </LinearLayout>
</ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_notifications.xml

<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=".ui.notifications.NotificationsFragment">

<LinearLayout
    android:id="@+id/linearLayout2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintTop_toTopOf="parent"
    tools:layout_editor_absoluteX="1dp">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="검색어"
        android:textAlignment="center"
        android:textSize="20sp" />

    <EditText
        android:id="@+id/eSearchWord"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="" />

    <Button
        android:id="@+id/bSearch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="검색" />
</LinearLayout>


<LinearLayout
    android:id="@+id/linearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintTop_toBottomOf="@+id/linearLayout2">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="Movie"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="영화 검색 결과" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/search_movies"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:clipToPadding="false"
        android:paddingStart="16dp"
        android:paddingEnd="16dp" />

</LinearLayout>

<LinearLayout
    android:id="@+id/linearLayout3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintTop_toBottomOf="@+id/linearLayout">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:text="TV"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        android:text="TV 검색 결과" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/search_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:clipToPadding="false"
        android:paddingStart="16dp"
        android:paddingEnd="16dp" />

</LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

item_movie.xml

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="128dp"
android:layout_height="192dp"
android:layout_marginEnd="8dp"
app:cardCornerRadius="4dp">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/item_movie_poster"
        android:layout_width="match_parent"
        android:layout_height="172dp" />

    <TextView
        android:id="@+id/item_movie_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Title" />
</LinearLayout>

</androidx.cardview.widget.CardView>

item_tv.xml

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="128dp"
android:layout_height="192dp"
android:layout_marginEnd="8dp"
app:cardCornerRadius="4dp">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/item_tv_poster"
        android:layout_width="match_parent"
        android:layout_height="172dp" />

    <TextView
        android:id="@+id/item_tv_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Title" />
</LinearLayout>

</androidx.cardview.widget.CardView>

GetTVResponse.kt

package com.example.moving

import com.google.gson.annotations.SerializedName

data class GetTVResponse (
@SerializedName("page") val page: Int,
@SerializedName("results") val tvlist: List,
@SerializedName("totla_pages") val pages: Int,
@SerializedName("totla_results") val results: Int
)

MainActivity.kt

package com.example.moving

import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.example.moving.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    val navView: BottomNavigationView = binding.navView

    val navController = findNavController(R.id.nav_host_fragment_activity_main)
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    val appBarConfiguration = AppBarConfiguration(setOf(R.id.navigation_movie, R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
    setupActionBarWithNavController(navController, appBarConfiguration)
    navView.setupWithNavController(navController)
}

companion object {
    const val MOVIE_BACKDROP = "extra_movie_backdrop"
    const val MOVIE_POSTER = "extra_movie_poster"
    const val MOVIE_TITLE = "extra_movie_title"
    const val MOVIE_RATING = "extra_movie_rating"
    const val MOVIE_RELEASE_DATE = "extra_movie_release_date"
    const val MOVIE_OVERVIEW = "extra_movie_overview"
}

}

MoviesAdapter.kt

package com.example.moving

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.example.moving.common.Movie

class MoviesAdapter (var movies: MutableList, var onMovieClick: (movie: Movie) -> Unit
) : RecyclerView.Adapter<MoviesAdapter.MovieViewHolder>(){

inner class MovieViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val poster: ImageView = itemView.findViewById(R.id.item_movie_poster)
    fun bind(movie: Movie) {
        Glide.with(itemView)
            .load("https://image.tmdb.org/t/p/w342${movie.poster_path}")
            .transform(CenterCrop())
            .into(poster)
        itemView.findViewById<TextView>(R.id.item_movie_title).text = movie.title
        itemView.setOnClickListener { onMovieClick.invoke(movie) }
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
    val view = LayoutInflater
        .from(parent.context)
        .inflate(R.layout.item_movie, parent, false)
    return MovieViewHolder(view)
}

override fun getItemCount(): Int = movies.size

override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
    holder.bind(movies[position])
}

fun appendMovies(movies: List<Movie>) {
    this.movies.addAll(movies)
    notifyItemRangeInserted(
        this.movies.size,
        movies.size - 1
    )
}

fun removeMovies(movies: List<Movie>) {
    this.movies.removeAll(movies)
}

}

SplashActivity.kt

package com.example.moving

import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import com.example.moving.databinding.ActivitySplashBinding
import com.example.moving.signIn.SignInActivity

class SplashActivity : AppCompatActivity() {

lateinit var binding: ActivitySplashBinding
override fun onCreate(savedInstanceState: Bundle?) {
    binding = ActivitySplashBinding.inflate(layoutInflater)
    super.onCreate(savedInstanceState)
    setContentView(binding.root)

    val splashImage = binding.imageSplash

    Glide.with(this).load(R.raw.splash_background).into(splashImage)

    splashImage.setOnClickListener {
        startActivity(Intent(this, SignInActivity::class.java))
    }
}

}

TV.kt

package com.example.moving

import com.google.gson.annotations.SerializedName

data class TV (
@SerializedName("id")
val id : Long,
@SerializedName("name")
val name : String,
@SerializedName("overview")
val overview : String,
@SerializedName("poster_path")
val poster_path: String,
@SerializedName("backdrop_path")
val backdrop_path: String,
@SerializedName("vote_average")
val rating: Float,
@SerializedName("vote_count")
val vcount: Long,
@SerializedName("first_air_date")
val first_air_date: String,
@SerializedName("popularity")
val prating: Float
)

TVAdapter.kt

package com.example.moving

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop

class TVAdapter (var tvlist: MutableList, var onTVClick: (tv: TV) -> Unit
) : RecyclerView.Adapter<TVAdapter.TvViewHolder>(){

inner class TvViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val poster: ImageView = itemView.findViewById(R.id.item_tv_poster)
    fun bind(tv: TV) {
        Glide.with(itemView)
            .load("https://image.tmdb.org/t/p/w342${tv.poster_path}")
            .transform(CenterCrop())
            .into(poster)
        itemView.findViewById<TextView>(R.id.item_tv_title).text = tv.name
        itemView.setOnClickListener { onTVClick.invoke(tv) }
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TvViewHolder {
    val view = LayoutInflater
        .from(parent.context)
        .inflate(R.layout.item_tv, parent, false)
    return TvViewHolder(view)
}

override fun getItemCount(): Int = tvlist.size

override fun onBindViewHolder(holder: TvViewHolder, position: Int) {
    holder.bind(tvlist[position])
}

fun appendTV(tvlist: List<TV>) {
    this.tvlist.addAll(tvlist)
    notifyItemRangeInserted(
        this.tvlist.size,
        tvlist.size - 1
    )
}

fun removeTV(tvlist: List<TV>) {
    this.tvlist.removeAll(tvlist)
}

}

TVRepository.kt

package com.example.moving

import com.example.moving.common.Api
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object TVRepository {
private val api: Api //인터페이스 구현

init {
    val retrofit = Retrofit.Builder()
        .baseUrl("https://api.themoviedb.org/3/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    api = retrofit.create(Api::class.java)
}

fun getPopularTV(page: Int = 1,
                 onSuccess: (tvlist: List<TV>) -> Unit,
                 onError: () -> Unit ) {
    TVRepository.api.getPopularTV(page = page)
        .enqueue(object : Callback<GetTVResponse> {
            override fun onResponse(
                call: Call<GetTVResponse>,
                response: Response<GetTVResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.tvlist)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetTVResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getTopRatedTV(page: Int = 1,
                  onSuccess: (tvlist: List<TV>) -> Unit,
                  onError: () -> Unit){
    api.getTopRatedTV(page = page)
        .enqueue(object : Callback<GetTVResponse> {
            override fun onResponse(
                call: Call<GetTVResponse>,
                response: Response<GetTVResponse>
            ) {
                if(response.isSuccessful) {
                    val responseBody = response.body()
                    if(responseBody != null) {
                        onSuccess.invoke(responseBody.tvlist)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetTVResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getOnTheAirTV(page: Int = 1,
                  onSuccess: (tvlist: List<TV>) -> Unit,
                  onError: () -> Unit){
    api.getOnTheAirTV(page = page)
        .enqueue(object : Callback<GetTVResponse> {
            override fun onResponse(
                call: Call<GetTVResponse>,
                response: Response<GetTVResponse>
            ) {
                if(response.isSuccessful) {
                    val responseBody = response.body()
                    if(responseBody != null) {
                        onSuccess.invoke(responseBody.tvlist)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetTVResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getAiringTodayTV(page: Int = 1,
                     onSuccess: (tvlist: List<TV>) -> Unit,
                     onError: () -> Unit){
    api.getAiringTodayTV(page = page)
        .enqueue(object : Callback<GetTVResponse> {
            override fun onResponse(
                call: Call<GetTVResponse>,
                response: Response<GetTVResponse>
            ) {
                if(response.isSuccessful) {
                    val responseBody = response.body()
                    if(responseBody != null) {
                        onSuccess.invoke(responseBody.tvlist)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetTVResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getDiscoverTV(page: Int = 1,
                  onSuccess: (tvlist: List<TV>) -> Unit,
                  onError: () -> Unit){
    api.getDiscoverTV(page = page)
        .enqueue(object : Callback<GetTVResponse> {
            override fun onResponse(
                call: Call<GetTVResponse>,
                response: Response<GetTVResponse>
            ) {
                if(response.isSuccessful) {
                    val responseBody = response.body()
                    if(responseBody != null) {
                        onSuccess.invoke(responseBody.tvlist)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetTVResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getSearchTV(page: Int = 1, query: String,
                onSuccess: (tvlist: List<TV>) -> Unit,
                onError: () -> Unit){
    api.getSearchTV(page = page, query = query)
        .enqueue(object : Callback<GetTVResponse> {
            override fun onResponse(
                call: Call<GetTVResponse>,
                response: Response<GetTVResponse>
            ) {
                if(response.isSuccessful) {
                    val responseBody = response.body()
                    if(responseBody != null) {
                        onSuccess.invoke(responseBody.tvlist)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetTVResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

}

Api.kt

package com.example.moving.common

import com.example.moving.GetTVResponse
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface Api {
@GET("movie/popular")
fun getPopularMovies(
@Query("api_key")
apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
@Query("page")
page: Int,
@Query("language")
language : String = "ko,en-US"
): Call

@GET("movie/top_rated")
fun getTopRatedMovies(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetMoviesResponse>

@GET("movie/upcoming")
fun getUpcomingMovies(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetMoviesResponse>

@GET("movie/now_playing")
fun getNowPlayingMovies(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetMoviesResponse>

@GET("discover/movie")
fun getDiscoverMovies(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetMoviesResponse>

@GET("tv/popular")
fun getPopularTV(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetTVResponse>

@GET("tv/top_rated")
fun getTopRatedTV(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetTVResponse>

@GET("tv/on_the_air")
fun getOnTheAirTV(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetTVResponse>

@GET("tv/airing_today")
fun getAiringTodayTV(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetTVResponse>

@GET("discover/tv")
fun getDiscoverTV(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetTVResponse>

@GET("search/movie")
fun getSearchMovies(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("query")
    query : String,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetMoviesResponse>

@GET("search/tv")
fun getSearchTV(
    @Query("api_key")
    apiKey: String = "9897e125444076b7172d70bff4fe9c5d",
    @Query("page")
    page : Int,
    @Query("query")
    query : String,
    @Query("language")
    language : String = "ko,en-US"
): Call<GetTVResponse>

}

GetMoviesResponse.kt

package com.example.moving.common

import com.google.gson.annotations.SerializedName

data class GetMoviesResponse(
@SerializedName("page")
val page: Int,
@SerializedName("results")
val movies: List,
@SerializedName("total_pages")
val pages: Int,
@SerializedName("total_results")
val results: Int
)

Movie.kt

package com.example.moving.common

import com.google.gson.annotations.SerializedName

data class Movie(
@SerializedName("id")
val id : Long,
@SerializedName("title")
val title : String,
@SerializedName("overview")
val overview : String,
@SerializedName("poster_path")
val poster_path: String,
@SerializedName("backdrop_path")
val backdrop_path: String,
@SerializedName("vote_average")
val rating: Float,
@SerializedName("vote_count")
val vcount: Long,
@SerializedName("release_date")
val releaseDate: String,
@SerializedName("popularity")
val prating: Float
)

MoviesRepository.kt

package com.example.moving.common

import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object MoviesRepository {

private val api: Api

init {
    val retrofit = Retrofit.Builder()
        .baseUrl("https://api.themoviedb.org/3/")
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    api = retrofit.create(Api::class.java)
}

fun getPopularMovies(page: Int = 1,
                     onSuccess: (movies: List<Movie>) -> Unit,
                     onError: () -> Unit ) {
    api.getPopularMovies(page = page)
        .enqueue(object : Callback<GetMoviesResponse> {
            override fun onResponse(
                call: Call<GetMoviesResponse>,
                response: Response<GetMoviesResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.movies)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetMoviesResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getTopRatedMovies(page: Int = 1,
                      onSuccess: (movies: List<Movie>) -> Unit,
                      onError: () -> Unit ) {
    api.getTopRatedMovies(page = page)
        .enqueue(object : Callback<GetMoviesResponse> {
            override fun onResponse(
                call: Call<GetMoviesResponse>,
                response: Response<GetMoviesResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.movies)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetMoviesResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getUpcomingMovies( page: Int = 1,
                       onSuccess: (movies: List<Movie>) -> Unit,
                       onError: () -> Unit ) {
    api.getUpcomingMovies(page = page)
        .enqueue(object : Callback<GetMoviesResponse> {
            override fun onResponse(
                call: Call<GetMoviesResponse>,
                response: Response<GetMoviesResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.movies)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetMoviesResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getNowPlayingMovies( page: Int = 1,
                         onSuccess: (movies: List<Movie>) -> Unit,
                         onError: () -> Unit ) {
    api.getNowPlayingMovies(page = page)
        .enqueue(object : Callback<GetMoviesResponse> {
            override fun onResponse(
                call: Call<GetMoviesResponse>,
                response: Response<GetMoviesResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.movies)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetMoviesResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getDiscoverMovies( page: Int = 1,
                       onSuccess: (movies: List<Movie>) -> Unit,
                       onError: () -> Unit ) {
    api.getDiscoverMovies(page = page)
        .enqueue(object : Callback<GetMoviesResponse> {
            override fun onResponse(
                call: Call<GetMoviesResponse>,
                response: Response<GetMoviesResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.movies)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetMoviesResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

fun getSearchMovies( page: Int = 1, query: String,
                     onSuccess: (movies: List<Movie>) -> Unit,
                     onError: () -> Unit ) {
    api.getSearchMovies(page = page, query = query)
        .enqueue(object : Callback<GetMoviesResponse> {
            override fun onResponse(
                call: Call<GetMoviesResponse>,
                response: Response<GetMoviesResponse>
            ) {
                if (response.isSuccessful) {
                    val responseBody = response.body()

                    if (responseBody != null) {
                        onSuccess.invoke(responseBody.movies)
                    } else {
                        onError.invoke()
                    }
                } else {
                    onError.invoke()
                }
            }

            override fun onFailure(call: Call<GetMoviesResponse>, t: Throwable) {
                onError.invoke()
            }
        })
}

}

MovieDetailsActivity.kt

package com.example.moving.detail

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView
import android.widget.RatingBar
import android.widget.TextView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.example.moving.MainActivity.Companion.MOVIE_BACKDROP
import com.example.moving.MainActivity.Companion.MOVIE_OVERVIEW
import com.example.moving.MainActivity.Companion.MOVIE_POSTER
import com.example.moving.MainActivity.Companion.MOVIE_RATING
import com.example.moving.MainActivity.Companion.MOVIE_RELEASE_DATE
import com.example.moving.MainActivity.Companion.MOVIE_TITLE
import com.example.moving.R

class MovieDetailsActivity : AppCompatActivity() {

private lateinit var backdrop: ImageView
private lateinit var poster: ImageView
private lateinit var title: TextView
private lateinit var rating: RatingBar
private lateinit var releaseDate: TextView
private lateinit var overview: TextView

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

    backdrop = findViewById(R.id.movie_backdrop)
    poster = findViewById(R.id.movie_poster)
    title = findViewById(R.id.movie_title)
    rating = findViewById(R.id.movie_rating)
    releaseDate = findViewById(R.id.movie_release_date)
    overview = findViewById(R.id.movie_overview)

    val extras = intent.extras

    if (extras != null) {
        populateDetails(extras)
    } else {
        finish()
    }
}


private fun populateDetails(extras: Bundle) {
    extras.getString(MOVIE_BACKDROP)?.let { backdropPath ->
        Glide.with(this)
            .load("https://image.tmdb.org/t/p/w1280$backdropPath")
            .transform(CenterCrop())
            .into(backdrop)
    }

    extras.getString(MOVIE_POSTER)?.let { posterPath ->
        Glide.with(this)
            .load("https://image.tmdb.org/t/p/w342$posterPath")
            .transform(CenterCrop())
            .into(poster)
    }

    title.text = extras.getString(MOVIE_TITLE, "")
    rating.rating = extras.getFloat(MOVIE_RATING, 0f) / 2
    releaseDate.text = extras.getString(MOVIE_RELEASE_DATE, "")
    overview.text = extras.getString(MOVIE_OVERVIEW, "")
}

}

SignInActivity.kt

package com.example.moving.signIn

import android.content.Intent
import android.os.Bundle
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import com.example.moving.R
import com.example.moving.MainActivity
import com.example.moving.signUp.SignUpActivity

class SignInActivity : AppCompatActivity() {

private lateinit var editTextName: EditText
private lateinit var editTextLocale: EditText
private lateinit var buttonLogin: TextView
private lateinit var buttonSignUp: TextView

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

    /*Glide 배경 움짤 추가 */
    val loginGlide = findViewById<ImageView>(R.id.login_glide)
    Glide.with(this).load(R.raw.login_background).into(loginGlide)
    //

    editTextName = findViewById(R.id.et_login_name)
    editTextLocale = findViewById(R.id.et_login_locale)
    buttonLogin = findViewById(R.id.buttonLogin)
    buttonSignUp = findViewById(R.id.buttonSignUp)

    buttonLogin.setOnClickListener {

        val checkName = intent.getStringExtra("userName") ?: "name"
        val checkEmailAddress = intent.getStringExtra("userEmailAddress") ?: "emailaddress"
        val checkTel = intent.getStringExtra("userTel") ?: "tel"
        val checkLocale = intent.getStringExtra("userLocale") ?: "locale"
        val checkAbility = intent.getStringExtra("userAbility") ?: "ability"

        val loginName = editTextName.text.toString()   // 이름, 암호명으로 로그인 변경 작업
        val loginLocale = editTextLocale.text.toString()

        if (loginName.isEmpty() || loginLocale.isEmpty()) {
            Toast.makeText(this, "이름/암호명 모두 입력해주세요.", Toast.LENGTH_SHORT).show()
        } else if((loginName == checkName) && (loginLocale == checkLocale)){
            Toast.makeText(this, R.string.successLogin, Toast.LENGTH_SHORT).show()
            val intent = Intent(this, MainActivity::class.java)
            intent.putExtra("userName", checkName)
            intent.putExtra("userEmailAddress", checkEmailAddress)
            intent.putExtra("userTel", checkTel)
            intent.putExtra("userAbility", checkAbility)
            intent.putExtra("userLocale", checkLocale)
            startActivity(intent)
            finish()
        } else{
            Toast.makeText(this, R.string.checkNameLocale, Toast.LENGTH_SHORT).show()
        }
    }

    buttonSignUp.setOnClickListener {
        startActivity(Intent(this, SignUpActivity::class.java))
    }
}

}

SignUpActivity.kt

package com.example.moving.signUp

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.res.ResourcesCompat
import com.example.moving.R
import com.example.moving.signIn.SignInActivity
import java.util.regex.Pattern

class SignUpActivity : AppCompatActivity() {

private val emailaddressPattern = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)\$")
private val pwPattern = Pattern.compile("^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[!@#\$%^&+=]).{8,15}\$")
private val localePattern = Pattern.compile("^[가-힣a-zA-Z]*\$")
private val namePattern = Pattern.compile("^[가-힣a-zA-Z]*\$")
private val telPattern = Pattern.compile("^[0-9]{10,11}\$")
private var imgSet: Int = R.drawable.logo1 // 기본 값으로 초기화

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

    val et_name = findViewById<EditText>(R.id.et_name)
    val et_emailaddress = findViewById<EditText>(R.id.et_emailaddress)
    val et_pw = findViewById<EditText>(R.id.et_pw)
    val et_locale = findViewById<EditText>(R.id.et_locale)
    val et_ability = findViewById<EditText>(R.id.et_ability)
    val et_tel = findViewById<EditText>(R.id.et_tel)
    val btn_signUp = findViewById<TextView>(R.id.btn_signupOk)
    val btn_signCancel = findViewById<TextView>(R.id.btn_signupcancel)




    et_emailaddress.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val emailaddress = s.toString()
            val valid = emailaddressPattern.matcher(emailaddress).matches()
            if (!valid) {
                et_emailaddress.error = getString(R.string._5_10)
            }
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })

    et_pw.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val pw = s.toString()
            val valid = pwPattern.matcher(pw).matches()
            if (!valid) {
                et_pw.error = getString(R.string._8_15)
            }
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })

    et_locale.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val locale = s.toString()
            val valid = localePattern.matcher(locale).matches()
            if (!valid) {
                et_locale.error = getString(R.string.kor)
            }
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })

    et_tel.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val tel = s.toString()
            val valid = telPattern.matcher(tel).matches()
            if (!valid) {
                et_tel.error = getString(R.string._10_11)
            }
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })

    et_name.addTextChangedListener(object : TextWatcher {
        override fun afterTextChanged(s: Editable?) {
            val name = s.toString()
            val valid = namePattern.matcher(name).matches()
            if (!valid) {
                et_name.error = getString(R.string.kor)
            }
        }

        override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
    })

    //이미지 초기화

// val iv_logo = findViewById(R.id.imageView)
// iv_logo.setOnClickListener {
// imgSet = when ((1..6).random()) {
// 1 -> R.drawable.logo1
// 2 -> R.drawable.logo2
// 3 -> R.drawable.logo3
// 4 -> R.drawable.logo4
// 5 -> R.drawable.logo5
// else -> R.drawable.logo1
// }
//
// iv_logo.setImageDrawable(ResourcesCompat.getDrawable(resources, imgSet, null))
//
// }

    btn_signUp.setOnClickListener{
        val name = et_name.text.toString()
        val emailaddress = et_emailaddress.text.toString()
        val pw = et_pw.text.toString()
        val locale = et_locale.text.toString()
        val ability = et_ability.text.toString()
        val tel = et_tel.text.toString()

        if (name.isBlank() || emailaddress.isBlank() || pw.isBlank() || locale.isBlank() || tel.isBlank()) {
            Toast.makeText(this, getString(R.string.info), Toast.LENGTH_SHORT).show()
            return@setOnClickListener
        }


        val nameValid = namePattern.matcher(name).matches()
        val emailaddressValid = emailaddressPattern.matcher(emailaddress).matches()
        val pwValid = pwPattern.matcher(pw).matches()
        val localeValid = localePattern.matcher(locale).matches()
        val telValid = telPattern.matcher(tel).matches()

        if (!nameValid) {
            et_name.error = getString(R.string.kor)
            return@setOnClickListener
        }

        if (!emailaddressValid) {
            et_emailaddress.error = getString(R.string._5_10)
            return@setOnClickListener
        }

        if (!pwValid) {
            et_pw.error = getString(R.string._8_15)
            return@setOnClickListener
        }

        if (!localeValid) {
            et_locale.error = getString(R.string.kor)
            return@setOnClickListener
        }

        if (!telValid) {
            et_tel.error = getString(R.string._10_11)
            return@setOnClickListener
        }

        val intent = Intent(this, SignInActivity::class.java)

        //수정하겠습니다.
        intent.putExtra("userName", name)
        intent.putExtra("userEmailAddress", emailaddress)
        intent.putExtra("userTel", tel)
        intent.putExtra("userLocale", locale)
        intent.putExtra("userAbility", ability)
        startActivity(intent)
        finish()
    }

    btn_signCancel.setOnClickListener {
        Toast.makeText(this@SignUpActivity, "취소 되었습니다.", Toast.LENGTH_SHORT).show()
        val intent = Intent(this@SignUpActivity, SignInActivity::class.java)
        startActivity(intent)
        finish()
    }


}

}

DashboardFragment.kt

package com.example.moving.ui.dashboard

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.moving.databinding.FragmentDashboardBinding

class DashboardFragment : Fragment() {

private var _binding: FragmentDashboardBinding? = null

// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    val dashboardViewModel =
        ViewModelProvider(this).get(DashboardViewModel::class.java)

    _binding = FragmentDashboardBinding.inflate(inflater, container, false)
    val root: View = binding.root

    val textView: TextView = binding.textDashboard
    dashboardViewModel.text.observe(viewLifecycleOwner) {
        textView.text = it
    }
    return root
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

}

DashboardViewModel.kt

package com.example.moving.ui.dashboard

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class DashboardViewModel : ViewModel() {

private val _text = MutableLiveData<String>().apply {
    value = "This is dashboard Fragment"
}
val text: LiveData<String> = _text

}

HomeFragment.kt

package com.example.moving.ui.home

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.moving.MainActivity
import com.example.moving.R
import com.example.moving.TV
import com.example.moving.TVAdapter
import com.example.moving.TVRepository
import com.example.moving.databinding.FragmentHomeBinding
import com.example.moving.detail.MovieDetailsActivity

class HomeFragment : Fragment() {
lateinit var root : View

private lateinit var popularTV: RecyclerView
private lateinit var popularTVAdapter: TVAdapter
private lateinit var popularTVLayoutMgr: LinearLayoutManager
private var popularTVPage = 1

private lateinit var topRatedTV: RecyclerView
private lateinit var topRatedTVAdapter: TVAdapter
private lateinit var topRatedTVLayoutMgr: LinearLayoutManager
private var topRatedTVPage = 1

private lateinit var onTheAirTV: RecyclerView
private lateinit var onTheAirTVAdapter: TVAdapter
private lateinit var onTheAirTVLayoutMgr: LinearLayoutManager
private var onTheAirTVPage = 1

private lateinit var airingTodayTV: RecyclerView
private lateinit var airingTodayTVAdapter: TVAdapter
private lateinit var airingTodayTVLayoutMgr: LinearLayoutManager
private var airingTodayTVPage = 1

private lateinit var discoverTV: RecyclerView
private lateinit var discoverTVAdapter: TVAdapter
private lateinit var discoverTVLayoutMgr: LinearLayoutManager
private var discoverTVPage = 1


override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?,
                           savedInstanceState: Bundle? ): View? {

    root = inflater.inflate(R.layout.fragment_home, container, false)

    popularTV = root.findViewById(R.id.popular_tv)
    popularTVLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    popularTV.layoutManager = popularTVLayoutMgr
    popularTVAdapter = TVAdapter(mutableListOf()) { tv -> showTVDetails(tv) }
    popularTV.adapter = popularTVAdapter

    getPopularTV()


    topRatedTV = root.findViewById(R.id.top_rated_tv)
    topRatedTVLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    topRatedTV.layoutManager = topRatedTVLayoutMgr
    topRatedTVAdapter = TVAdapter(mutableListOf()) { tv -> showTVDetails(tv) }
    topRatedTV.adapter = topRatedTVAdapter

    getTopRatedTV()


    onTheAirTV = root.findViewById(R.id.on_the_air_tv)
    onTheAirTVLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    onTheAirTV.layoutManager = onTheAirTVLayoutMgr
    onTheAirTVAdapter = TVAdapter(mutableListOf()) { tv -> showTVDetails(tv) }
    onTheAirTV.adapter = onTheAirTVAdapter

    getOnTheAirTV()


    airingTodayTV = root.findViewById(R.id.airing_today_tv)
    airingTodayTVLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    airingTodayTV.layoutManager = airingTodayTVLayoutMgr
    airingTodayTVAdapter = TVAdapter(mutableListOf()) { tv -> showTVDetails(tv) }
    airingTodayTV.adapter = airingTodayTVAdapter

    getAiringTodayTV()


    discoverTV = root.findViewById(R.id.discover_tv)
    discoverTVLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    discoverTV.layoutManager = discoverTVLayoutMgr
    discoverTVAdapter = TVAdapter(mutableListOf()) { tv -> showTVDetails(tv) }
    discoverTV.adapter = discoverTVAdapter

    getDiscoverTV()


    return root
}


private fun getPopularTV() {
    TVRepository.getPopularTV(
        popularTVPage,
        ::onPopularTVFetched,
        ::onError
    )
}

private fun onPopularTVFetched(tvlist: List<TV>) {
    popularTVAdapter.appendTV(tvlist)
    attachPopularTVOnScrollListener()
}

private fun attachPopularTVOnScrollListener() {
    popularTV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = popularTVLayoutMgr.itemCount
            val visibleItemCount = popularTVLayoutMgr.childCount
            val firstVisibleItem = popularTVLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                popularTV.removeOnScrollListener(this)
                popularTVPage++
                getPopularTV()
            }
        }
    })
}

private fun getTopRatedTV() {
    TVRepository.getTopRatedTV(
        topRatedTVPage,
        ::onTopRatedTVFetched,
        ::onError
    )
}

private fun onTopRatedTVFetched(tvlist: List<TV>) {
    topRatedTVAdapter.appendTV(tvlist)
    attachTopRatedTVOnScrollListener()
}

private fun attachTopRatedTVOnScrollListener() {
    topRatedTV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = topRatedTVLayoutMgr.itemCount
            val visibleItemCount = topRatedTVLayoutMgr.childCount
            val firstVisibleItem = topRatedTVLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                topRatedTV.removeOnScrollListener(this)
                topRatedTVPage++
                getTopRatedTV()
            }
        }
    })
}

private fun getOnTheAirTV() {
    TVRepository.getOnTheAirTV(
        onTheAirTVPage,
        ::onOnTheAirTVFetched,
        ::onError
    )
}

private fun onOnTheAirTVFetched(tvlist: List<TV>) {
    onTheAirTVAdapter.appendTV(tvlist)
    attachOnTheAirTVOnScrollListener()
}

private fun attachOnTheAirTVOnScrollListener() {
    onTheAirTV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = onTheAirTVLayoutMgr.itemCount
            val visibleItemCount = onTheAirTVLayoutMgr.childCount
            val firstVisibleItem = onTheAirTVLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                onTheAirTV.removeOnScrollListener(this)
                onTheAirTVPage++
                getOnTheAirTV()
            }
        }
    })
}


private fun getAiringTodayTV() {
    TVRepository.getAiringTodayTV(
        airingTodayTVPage,
        ::onAiringTodayTVFetched,
        ::onError
    )
}

private fun onAiringTodayTVFetched(tvlist: List<TV>) {
    airingTodayTVAdapter.appendTV(tvlist)
    attachAiringTodayTVOnScrollListener()
}

private fun attachAiringTodayTVOnScrollListener() {
    airingTodayTV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = airingTodayTVLayoutMgr.itemCount
            val visibleItemCount = airingTodayTVLayoutMgr.childCount
            val firstVisibleItem = airingTodayTVLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                airingTodayTV.removeOnScrollListener(this)
                airingTodayTVPage++
                getAiringTodayTV()
            }
        }
    })
}

private fun getDiscoverTV() {
    TVRepository.getDiscoverTV(
        discoverTVPage,
        ::onDiscoverTVFetched,
        ::onError
    )
}

private fun onDiscoverTVFetched(tvlist: List<TV>) {
    discoverTVAdapter.appendTV(tvlist)
    attachDiscoverTVOnScrollListener()
}

private fun attachDiscoverTVOnScrollListener() {
    discoverTV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = discoverTVLayoutMgr.itemCount
            val visibleItemCount = discoverTVLayoutMgr.childCount
            val firstVisibleItem = discoverTVLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                discoverTV.removeOnScrollListener(this)
                discoverTVPage++
                getDiscoverTV()
            }
        }
    })
}


private fun onError() {
    Toast.makeText(activity, "error Movies", Toast.LENGTH_SHORT).show()
}

private fun showTVDetails(tv: TV) {
    val intent = Intent(activity, MovieDetailsActivity::class.java)
    intent.putExtra(MainActivity.MOVIE_BACKDROP, tv.backdrop_path)
    intent.putExtra(MainActivity.MOVIE_POSTER, tv.poster_path)
    intent.putExtra(MainActivity.MOVIE_TITLE, tv.name)
    intent.putExtra(MainActivity.MOVIE_RATING, tv.rating)
    intent.putExtra(MainActivity.MOVIE_RELEASE_DATE, tv.first_air_date)
    intent.putExtra(MainActivity.MOVIE_OVERVIEW, tv.overview)
    startActivity(intent)
}

}

HomeViewModel.kt

package com.example.moving.ui.home

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class HomeViewModel : ViewModel() {

private val _text = MutableLiveData<String>().apply {
    value = "This is home Fragment"
}
val text: LiveData<String> = _text

}

MovieFragment.kt

package com.example.moving.ui.movie

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.moving.MainActivity
import com.example.moving.MoviesAdapter
import com.example.moving.R
import com.example.moving.common.MoviesRepository
import com.example.moving.common.Movie
import com.example.moving.detail.MovieDetailsActivity

class MovieFragment : Fragment() {
lateinit var root: View

private lateinit var popularMovies: RecyclerView
private lateinit var popularMoviesAdapter: MoviesAdapter
private lateinit var popularMoviesLayoutMgr: LinearLayoutManager
private var popularMoviesPage = 1

private lateinit var topRatedMovies: RecyclerView
private lateinit var topRatedMoviesAdapter: MoviesAdapter
private lateinit var topRatedMoviesLayoutMgr: LinearLayoutManager
private var topRatedMoviesPage = 1

private lateinit var upcomingMovies: RecyclerView
private lateinit var upcomingMoviesAdapter: MoviesAdapter
private lateinit var upcomingMoviesLayoutMgr: LinearLayoutManager
private var upcomingMoviesPage = 1

private lateinit var nowplayingMovies: RecyclerView
private lateinit var nowplayingMoviesAdapter: MoviesAdapter
private lateinit var nowplayingMoviesLayoutMgr: LinearLayoutManager
private var nowplayingMoviesPage = 1

private lateinit var discoverMovies: RecyclerView
private lateinit var discoverMoviesAdapter: MoviesAdapter
private lateinit var discoverMoviesLayoutMgr: LinearLayoutManager
private var discoverMoviesPage = 1

override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?,
                           savedInstanceState: Bundle? ): View? {
    root = inflater.inflate(R.layout.fragment_movie, container, false)

    popularMovies = root.findViewById(R.id.popular_movies)
    popularMoviesLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    popularMovies.layoutManager = popularMoviesLayoutMgr
    popularMoviesAdapter = MoviesAdapter(mutableListOf()) { movie -> showMovieDetails(movie) }
    popularMovies.adapter = popularMoviesAdapter

    getPopularMovies()


    topRatedMovies = root.findViewById(R.id.top_rated_movies)
    topRatedMoviesLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    topRatedMovies.layoutManager = topRatedMoviesLayoutMgr
    topRatedMoviesAdapter = MoviesAdapter(mutableListOf()) { movie -> showMovieDetails(movie) }
    topRatedMovies.adapter = topRatedMoviesAdapter

    getTopRatedMovies()


    upcomingMovies = root.findViewById(R.id.upcoming_movies)
    upcomingMoviesLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    upcomingMovies.layoutManager = upcomingMoviesLayoutMgr
    upcomingMoviesAdapter = MoviesAdapter(mutableListOf()) { movie -> showMovieDetails(movie) }
    upcomingMovies.adapter = upcomingMoviesAdapter

    getUpcomingMovies()


    nowplayingMovies = root.findViewById(R.id.nowplaying_movies)
    nowplayingMoviesLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    nowplayingMovies.layoutManager = nowplayingMoviesLayoutMgr
    nowplayingMoviesAdapter = MoviesAdapter(mutableListOf()) { movie -> showMovieDetails(movie) }
    nowplayingMovies.adapter = nowplayingMoviesAdapter

    getNowplayingMovies()


    discoverMovies = root.findViewById(R.id.discover_movies)
    discoverMoviesLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    discoverMovies.layoutManager = discoverMoviesLayoutMgr
    discoverMoviesAdapter = MoviesAdapter(mutableListOf()) { movie -> showMovieDetails(movie) }
    discoverMovies.adapter = discoverMoviesAdapter

    getDiscoverMovies()


    return root
}

private fun getPopularMovies() {
    MoviesRepository.getPopularMovies(
        popularMoviesPage,
        ::onPopularMoviesFetched,
        ::onError
    )
}

private fun onPopularMoviesFetched(movies: List<Movie>) {
    popularMoviesAdapter.appendMovies(movies)
    attachPopularMoviesOnScrollListener()
}

private fun attachPopularMoviesOnScrollListener() {
    popularMovies.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = popularMoviesLayoutMgr.itemCount
            val visibleItemCount = popularMoviesLayoutMgr.childCount
            val firstVisibleItem = popularMoviesLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                popularMovies.removeOnScrollListener(this)
                popularMoviesPage++
                getPopularMovies()
            }
        }
    })
}


private fun getTopRatedMovies() {
    MoviesRepository.getTopRatedMovies(
        topRatedMoviesPage,
        ::onTopRatedMoviesFetched,
        ::onError
    )
}

private fun attachTopRatedMoviesOnScrollListener() {
    topRatedMovies.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = topRatedMoviesLayoutMgr.itemCount
            val visibleItemCount = topRatedMoviesLayoutMgr.childCount
            val firstVisibleItem = topRatedMoviesLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                topRatedMovies.removeOnScrollListener(this)
                topRatedMoviesPage++
                getTopRatedMovies()
            }
        }
    })
}

private fun onTopRatedMoviesFetched(movies: List<Movie>) {
    topRatedMoviesAdapter.appendMovies(movies)
    attachTopRatedMoviesOnScrollListener()
}


private fun getUpcomingMovies() {
    MoviesRepository.getUpcomingMovies(
        upcomingMoviesPage,
        ::onUpcomingMoviesFetched,
        ::onError
    )
}

private fun attachUpcomingMoviesOnScrollListener() {
    upcomingMovies.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = upcomingMoviesLayoutMgr.itemCount
            val visibleItemCount = upcomingMoviesLayoutMgr.childCount
            val firstVisibleItem = upcomingMoviesLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                upcomingMovies.removeOnScrollListener(this)
                upcomingMoviesPage++
                getUpcomingMovies()
            }
        }
    })
}

private fun onUpcomingMoviesFetched(movies: List<Movie>) {
    upcomingMoviesAdapter.appendMovies(movies)
    attachUpcomingMoviesOnScrollListener()
}


private fun getNowplayingMovies() {
    MoviesRepository.getNowPlayingMovies(
        nowplayingMoviesPage,
        ::onNowplayingMoviesFetched,
        ::onError
    )
}

private fun attachNowplayingMoviesOnScrollListener() {
    nowplayingMovies.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = nowplayingMoviesLayoutMgr.itemCount
            val visibleItemCount = nowplayingMoviesLayoutMgr.childCount
            val firstVisibleItem = nowplayingMoviesLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                nowplayingMovies.removeOnScrollListener(this)
                nowplayingMoviesPage++
                getNowplayingMovies()
            }
        }
    })
}

private fun onNowplayingMoviesFetched(movies: List<Movie>) {
    nowplayingMoviesAdapter.appendMovies(movies)
    attachNowplayingMoviesOnScrollListener()
}


private fun getDiscoverMovies() {
    MoviesRepository.getDiscoverMovies(
        discoverMoviesPage,
        ::onDiscoverMoviesFetched,
        ::onError
    )
}

private fun attachDiscoverMoviesOnScrollListener() {
    discoverMovies.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = discoverMoviesLayoutMgr.itemCount
            val visibleItemCount = discoverMoviesLayoutMgr.childCount
            val firstVisibleItem = discoverMoviesLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                discoverMovies.removeOnScrollListener(this)
                discoverMoviesPage++
                getDiscoverMovies()
            }
        }
    })
}

private fun onDiscoverMoviesFetched(movies: List<Movie>) {
    discoverMoviesAdapter.appendMovies(movies)
    attachDiscoverMoviesOnScrollListener()
}


private fun onError() {
    Toast.makeText(activity, "error Movies", Toast.LENGTH_SHORT).show()
}

private fun showMovieDetails(movie: Movie) {
    val intent = Intent(activity, MovieDetailsActivity::class.java)
    intent.putExtra(MainActivity.MOVIE_BACKDROP, movie.backdrop_path)
    intent.putExtra(MainActivity.MOVIE_POSTER, movie.poster_path)
    intent.putExtra(MainActivity.MOVIE_TITLE, movie.title)
    intent.putExtra(MainActivity.MOVIE_RATING, movie.rating)
    intent.putExtra(MainActivity.MOVIE_RELEASE_DATE, movie.releaseDate)
    intent.putExtra(MainActivity.MOVIE_OVERVIEW, movie.overview)
    startActivity(intent)
}

}

NotificationsFragment.kt

package com.example.moving.ui.notifications

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.moving.MainActivity
import com.example.moving.MoviesAdapter
import com.example.moving.R
import com.example.moving.TV
import com.example.moving.TVAdapter
import com.example.moving.TVRepository
import com.example.moving.common.MoviesRepository
import com.example.moving.databinding.FragmentNotificationsBinding
import com.example.moving.detail.MovieDetailsActivity
import com.example.moving.common.Movie

class NotificationsFragment : Fragment() {
lateinit var root : View

var searchKeyword = ""

private lateinit var searchMovies: RecyclerView
private lateinit var searchMoviesAdapter: MoviesAdapter
private lateinit var searchMoviesLayoutMgr: LinearLayoutManager
private var searchMoviesPage = 1

private lateinit var searchTV: RecyclerView
private lateinit var searchTVAdapter: TVAdapter
private lateinit var searchTVLayoutMgr: LinearLayoutManager
private var searchTVPage = 1

override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?,
                           savedInstanceState: Bundle? ): View? {

    root = inflater.inflate(R.layout.fragment_notifications, container, false)

    val searchButton = root.findViewById<Button>(R.id.bSearch)
    val searchInputField = root.findViewById<EditText>(R.id.eSearchWord)

    searchMovies = root.findViewById(R.id.search_movies)
    searchMoviesLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    searchMovies.layoutManager = searchMoviesLayoutMgr
    searchMoviesAdapter = MoviesAdapter(mutableListOf()) { movie -> showMovieDetails(movie) }
    searchMovies.adapter = searchMoviesAdapter

    searchTV = root.findViewById(R.id.search_tv)
    searchTVLayoutMgr = LinearLayoutManager(
        context,
        LinearLayoutManager.HORIZONTAL,
        false
    )
    searchTV.layoutManager = searchTVLayoutMgr
    searchTVAdapter = TVAdapter(mutableListOf()) { tv -> showTVDetails(tv) }
    searchTV.adapter = searchTVAdapter

    searchButton.setOnClickListener {
        searchKeyword = searchInputField.text.toString()

        if(searchKeyword == "") {
            Toast.makeText(activity, "input keyword", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(activity, searchKeyword, Toast.LENGTH_SHORT).show()
            getSearchMovies()
            getPopularTV()
        }
    }

    return root
}

private fun removeData() {
    searchMovies.removeAllViews()
    searchTV.removeAllViews()

    searchMoviesAdapter.removeMovies(searchMoviesAdapter.movies)
    searchMoviesAdapter.notifyDataSetChanged()

    searchTVAdapter.removeTV(searchTVAdapter.tvlist)
    searchTVAdapter.notifyDataSetChanged()
}

private fun getSearchMovies() {
    MoviesRepository.getSearchMovies(
        searchMoviesPage,
        searchKeyword,
        ::onSearchMoviesFetched,
        ::onError
    )
}

private fun attachSearchMoviesOnScrollListener() {
    searchMovies.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = searchMoviesLayoutMgr.itemCount
            val visibleItemCount = searchMoviesLayoutMgr.childCount
            val firstVisibleItem = searchMoviesLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                searchMovies.removeOnScrollListener(this)
                searchMoviesPage++
                getSearchMovies()
            }
        }
    })
}

private fun onSearchMoviesFetched(movies: List<Movie>) {
    searchMoviesAdapter.appendMovies(movies)
    attachSearchMoviesOnScrollListener()
}


private fun getPopularTV() {
    TVRepository.getSearchTV(
        searchTVPage,
        searchKeyword,
        ::onSearchTVFetched,
        ::onError
    )
}
private fun onSearchTVFetched(tvlist: List<TV>) {
    searchTVAdapter.appendTV(tvlist)
    attachSearchTVOnScrollListener()
}


private fun attachSearchTVOnScrollListener() {
    searchTV.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            val totalItemCount = searchTVLayoutMgr.itemCount
            val visibleItemCount = searchTVLayoutMgr.childCount
            val firstVisibleItem = searchTVLayoutMgr.findFirstVisibleItemPosition()

            if (firstVisibleItem + visibleItemCount >= totalItemCount / 2) {
                searchTV.removeOnScrollListener(this)
                searchTVPage++
                getPopularTV()
            }
        }
    })
}


private fun onError() {
    Toast.makeText(activity, "error error", Toast.LENGTH_SHORT).show()
}

private fun showMovieDetails(movie: Movie) {
    val intent = Intent(activity, MovieDetailsActivity::class.java)
    intent.putExtra(MainActivity.MOVIE_BACKDROP, movie.backdrop_path)
    intent.putExtra(MainActivity.MOVIE_POSTER, movie.poster_path)
    intent.putExtra(MainActivity.MOVIE_TITLE, movie.title)
    intent.putExtra(MainActivity.MOVIE_RATING, movie.rating)
    intent.putExtra(MainActivity.MOVIE_RELEASE_DATE, movie.releaseDate)
    intent.putExtra(MainActivity.MOVIE_OVERVIEW, movie.overview)
    startActivity(intent)
}

private fun showTVDetails(tv: TV) {
    val intent = Intent(activity, MovieDetailsActivity::class.java)
    intent.putExtra(MainActivity.MOVIE_BACKDROP, tv.backdrop_path)
    intent.putExtra(MainActivity.MOVIE_POSTER, tv.poster_path)
    intent.putExtra(MainActivity.MOVIE_TITLE, tv.name)
    intent.putExtra(MainActivity.MOVIE_RATING, tv.rating)
    intent.putExtra(MainActivity.MOVIE_RELEASE_DATE, tv.first_air_date)
    intent.putExtra(MainActivity.MOVIE_OVERVIEW, tv.overview)
    startActivity(intent)
}

}

NotificationsViewModel.kt

package com.example.moving.ui.notifications

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class NotificationsViewModel : ViewModel() {

private val _text = MutableLiveData<String>().apply {
    value = "This is notifications Fragment"
}
val text: LiveData<String> = _text

}

기술면접 질문

53.비동기 프로그래밍이 무엇인지, 왜 사용해야하는지 설명해주세요

비동기 프로그래밍은 주요 작업 흐름을 차단하지 않고 별도의 작업 흐름에서 태스크를 실행하는 프로그래밍 방식입니다. 주요 작업(예: UI 스레드)을 차단하지 않고 복잡하거나 시간이 오래 걸리는 작업을 처리하기 위해 사용됩니다. 이를 통해 애플리케이션의 반응성이 향상됩니다.

54.RESTful API를 사용하여 서버와 통신하는 방법에 대해 설명하세요

RESTful API와의 통신은 주로 HTTP 프로토콜을 사용하여 이루어집니다. 안드로이드에서는 Retrofit, OkHttp와 같은 라이브러리를 사용하여 API 호출을 수행합니다.

36. 암시적 인텐트와 명시적 인텐트를 설명해주세요.’

명시적 인텐트는 인텐트에 클래스 객체나 컴포넌트 이름을 지정하여 호출할 대상을 확실히 알 수 있는 경우에 사용합니다. 주로 애플리케이션 내부에서 사용합니다. 인텐트의 액션과 데이터를 지정하긴 했지만, 호출할 대상이 달라질 수 있는 경우에는 암시적 인텐트를 사용합니다.

즉 설치된 애플리케이션들에 대한 정보를 알고 있는 안드로이드 시스템이 인텐트를 이용해 요청한 정보를 처리할 수 있는 적절한 콤포넌트를 찾아본 다음 사용자에게 그 대상과 처리 결과를 보여주는 과정을 거치게 됩니다.

45. foreground service와 background service의 차이점이 무엇인가요?

백그라운드 서비스와 포그라운드 서비스의 가장 큰 차이점은, 사용자가 서비스의 존재에 대해 인지할 수 있는지 없는지에 대한 차이라고 볼 수 있다.

47. Deep Links와 App Links의 차이점을 설명해주세요

딥링크는 인텐트필터의 일종으로 사용자들이 직접적으로 안드로이드 앱내의 액티비티에 접근하는것을 허용합니다. 다른 앱에서 또는 웹브라우저에서의 링크를 클릭했을때 해당 링크의 scheme을 보고 앱을 실행하게 되며, 해당 링크를 처리하는 2개이상의 앱이 있다면 사용자에게 다이얼로그를 띄어 앱을 실행할 수 있도록 유도 합니다. 앱링크는 인증된 웹사이트 URL을 기반으로 하는 딥링크입니다. 링크 클릭시 앱이 설치되어있다면 즉시 열어서 보여주고 없다면 웹으로 이동합니다. 다이얼로그는 나타나지 않습니다.

50. BroadcastReceiver의 역할에 대해 설명해주세요.

BroadCastReceiver 의 역할은 단말기 안에서 이루어지는 수많은 일들을 대신해서 알려준다. 예를들어 배터리부족,SMS문자메시지,전화가온다거나 하는 일들을 방송알림 해준다.

51. 안드로이드 디자인패턴은 어떤것이 있는지 설명해주세요

디자인 패턴 = 검증된 소프트웨어 개발 설계 방법이다. 안드로이드 앱을 설계할 때 디자인 패턴을 적용. 이미 검증된 패턴이므로 문제가 발생할 일이 적다. 정형화된 패턴이므로 개발자 간의 의사소통이 수월해진다. 더 유연하고 좋은 코드를 사용할 수 있다. 디자인 패턴은 크게 3종류로 나뉜다. 생성 패턴, 구조 패턴, 행위 패턴

52. AAC가 무엇인가요

보완대체 의사소통 시스템(AAC)는 많은 장애인들의 의사소통 및 언어의 어려움을 보완하거나 대체하는 것을 목표로 하는 구어와는 다른 표현 방식입니다.

48. 안드로이드에서 다국어 (다양한 언어) 지원은 어떻게 구현하나요?

앱에는 특정 문화에 관련된 리소스가 포함됩니다. 예를 들어, 앱에는 현재 설정된 언어로 번역되는 문화 관련 문자열이 포함될 수 있습니다. 문화 관련 리소스는 앱의 다른 부분과 분리하는 것이 좋습니다. Android는 시스템 언어 설정에 따라 언어 및 문화 관련 리소스를 결정합니다. Android 프로젝트의 리소스 디렉터리를 사용하여 다양한 언어를 지원할 수 있습니다.

50. BroadcastReceiver의 역할에 대해 설명해주세요.

BroadCastReceiver 의 역할은 단말기 안에서 이루어지는 수많은 일들을 대신해서 알려준다. 예를들어 배터리부족,SMS문자메시지,전화가온다거나 하는 일들을 방송알림 해준다.

profile
열심히 하자

0개의 댓글