From 98dc695c0a0e06edfd563566184d18de7d9212a1 Mon Sep 17 00:00:00 2001 From: dolchvita Date: Mon, 13 Jan 2025 14:08:47 +0900 Subject: [PATCH] =?UTF-8?q?=EC=83=81=EC=84=B8=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20=EC=A7=91=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 8 +- .../java/com/flab/deepsleep/MainActivity.kt | 32 +++--- .../flab/deepsleep/data/entity/photos/Exif.kt | 3 +- .../data/entity/photos/SinglePhoto.kt | 2 +- .../flab/deepsleep/data/entity/photos/Urls.kt | 3 +- .../flab/deepsleep/data/entity/photos/User.kt | 3 +- .../deepsleep/ui/details/DetailsActivity.kt | 49 ++++++++ .../flab/deepsleep/ui/photo/PhotoAdapter.kt | 16 ++- .../flab/deepsleep/ui/photo/onItemClick.kt | 8 ++ app/src/main/res/layout/activity_details.xml | 105 ++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 21 ++-- app/src/main/res/values/style.xml | 11 ++ 12 files changed, 225 insertions(+), 36 deletions(-) create mode 100644 app/src/main/java/com/flab/deepsleep/ui/details/DetailsActivity.kt create mode 100644 app/src/main/java/com/flab/deepsleep/ui/photo/onItemClick.kt create mode 100644 app/src/main/res/layout/activity_details.xml create mode 100644 app/src/main/res/values/style.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4ec35e2..24ed355 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,7 @@ - + - + + + diff --git a/app/src/main/java/com/flab/deepsleep/MainActivity.kt b/app/src/main/java/com/flab/deepsleep/MainActivity.kt index c4f81e2..bdbe1df 100644 --- a/app/src/main/java/com/flab/deepsleep/MainActivity.kt +++ b/app/src/main/java/com/flab/deepsleep/MainActivity.kt @@ -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 @@ -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?) { @@ -61,7 +54,6 @@ class MainActivity : AppCompatActivity() { photoViewModel.searchPhotos(text.toString()) } - /* 에러 관찰 */ photoViewModel.errorMessage.observe(this, Observer { it -> it?.let { @@ -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) + } } \ No newline at end of file diff --git a/app/src/main/java/com/flab/deepsleep/data/entity/photos/Exif.kt b/app/src/main/java/com/flab/deepsleep/data/entity/photos/Exif.kt index c77d5ba..ab4dce0 100644 --- a/app/src/main/java/com/flab/deepsleep/data/entity/photos/Exif.kt +++ b/app/src/main/java/com/flab/deepsleep/data/entity/photos/Exif.kt @@ -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") @@ -17,4 +18,4 @@ data class Exif( val model: String?, @SerializedName("name") val name: String? -) +) : Serializable diff --git a/app/src/main/java/com/flab/deepsleep/data/entity/photos/SinglePhoto.kt b/app/src/main/java/com/flab/deepsleep/data/entity/photos/SinglePhoto.kt index 2f97903..91b4646 100644 --- a/app/src/main/java/com/flab/deepsleep/data/entity/photos/SinglePhoto.kt +++ b/app/src/main/java/com/flab/deepsleep/data/entity/photos/SinglePhoto.kt @@ -34,7 +34,7 @@ data class SinglePhoto( val urls: Urls?, @SerializedName("user") val user: User? -) +) : java.io.Serializable fun SinglePhoto.toPhoto(): Photo { return Photo( diff --git a/app/src/main/java/com/flab/deepsleep/data/entity/photos/Urls.kt b/app/src/main/java/com/flab/deepsleep/data/entity/photos/Urls.kt index a3b8b1c..8fb69f2 100644 --- a/app/src/main/java/com/flab/deepsleep/data/entity/photos/Urls.kt +++ b/app/src/main/java/com/flab/deepsleep/data/entity/photos/Urls.kt @@ -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") @@ -13,4 +14,4 @@ data class Urls( val small: String?, @SerializedName("thumb") val thumb: String? -) +) : Serializable diff --git a/app/src/main/java/com/flab/deepsleep/data/entity/photos/User.kt b/app/src/main/java/com/flab/deepsleep/data/entity/photos/User.kt index b8e93cb..d199e53 100644 --- a/app/src/main/java/com/flab/deepsleep/data/entity/photos/User.kt +++ b/app/src/main/java/com/flab/deepsleep/data/entity/photos/User.kt @@ -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") @@ -23,4 +24,4 @@ data class User( val updatedAt: String?, @SerializedName("username") val username: String? -) +) : Serializable diff --git a/app/src/main/java/com/flab/deepsleep/ui/details/DetailsActivity.kt b/app/src/main/java/com/flab/deepsleep/ui/details/DetailsActivity.kt new file mode 100644 index 0000000..2572535 --- /dev/null +++ b/app/src/main/java/com/flab/deepsleep/ui/details/DetailsActivity.kt @@ -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 + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/flab/deepsleep/ui/photo/PhotoAdapter.kt b/app/src/main/java/com/flab/deepsleep/ui/photo/PhotoAdapter.kt index 9ed9ae5..0ec5832 100644 --- a/app/src/main/java/com/flab/deepsleep/ui/photo/PhotoAdapter.kt +++ b/app/src/main/java/com/flab/deepsleep/ui/photo/PhotoAdapter.kt @@ -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(ARTICLE_DIFF_CALLBACK) { inner class ImageViewHolder( @@ -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) @@ -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) + } } } diff --git a/app/src/main/java/com/flab/deepsleep/ui/photo/onItemClick.kt b/app/src/main/java/com/flab/deepsleep/ui/photo/onItemClick.kt new file mode 100644 index 0000000..4758090 --- /dev/null +++ b/app/src/main/java/com/flab/deepsleep/ui/photo/onItemClick.kt @@ -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) +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_details.xml b/app/src/main/res/layout/activity_details.xml new file mode 100644 index 0000000..e2fb6a1 --- /dev/null +++ b/app/src/main/res/layout/activity_details.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ab5b7f2..dd05970 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -11,9 +11,10 @@ android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintTop_toTopOf="parent" + android:padding="10sp" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent"> + app:layout_constraintTop_toTopOf="parent"> + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintStart_toEndOf="@+id/editText" + app:layout_constraintTop_toTopOf="@+id/editText" /> @@ -55,8 +56,8 @@ android:id="@+id/menu_bar" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintTop_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent"/> + app:layout_constraintTop_toBottomOf="parent" /> \ No newline at end of file diff --git a/app/src/main/res/values/style.xml b/app/src/main/res/values/style.xml new file mode 100644 index 0000000..c53023a --- /dev/null +++ b/app/src/main/res/values/style.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file