Skip to content

Commit

Permalink
상세페이지 집입
Browse files Browse the repository at this point in the history
  • Loading branch information
yeseoRyu committed Jan 13, 2025
1 parent ea48b3d commit 98dc695
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 36 deletions.
8 changes: 6 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

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

<application
android:name=".MainApplication"
Expand All @@ -20,10 +20,14 @@
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=".ui.details.DetailsActivity"
android:exported="true" />
</application>


Expand Down
32 changes: 18 additions & 14 deletions app/src/main/java/com/flab/deepsleep/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.flab.deepsleep

import PhotoAdapter
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AlertDialog
Expand All @@ -14,32 +14,25 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.flab.deepsleep.data.entity.photos.SinglePhoto
import com.flab.deepsleep.databinding.ActivityMainBinding
import com.flab.deepsleep.ui.details.DetailsActivity
import com.flab.deepsleep.ui.photo.PhotoViewModel
import com.flab.deepsleep.utils.RecyclerItemClickListener
import com.flab.deepsleep.ui.photo.onItemClick
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
class MainActivity : AppCompatActivity(), onItemClick {
private val photoViewModel: PhotoViewModel by viewModels()
private val binding: ActivityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val photoRecyclerView: RecyclerView by lazy { binding.photosRecyclerView }
private val photoAdapter: PhotoAdapter by lazy { PhotoAdapter() }
private val photoAdapter: PhotoAdapter by lazy { PhotoAdapter(this) }

private fun setRecyclerView() {
photoRecyclerView.layoutManager = GridLayoutManager(this, 2)
photoRecyclerView.adapter = photoAdapter
photoRecyclerView.addOnItemTouchListener(
RecyclerItemClickListener(this, photoRecyclerView) { _, position ->
val photo = photoAdapter.snapshot()[position]
photo?.let {
photoViewModel.insertPhoto(photo)
Toast.makeText(this, "즐겨찾기 추가", Toast.LENGTH_SHORT).show()
}
}
)
}

override fun onCreate(savedInstanceState: Bundle?) {
Expand All @@ -61,7 +54,6 @@ class MainActivity : AppCompatActivity() {
photoViewModel.searchPhotos(text.toString())
}


/* 에러 관찰 */
photoViewModel.errorMessage.observe(this, Observer { it ->
it?.let {
Expand All @@ -79,4 +71,16 @@ class MainActivity : AppCompatActivity() {
}
.show()
}

override fun onButtonClick(singlePhoto: SinglePhoto, position: Int) {
/* 즐겨찾기 추가 */
photoViewModel.insertPhoto(singlePhoto)
}

override fun onPhotoClick(singlePhoto: SinglePhoto, position: Int) {
// TODO : 상세페이지 진입
val intent = Intent(this, DetailsActivity::class.java)
intent.putExtra("singlePhoto", singlePhoto) // 객체 전달
startActivity(intent)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.flab.deepsleep.data.entity.photos

import com.google.gson.annotations.SerializedName
import java.io.Serializable

data class Exif(
@SerializedName("aperture")
Expand All @@ -17,4 +18,4 @@ data class Exif(
val model: String?,
@SerializedName("name")
val name: String?
)
) : Serializable
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ data class SinglePhoto(
val urls: Urls?,
@SerializedName("user")
val user: User?
)
) : java.io.Serializable

fun SinglePhoto.toPhoto(): Photo {
return Photo(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.flab.deepsleep.data.entity.photos

import com.google.gson.annotations.SerializedName
import java.io.Serializable

data class Urls(
@SerializedName("full")
Expand All @@ -13,4 +14,4 @@ data class Urls(
val small: String?,
@SerializedName("thumb")
val thumb: String?
)
) : Serializable
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.flab.deepsleep.data.entity.photos

import com.google.gson.annotations.SerializedName
import java.io.Serializable

data class User(
@SerializedName("bio")
Expand All @@ -23,4 +24,4 @@ data class User(
val updatedAt: String?,
@SerializedName("username")
val username: String?
)
) : Serializable
49 changes: 49 additions & 0 deletions app/src/main/java/com/flab/deepsleep/ui/details/DetailsActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.flab.deepsleep.ui.details

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import com.flab.deepsleep.R
import com.flab.deepsleep.data.entity.photos.SinglePhoto
import com.flab.deepsleep.databinding.ActivityDetailsBinding
import timber.log.Timber

class DetailsActivity : AppCompatActivity() {
val detailsBinding: ActivityDetailsBinding by lazy {
ActivityDetailsBinding.inflate(
layoutInflater
)
}

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

val singlePhoto = intent.getSerializableExtra("singlePhoto") as? SinglePhoto

singlePhoto?.let {
loadImage(it.urls?.raw)
bindPhotoDetails(it)
} ?: run {
loadImage(null)
Timber.w("singlePhoto is null")
}
}

private fun loadImage(imageUrl: String?) {
val placeholderImage = R.drawable.ic_launcher_foreground
Glide.with(detailsBinding.detailsImageView.context)
.load(imageUrl ?: placeholderImage)
.placeholder(placeholderImage)
.into(detailsBinding.detailsImageView)
}

private fun bindPhotoDetails(photo: SinglePhoto) {
detailsBinding.apply {
detailDescription.text = photo.description ?: "No description available"
detailCreateAt.text = photo.createdAt ?: "Unknown date"
detailLikes.text = photo.likes.toString()
detailUsername.text = photo.user?.username
}
}
}
16 changes: 10 additions & 6 deletions app/src/main/java/com/flab/deepsleep/ui/photo/PhotoAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import com.bumptech.glide.Glide
import com.flab.deepsleep.R
import com.flab.deepsleep.data.entity.photos.SinglePhoto
import com.flab.deepsleep.databinding.ItemPhotoBinding
import timber.log.Timber
import com.flab.deepsleep.ui.photo.onItemClick

class PhotoAdapter :
class PhotoAdapter(private val itemClick: onItemClick) :
PagingDataAdapter<SinglePhoto, PhotoAdapter.ImageViewHolder>(ARTICLE_DIFF_CALLBACK) {

inner class ImageViewHolder(
Expand All @@ -22,10 +22,6 @@ class PhotoAdapter :
fun bind(photo: SinglePhoto) {
itemView.tag = photo

/* Like Button */
btHeart.setOnClickListener {
itemView.performClick()
}
val imageUrl = photo?.urls?.raw
if (imageUrl != null) {
Glide.with(imageView.context)
Expand All @@ -47,6 +43,14 @@ class PhotoAdapter :
val photo = getItem(position)
photo?.let {
holder.bind(photo)
holder.imageView.setOnClickListener {
itemClick.onPhotoClick(photo, position)
}

/* Like Button */
holder.btHeart.setOnClickListener {
itemClick.onButtonClick(photo, position)
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/flab/deepsleep/ui/photo/onItemClick.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.flab.deepsleep.ui.photo

import com.flab.deepsleep.data.entity.photos.SinglePhoto

interface onItemClick {
fun onButtonClick(singlePhoto: SinglePhoto, position: Int)
fun onPhotoClick(singlePhoto: SinglePhoto, position: Int)
}
105 changes: 105 additions & 0 deletions app/src/main/res/layout/activity_details.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.details.DetailsActivity">

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

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<ImageView
android:id="@+id/details_image_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_constraintBottom_toTopOf="@+id/photo_config_layout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/photo_config_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/details_image_view">

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/detail_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10sp"
android:hint="@string/test"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<android.widget.ImageView
android:id="@+id/detail_bt_heart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_heart"
app:layout_constraintBottom_toBottomOf="@+id/detail_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/detail_description" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/detail_create_at"
style="@style/activityDetailsStyle"
android:hint="@string/test"
android:textSize="12sp"
app:layout_constraintBottom_toTopOf="@+id/detail_likes_icon"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/detail_description" />

<android.widget.ImageView
android:id="@+id/detail_likes_icon"
style="@style/activityDetailsStyle"
android:src="@drawable/ic_heart_fill"
app:layout_constraintBottom_toTopOf="@+id/detail_username"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/detail_create_at" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/detail_likes"
style="@style/activityDetailsStyle"
android:hint="@string/test"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="@+id/detail_likes_icon"
app:layout_constraintStart_toEndOf="@+id/detail_likes_icon"
app:layout_constraintTop_toTopOf="@+id/detail_likes_icon" />

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/detail_username"
style="@style/activityDetailsStyle"
android:background="#E6E6E6"
android:hint="@string/test"
android:padding="5sp"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/detail_likes" />

</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
Loading

0 comments on commit 98dc695

Please sign in to comment.