1+ package com.texthip.thip.ui.feed.component
2+
3+ import androidx.compose.foundation.Image
4+ import androidx.compose.foundation.background
5+ import androidx.compose.foundation.clickable
6+ import androidx.compose.foundation.layout.Arrangement
7+ import androidx.compose.foundation.layout.Box
8+ import androidx.compose.foundation.layout.Row
9+ import androidx.compose.foundation.layout.fillMaxSize
10+ import androidx.compose.foundation.layout.padding
11+ import androidx.compose.foundation.layout.size
12+ import androidx.compose.foundation.pager.HorizontalPager
13+ import androidx.compose.foundation.pager.rememberPagerState
14+ import androidx.compose.foundation.shape.CircleShape
15+ import androidx.compose.material3.Icon
16+ import androidx.compose.material3.Text
17+ import androidx.compose.runtime.Composable
18+ import androidx.compose.ui.Alignment
19+ import androidx.compose.ui.Modifier
20+ import androidx.compose.ui.draw.clip
21+ import androidx.compose.ui.graphics.Color
22+ import androidx.compose.ui.graphics.painter.Painter
23+ import androidx.compose.ui.layout.ContentScale
24+ import androidx.compose.ui.res.painterResource
25+ import androidx.compose.ui.res.stringResource
26+ import androidx.compose.ui.tooling.preview.Preview
27+ import androidx.compose.ui.unit.dp
28+ import androidx.compose.ui.zIndex
29+ import com.texthip.thip.R
30+ import com.texthip.thip.ui.theme.ThipTheme
31+ import com.texthip.thip.ui.theme.ThipTheme.colors
32+ import com.texthip.thip.ui.theme.ThipTheme.typography
33+
34+ @Composable
35+ fun ImageViewerModal (
36+ images : List <Painter >,
37+ initialIndex : Int = 0,
38+ onDismiss : () -> Unit
39+ ) {
40+ val pagerState = rememberPagerState(
41+ initialPage = initialIndex,
42+ pageCount = { images.size }
43+ )
44+
45+ Box (
46+ modifier = Modifier
47+ .fillMaxSize()
48+ .background(colors.Black )
49+ .clickable { onDismiss() }
50+ ) {
51+ // 닫기 버튼
52+ Icon (
53+ painter = painterResource(R .drawable.ic_x),
54+ contentDescription = " 닫기" ,
55+ tint = colors.White ,
56+ modifier = Modifier
57+ .align(Alignment .TopEnd )
58+ .padding(20 .dp)
59+ .size(24 .dp)
60+ .clickable { onDismiss() }
61+ .zIndex(1f )
62+ )
63+
64+ // 이미지 페이저
65+ HorizontalPager (
66+ state = pagerState,
67+ modifier = Modifier
68+ .fillMaxSize()
69+ .clickable { /* HorizontalPager 내부 클릭 시 모달 닫기 방지 */ }
70+ ) { page ->
71+ Box (
72+ modifier = Modifier .fillMaxSize(),
73+ contentAlignment = Alignment .Center
74+ ) {
75+ Image (
76+ painter = images[page],
77+ contentDescription = null ,
78+ contentScale = ContentScale .Fit , // 원본 비율 유지하면서 화면에 맞춤
79+ modifier = Modifier .fillMaxSize()
80+ )
81+ }
82+ }
83+
84+ // 페이지 인디케이터 (이미지가 2개 이상일 때만 표시)
85+ if (images.size > 1 ) {
86+ Row (
87+ modifier = Modifier
88+ .align(Alignment .BottomCenter )
89+ .padding(20 .dp),
90+ horizontalArrangement = Arrangement .spacedBy(8 .dp)
91+ ) {
92+ repeat(images.size) { index ->
93+ Box (
94+ modifier = Modifier
95+ .size(8 .dp)
96+ .clip(CircleShape )
97+ .background(
98+ if (index == pagerState.currentPage) colors.White
99+ else colors.White .copy(alpha = 0.4f )
100+ )
101+ )
102+ }
103+ }
104+ }
105+
106+ // 이미지 카운터 (예: 1/3)
107+ if (images.size > 1 ) {
108+ Text (
109+ text = stringResource(id = R .string.tag_count, images.size, 3 ),
110+ style = typography.copy_r400_s14,
111+ color = colors.White ,
112+ modifier = Modifier
113+ .align(Alignment .TopCenter )
114+ .padding(20 .dp)
115+ .background(
116+ colors.Black .copy(alpha = 0.5f ),
117+ shape = androidx.compose.foundation.shape.RoundedCornerShape (12 .dp)
118+ )
119+ .padding(horizontal = 12 .dp, vertical = 6 .dp)
120+ )
121+ }
122+ }
123+ }
124+
125+
126+ @Preview
127+ @Composable
128+ private fun ImageViewerModalSingleImagePreview () {
129+ ThipTheme {
130+ val mockImages = listOf (
131+ painterResource(R .drawable.bookcover_sample)
132+ )
133+
134+ ImageViewerModal (
135+ images = mockImages,
136+ initialIndex = 0 ,
137+ onDismiss = {}
138+ )
139+ }
140+ }
141+
142+ @Preview
143+ @Composable
144+ private fun ImageViewerModalMultipleImagesPreview () {
145+ ThipTheme {
146+ val mockImages = listOf (
147+ painterResource(R .drawable.character_art),
148+ painterResource(R .drawable.character_literature),
149+ painterResource(R .drawable.character_sociology)
150+ )
151+
152+ ImageViewerModal (
153+ images = mockImages,
154+ initialIndex = 1 ,
155+ onDismiss = { }
156+ )
157+ }
158+ }
0 commit comments