소개팅 앱 1. Card Stack View 구성하기

변현섭·2023년 8월 22일
0

이번 포스팅부터는 방식을 조금 바꿔서, 하나의 완성도 있는 어플리케이션을 만들어보도록 하겠습니다. 저희가 만들어 볼 앱은 소개팅 어플리케이션으로, 소개팅 앱을 만들기 위한 여러가지 기능을 추가해나갈 예정입니다. 그중에서 이번 포스팅에서 다뤄볼 내용은 아래와 같습니다.

  • 프로필 사진을 CardStackView로 나타내기
  • 프로필 사진을 좌우로 swipe하여 좋아요와 싫어요 나타내기
  • 스플래시 화면 구성하기

소개팅 앱의 전체 코드는 아래의 깃허브 링크에서 확인하실 수 있습니다.
>> 깃허브 링크

1. Card Stack View 구성하기

① dating app이라는 이름으로 프로젝트를 생성한다.

② 먼저 drawable 디렉토리에 좋아요, 싫어요 표시를 위한 아이콘, 기본 프로필 이미지, 스플래시 화면에 사용할 이미지를 추가한다.

③ Card Stack View를 사용하기 위해 app 수준의 build.gradle 파일의 dependencies에 아래의 의존성을 추가한다.

implementation("com.yuyakaido.android:card-stack-view:2.3.4")

④ settings.gradle 파일의 dependencyResolutionManagement에 jcenter()를 추가해야 CardStackView를 사용할 수 있다.

dependencyResolutionManagement {
  repositories {
      ...
      jcenter()
  }
}

⑤ activity_main.xml 파일에 기존 TextView 태그는 지우고, CardStackView 태그를 추가한다.

<com.yuyakaido.android.cardstackview.CardStackView
    android:id="@+id/cardStackView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

⑥ layout 디렉토리 하위로 item_card라는 이름의 Resource 파일을 추가한다.

⑦ LinearLayout을 CardView로 변경하고, 아래의 코드를 추가한다.

<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="20dp">

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

        <ImageView
            android:id="@+id/profileImage"
            android:src="@drawable/profile"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:scaleType="fitXY"/>

        <TextView
            android:layout_marginVertical="20dp"
            android:layout_marginHorizontal="10dp"
            android:text="이름"
            android:textSize="30sp"
            android:textColor="#000000"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_marginVertical="20dp"
            android:layout_marginHorizontal="10dp"
            android:text="나이"
            android:textSize="30sp"
            android:textColor="#000000"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <TextView
            android:layout_marginVertical="20dp"
            android:layout_marginHorizontal="10dp"
            android:text="지역"
            android:textSize="30sp"
            android:textColor="#000000"
            android:textStyle="bold"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</androidx.cardview.widget.CardView>

⑧ CardStackAdapter라는 이름의 Kotlin 클래스를 추가한다.

class CardStackAdapter(val context : Context, val items: MutableList<String>) : RecyclerView.Adapter<CardStackAdapter.ViewHolder>() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CardStackAdapter.ViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_card, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: CardStackAdapter.ViewHolder, position: Int) {
        holder.bindItems(items[position])
    }

    override fun getItemCount(): Int {
        return items.size
    }

    inner class ViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView) {
        fun bindItems(item : String) {

        }
    }
}

⑨ MainActivity에 CardStackView를 적용하자.

lateinit var cardStackAdapter : CardStackAdapter
lateinit var manager : CardStackLayoutManager
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val cardStackView = findViewById<CardStackView>(R.id.cardStackView)
    manager = CardStackLayoutManager(baseContext, object : CardStackListener {
        override fun onCardDragging(direction: Direction?, ratio: Float) {
        }
        override fun onCardSwiped(direction: Direction?) {
        }
        override fun onCardRewound() {
        }
        override fun onCardCanceled() {
        }
        override fun onCardAppeared(view: View?, position: Int) {
        }
        override fun onCardDisappeared(view: View?, position: Int) {
        }
    })
    val initList = mutableListOf<String>()
    initList.add("a") // 테스트 용 더미데이터
    initList.add("b") // 테스트 용 더미데이터
    cardStackAdapter = CardStackAdapter(baseContext, initList)
    cardStackView.layoutManager = manager
    cardStackView.adapter = cardStackAdapter
}

코드를 실행시킨 후, CardView 이미지를 swipe해보자. 이미지가 CardStackView의 형태로 잘 쌓여있음을 확인할 수 있다.

2. Left/Right Overlay 구현하기

프로필 사진을 왼쪽으로 swipe하면 싫어요 아이콘을, 오른쪽으로 swipe하면 좋아요 아이콘을 표기해보기로 하자.

① 계속해서 item_card.xml 파일의 LinearLayout 컨테이너 아래에 FrameLayout 컨테이너를 추가한다.

  • 반드시 LinearLayout 태그보다 아래에 작성해야 좋아요와 싫어요 아이콘이 정상적으로 화면에 나타난다.
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/left_overlay"
        android:src="@drawable/bad"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"/>
