-
Notifications
You must be signed in to change notification settings - Fork 28
/
CarouselActivity.kt
111 lines (89 loc) · 3.97 KB
/
CarouselActivity.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.davidferrand.pagingimagegallery.recyclerview.v1alpha2
import android.graphics.Rect
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.annotation.Px
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.davidferrand.pagingimagegallery.GridActivity
import com.davidferrand.pagingimagegallery.Image
import com.davidferrand.pagingimagegallery.R
import com.davidferrand.pagingimagegallery.databinding.ActivityCarouselRecyclerviewBinding
import kotlin.math.roundToInt
class CarouselActivity : AppCompatActivity() {
private lateinit var binding: ActivityCarouselRecyclerviewBinding
private lateinit var layoutManager: LinearLayoutManager
private lateinit var adapter: CarouselAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCarouselRecyclerviewBinding.inflate(layoutInflater)
setContentView(binding.root)
supportActionBar?.title = intent.getStringExtra(GridActivity.EXTRA_TITLE)
val images: ArrayList<Image> = intent.getParcelableArrayListExtra(GridActivity.EXTRA_IMAGES)
?: ArrayList()
layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
adapter = CarouselAdapter(images)
with(binding.recyclerView) {
layoutManager = this@CarouselActivity.layoutManager
adapter = this@CarouselActivity.adapter
val spacing = resources.getDimensionPixelSize(R.dimen.carousel_spacing)
addItemDecoration(LinearHorizontalSpacingDecoration(spacing))
}
}
}
/** Works best with a [LinearLayoutManager] in [LinearLayoutManager.HORIZONTAL] orientation */
class LinearHorizontalSpacingDecoration(@Px private val innerSpacing: Int) :
RecyclerView.ItemDecoration() {
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
super.getItemOffsets(outRect, view, parent, state)
val itemPosition = parent.getChildAdapterPosition(view)
outRect.left = if (itemPosition == 0) 0 else innerSpacing / 2
outRect.right = if (itemPosition == state.itemCount - 1) 0 else innerSpacing / 2
}
}
internal class CarouselAdapter(private val images: List<Image>) :
RecyclerView.Adapter<CarouselAdapter.VH>() {
private var hasInitParentDimensions = false
private var maxImageWidth: Int = 0
private var maxImageHeight: Int = 0
private var maxImageAspectRatio: Float = 1f
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
// At this point [parent] has been measured and has valid width & height
if (!hasInitParentDimensions) {
maxImageWidth = parent.width
maxImageHeight = parent.height
maxImageAspectRatio = maxImageWidth.toFloat() / maxImageHeight.toFloat()
hasInitParentDimensions = true
}
return VH(ImageView(parent.context))
}
override fun onBindViewHolder(vh: VH, position: Int) {
val image = images[position]
// Change aspect ratio
val imageAspectRatio = image.aspectRatio
val targetImageWidth: Int = if (imageAspectRatio < maxImageAspectRatio) {
// Tall image: height = max
(maxImageHeight * imageAspectRatio).roundToInt()
} else {
// Wide image: width = max
maxImageWidth
}
vh.imageView.layoutParams = RecyclerView.LayoutParams(
targetImageWidth,
RecyclerView.LayoutParams.MATCH_PARENT
)
// Load image
Glide.with(vh.imageView).load(image.url).into(vh.imageView)
}
override fun getItemCount(): Int = images.size
class VH(val imageView: ImageView) : RecyclerView.ViewHolder(imageView)
}