diff --git a/app/src/main/java/com/starters/yeogida/presentation/around/AroundPlaceFragment.kt b/app/src/main/java/com/starters/yeogida/presentation/around/AroundPlaceFragment.kt index b8279332..ccb8cf67 100644 --- a/app/src/main/java/com/starters/yeogida/presentation/around/AroundPlaceFragment.kt +++ b/app/src/main/java/com/starters/yeogida/presentation/around/AroundPlaceFragment.kt @@ -109,7 +109,6 @@ class AroundPlaceFragment : Fragment() { val icLikeRed = ResourcesCompat.getDrawable(resources, R.drawable.ic_like_selected_red, null) - if (abs(verticalOffset) - appBarLayout.totalScrollRange == 0) { // Collapsed if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { @@ -128,10 +127,10 @@ class AroundPlaceFragment : Fragment() { icMore?.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP) icLike?.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP) } - } else if (abs(verticalOffset) > 0) { + with(binding.layoutAroundPlaceCount) { val transition: Transition = Fade() - transition.duration = 600L + transition.duration = 1L transition.addTarget(this) TransitionManager.beginDelayedTransition( @@ -181,8 +180,6 @@ class AroundPlaceFragment : Fragment() { binding.btnAroundPlaceLike.setImageDrawable(icLike) } } - - binding.layoutCollapsingAroundPlace.addOnLayoutChangeListener { view, i, i2, i3, i4, i5, i6, i7, i8 -> } } private fun getTripId() { diff --git a/app/src/main/java/com/starters/yeogida/presentation/common/ImageBindingAdapter.kt b/app/src/main/java/com/starters/yeogida/presentation/common/ImageBindingAdapter.kt index d84665e0..e6107a32 100644 --- a/app/src/main/java/com/starters/yeogida/presentation/common/ImageBindingAdapter.kt +++ b/app/src/main/java/com/starters/yeogida/presentation/common/ImageBindingAdapter.kt @@ -4,6 +4,7 @@ import android.net.Uri import android.widget.ImageView import androidx.databinding.BindingAdapter import com.starters.yeogida.GlideApp +import com.starters.yeogida.R import java.io.File @BindingAdapter("imageUrl") @@ -11,6 +12,7 @@ fun loadImage(imageView: ImageView, imageUrl: String?) { if (!imageUrl.isNullOrEmpty()) { GlideApp.with(imageView) .load(imageUrl) + .placeholder(R.drawable.progress_animation) .into(imageView) } } @@ -21,6 +23,7 @@ fun loadCircleImage(imageView: ImageView, imageUrl: String?) { GlideApp.with(imageView) .load(imageUrl) .circleCrop() + .placeholder(R.drawable.progress_animation) .into(imageView) } } @@ -30,6 +33,7 @@ fun loadImageWithUri(imageView: ImageView, imageUri: Uri?) { imageUri?.let { GlideApp.with(imageView) .load(it) + .placeholder(R.drawable.progress_animation) .into(imageView) } } @@ -39,6 +43,7 @@ fun loadImageWithBitmap(imageView: ImageView, imageFile: File?) { imageFile?.let { GlideApp.with(imageView) .load(imageFile) + .placeholder(R.drawable.progress_animation) .into(imageView) } } \ No newline at end of file diff --git a/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceFragment.kt b/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceFragment.kt index 00f4bd4b..31f8afaf 100644 --- a/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceFragment.kt +++ b/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceFragment.kt @@ -5,7 +5,7 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.graphics.Bitmap -import android.graphics.drawable.Drawable +import android.graphics.BitmapFactory import android.net.Uri import android.os.Bundle import android.provider.Settings @@ -25,13 +25,11 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import androidx.navigation.fragment.findNavController -import com.bumptech.glide.request.target.CustomTarget -import com.bumptech.glide.request.transition.Transition import com.google.android.material.chip.Chip import com.starters.yeogida.BuildConfig -import com.starters.yeogida.GlideApp import com.starters.yeogida.R import com.starters.yeogida.YeogidaApplication +import com.starters.yeogida.data.remote.response.place.PlaceImg import com.starters.yeogida.databinding.FragmentEditPlaceBinding import com.starters.yeogida.network.YeogidaClient import com.starters.yeogida.presentation.common.CustomDialog @@ -52,6 +50,7 @@ import okhttp3.RequestBody import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody import java.io.File +import java.net.URL class EditPlaceFragment : Fragment(), PlaceEditImageClickListener { @@ -74,8 +73,6 @@ class EditPlaceFragment : Fragment(), PlaceEditImageClickListener { private val placeImageFileList = mutableListOf() // 기존 이미지 파일 - private lateinit var placeRequestImages: List - private lateinit var mContext: Context private lateinit var progressDialog: CustomProgressDialog @@ -108,7 +105,6 @@ class EditPlaceFragment : Fragment(), PlaceEditImageClickListener { progressDialog = CustomProgressDialog(mContext) setOnBackPressed() // 뒤로가기 리스너 - setPlaceImageAdapter() getPlaceDetail() onAddPhotoButtonClicked() // 장소 사진 추가 버튼 클릭 @@ -227,21 +223,15 @@ class EditPlaceFragment : Fragment(), PlaceEditImageClickListener { currChip.isChecked = true } } - - // 기존 장소 사진 목록 가져오기 - if (data.placeImgs[0].imgUrl != "https://yeogida-bucket.s3.ap-northeast-2.amazonaws.com/default_place.png") { - // 기본 이미지가 아닐 때 - placeImageFileList.clear() - - // Url -> File - for (placeImg in data.placeImgs) { - initImageFiles(placeImg.imgUrl) - } - progressDialog.dismissDialog() - } else { + } + // 기존 장소 사진 목록 가져오기 + if (data.placeImgs[0].imgUrl != "https://yeogida-bucket.s3.ap-northeast-2.amazonaws.com/default_place.png") { + // 기본 이미지가 아닐 때 + initImageFiles(data.placeImgs) + } else { + withContext(Dispatchers.Main) { progressDialog.dismissDialog() } - } } } @@ -249,26 +239,22 @@ class EditPlaceFragment : Fragment(), PlaceEditImageClickListener { } } - private fun initImageFiles(imgUrl: String) { - imgUrl?.let { - GlideApp.with(mContext) - .asBitmap() - .load(it) - .into(object : CustomTarget(1920, 1080) { - override fun onResourceReady( - bitmap: Bitmap, - transition: Transition? - ) { - bitmapToImageFile(bitmap) - binding.rvEditPlacePhoto.adapter?.notifyDataSetChanged() - } + private suspend fun initImageFiles(placeImgs: List) { + CoroutineScope(Dispatchers.IO).launch { + placeImgs.forEach { placeImg -> + val bitmap = BitmapFactory.decodeStream(URL(placeImg.imgUrl).openStream()) + bitmapToImageFile(bitmap) + } + }.join() - override fun onLoadCleared(placeholder: Drawable?) {} - }) + withContext(Dispatchers.Main) { + setPlaceImageAdapter() + binding.rvEditPlacePhoto.adapter?.notifyItemRangeInserted(0, placeImgs.size) + progressDialog.dismissDialog() } } - private fun bitmapToImageFile(bitmap: Bitmap) { + private fun bitmapToImageFile(bitmap: Bitmap?) { val uri = UriUtil.bitmapToCompressedUri(mContext, bitmap, "") uri?.let { placeImageFileList.add( diff --git a/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceImgAdapter.kt b/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceImgAdapter.kt index e72b17ae..cd9de6be 100644 --- a/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceImgAdapter.kt +++ b/app/src/main/java/com/starters/yeogida/presentation/place/EditPlaceImgAdapter.kt @@ -4,6 +4,7 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.starters.yeogida.databinding.ItemEditPlacePhotoBinding +import com.starters.yeogida.util.ImageUtil import java.io.File class EditPlaceImgAdapter( @@ -12,14 +13,28 @@ class EditPlaceImgAdapter( ) : RecyclerView.Adapter() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { - val binding = - ItemEditPlacePhotoBinding.inflate(LayoutInflater.from(parent.context), parent, false) + val inflater = LayoutInflater.from(parent.context) + val binding = ItemEditPlacePhotoBinding.inflate(inflater, parent, false) + return ImgViewHolder(binding) } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { - imageFileList[position]?.let { - if (holder is ImgViewHolder) holder.bind(it) + if (holder is ImgViewHolder) { + imageFileList[position]?.let { file -> + holder.bind(file) + + if (position <= imageFileList.size) { + val endPosition = if (position + 6 > imageFileList.size) { + imageFileList.size + } else { + position + 6 + } + imageFileList.subList(position, endPosition).map { it }.forEach { + ImageUtil.preload(holder.itemView.context, file) + } + } + } } } @@ -36,5 +51,4 @@ class EditPlaceImgAdapter( binding.executePendingBindings() } } - } \ No newline at end of file diff --git a/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailFragment.kt b/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailFragment.kt index 72e81a99..c77ad4e4 100644 --- a/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailFragment.kt +++ b/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailFragment.kt @@ -21,6 +21,7 @@ import androidx.core.widget.addTextChangedListener import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController +import androidx.viewpager2.widget.ViewPager2 import com.starters.yeogida.R import com.starters.yeogida.YeogidaApplication import com.starters.yeogida.data.remote.request.ReportRequest @@ -41,6 +42,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import kotlin.math.abs import kotlin.properties.Delegates class PlaceDetailFragment : Fragment() { @@ -95,7 +97,9 @@ class PlaceDetailFragment : Fragment() { binding.appBarLayout.addOnOffsetChangedListener { appBarLayout, verticalOffset -> val icBack = ResourcesCompat.getDrawable(resources, R.drawable.ic_back, null) val icMore = ResourcesCompat.getDrawable(resources, R.drawable.ic_more, null) - if (verticalOffset < -700) { + + if (abs(verticalOffset) - appBarLayout.totalScrollRange == 0) { + // Collapsed if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { icBack?.colorFilter = BlendModeColorFilter( ContextCompat.getColor(requireContext(), R.color.black), BlendMode.SRC_ATOP @@ -109,6 +113,7 @@ class PlaceDetailFragment : Fragment() { } } else { + //Expanded if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { icBack?.colorFilter = BlendModeColorFilter( ContextCompat.getColor(requireContext(), R.color.white), BlendMode.SRC_ATOP @@ -202,8 +207,23 @@ class PlaceDetailFragment : Fragment() { private fun setToolbar(placeImages: List) { with(binding.viewpagerPlaceToolbar) { - adapter = PlaceDetailPhotoAdapter(placeImages) + val placeDetailPhotoAdapter = PlaceDetailPhotoAdapter(placeImages) + adapter = PlaceDetailPhotoAdapter(placeImages).apply { + binding.tvAroundPlacePhotoCounter.text = "1 / $itemCount" + } binding.indicatorPlaceDetailToolbar.attachToPager(this) + + registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageScrolled( + position: Int, + positionOffset: Float, + positionOffsetPixels: Int + ) { + super.onPageScrolled(position, positionOffset, positionOffsetPixels) + binding.tvAroundPlacePhotoCounter.text = + "${position + 1} / ${placeDetailPhotoAdapter.itemCount}" + } + }) } } diff --git a/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailPhotoAdapter.kt b/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailPhotoAdapter.kt index bc503b98..63eb9e49 100644 --- a/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailPhotoAdapter.kt +++ b/app/src/main/java/com/starters/yeogida/presentation/place/PlaceDetailPhotoAdapter.kt @@ -5,6 +5,7 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.starters.yeogida.data.remote.response.place.PlaceImg import com.starters.yeogida.databinding.ItemPlaceDetailPhotoBinding +import com.starters.yeogida.util.ImageUtil class PlaceDetailPhotoAdapter( private val imageUrlList: List @@ -17,7 +18,20 @@ class PlaceDetailPhotoAdapter( } override fun onBindViewHolder(holder: PlaceViewHolder, position: Int) { - holder.bind(imageUrlList[position], position) + imageUrlList[position]?.let { url -> + holder.bind(url) + + if (position <= imageUrlList.size) { + val endPosition = if (position + 6 > imageUrlList.size) { + imageUrlList.size + } else { + position + 6 + } + imageUrlList.subList(position, endPosition).map { it }.forEach { + ImageUtil.preload(holder.itemView.context, url.imgUrl) + } + } + } } override fun getItemCount(): Int { @@ -27,10 +41,8 @@ class PlaceDetailPhotoAdapter( inner class PlaceViewHolder( private val binding: ItemPlaceDetailPhotoBinding ) : RecyclerView.ViewHolder(binding.root) { - fun bind(placeImg: PlaceImg, position: Int) { + fun bind(placeImg: PlaceImg) { binding.imgUrl = placeImg.imgUrl - binding.position = (position + 1).toString() - binding.size = imageUrlList.size.toString() binding.executePendingBindings() } } diff --git a/app/src/main/java/com/starters/yeogida/util/ImageUtil.kt b/app/src/main/java/com/starters/yeogida/util/ImageUtil.kt index dfe8d657..b7b09a88 100644 --- a/app/src/main/java/com/starters/yeogida/util/ImageUtil.kt +++ b/app/src/main/java/com/starters/yeogida/util/ImageUtil.kt @@ -6,6 +6,7 @@ import android.graphics.BitmapFactory import android.graphics.Matrix import android.media.ExifInterface import android.net.Uri +import com.starters.yeogida.GlideApp import java.io.File import java.io.FileInputStream @@ -97,5 +98,18 @@ object ImageUtil { } } - // + fun preload(context: Context, imageFile: File) { + GlideApp.with(context).load(imageFile) + .preload(150, 150) + } + + fun preload(context: Context, url: String) { + GlideApp.with(context).load(url) + .preload(150, 150) + } + + fun preload(context: Context, uri: Uri) { + GlideApp.with(context).load(uri) + .preload(150, 150) + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/loading_image.png b/app/src/main/res/drawable/loading_image.png new file mode 100644 index 00000000..8ddda5a9 Binary files /dev/null and b/app/src/main/res/drawable/loading_image.png differ diff --git a/app/src/main/res/drawable/progress_animation.xml b/app/src/main/res/drawable/progress_animation.xml new file mode 100644 index 00000000..5d25410b --- /dev/null +++ b/app/src/main/res/drawable/progress_animation.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_image.xml b/app/src/main/res/layout/activity_image.xml index 3ace3922..875454c1 100644 --- a/app/src/main/res/layout/activity_image.xml +++ b/app/src/main/res/layout/activity_image.xml @@ -20,8 +20,7 @@ android:id="@+id/iv_image" android:layout_width="0dp" android:layout_height="0dp" - app:layout_constraintDimensionRatio="1:1" - android:scaleType="centerCrop" + android:scaleType="centerInside" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/app/src/main/res/layout/fragment_place_detail.xml b/app/src/main/res/layout/fragment_place_detail.xml index 9b9375f4..b3858019 100644 --- a/app/src/main/res/layout/fragment_place_detail.xml +++ b/app/src/main/res/layout/fragment_place_detail.xml @@ -44,6 +44,25 @@ app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.3" /> + + - - - - - - - \ No newline at end of file