</FrameLayout>
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/right_overlay"
        android:src="@drawable/good"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"/>
</FrameLayout>

② 다시 코드를 실행시켜보자. 이미지를 좌측으로 swipe하면 싫어요 아이콘이, 우측으로 swipe하면 좋아요 아이콘이 나와야 한다.

3. 상태 Bar 색깔 변경하기

애플리케이션 상태 바의 색깔이 현재는 보라색으로 되어 있다. 이 상태 바의 색깔을 메인 화면의 색깔과 동일한 색깔을 맞춰주기로 하자.

① 먼저 메인화면의 색깔을 분홍색으로 변경해보자. activity_main.xml 파일의 ConstraintLayout 컨테이너의 아래의 속성을 추가한다.

android:background="#ff9999"

② values > themes > themes.xml과 themes.xml(night) 파일의 style 컨테이너에 아래와 같이 item 컨테이너를 추가한다.

  • windowLightStatusBar의 content에는 배경색이 밝으면 true, 어두우면 false를 입력하면 된다.
  • true인 경우, 상태 표시줄의 아이콘과 텍스트를 어두운 색으로 표시하고, false인 경우, 상태 표시줄의 아이콘과 텍스트를 밝은 색으로 표시한다.
<style name="Base.Theme.DatingApp" 
	<item name="android:windowLightStatusBar">true</item>
	<item name="android:statusBarColor">#ff9999</item>
</style>

③ 코드를 실행시켜보면 상태 바와 메인화면의 색깔이 동일하게 맞춰진 것을 확인할 수 있다.

④ 16진수 색상 값을 사용하는 대신 색상을 등록할 수도 있다. values > colors.xml 파일의 resources 컨테이너 안에 아래의 내용을 추가하자.

<resources>
    <color name="pink">#FF9999</color>
</resources>

⑤ 이제 #FF9999 대신 @color/pink를 사용하여 동일한 결과를 얻을 수 있다.

<style name="Base.Theme.DatingApp" parent="Theme.Material3.DayNight.NoActionBar">
    <item name="android:windowLightStatusBar">true</item>
    <item name="android:statusBarColor">@color/pink</item>
</style>

4. 스플래시 화면 구성하기

① default 패키지 하위로 SplashActivity와 IntroActivity를 추가한다.

  • IntroActivity는 회원가입을 위한 Activity이다.

② SplashActivity의 onCreate 메서드 안에 아래의 내용을 입력한다.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_splash)
    
    Handler().postDelayed({
        startActivity(Intent(this, IntroActivity::class.java))
        finish()
    }, 3000)
}

③ Splash 화면이 가장 먼저 나타날 수 있도록, AndroidManifest.xml 파일의 activity 컨테이너를 수정한다.

<activity
    android:name=".IntroActivity"
    android:exported="false" />
<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=".MainActivity"
    android:exported="true">
</activity>

④ 미리 준비한 스플래시 화면의 이미지를 넣어주자. activity_splash.xml 파일의 ConstraintLayout 컨테이너의 속성에 아래의 내용을 추가한다.

android:background="@drawable/date"

⑤ TextView도 추가한다.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="120dp"
    android:text="♡ 소중한 인연으로\n장식할 우리의 내일 ♡"
    android:textColor="@color/white"
    android:textSize="35sp"
    android:textStyle="bold"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

⑥ 이번에는 activity_intro.xml 파일에서 배경을 지정해주자. 여기서는 스플래시 화면과 동일한 배경을 사용하겠다.

android:background="@drawable/date"

⑦ ConstraintLayout 컨테이너 안에 LinearLayout 컨테이너를 추가한다.

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    android:orientation="vertical"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.919"
    tools:layout_editor_absoluteX="9dp">
    
    <Button
    	android:id="@+id/join"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:background="@color/pink"
        android:textColor="@color/white"
        android:textStyle="bold"
        android:textSize="20sp"
        android:text="회원 가입" />
        
    <Button
    	android:id="@+id/login"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="15dp"
        android:background="@color/pink"
        android:textColor="@color/white"
        android:textStyle="bold"
        android:textSize="20sp"
        android:text="로그인" />
        
</LinearLayout>

※ Button의 배경색이 적용되지 않는 경우
values > themes > themes.xml 파일의 style 컨테이너 속성 값을 아래와 같이 변경해야 한다.

<style name="Base.Theme.DatingApp" parent="Theme.AppCompat.Light">

※ 타이틀 바가 자동 생성되는 경우
themes.xml 파일의 style 컨테이너 안에 아래와 같이 item 컨테이너를 추가해야 한다.

<item name="windowNoTitle">true</item>
profile
Java Spring, Android Kotlin, Node.js, ML/DL 개발을 공부하는 인하대학교 정보통신공학과 학생입니다.

0개의 댓글