ํ๋ก์ ํธ ๋ง๋ฐ์ง๋ก ์ ์ด๋ค๋ฉด์, ํ์ ๊ธฐ๋ฅ ๊ตฌํ์ ๋๋๊ฐ๊ณ ๋ค๋ฅธ ๊ฒ๋ค์ ์์ฌ์ด ์๊ธฐ๊ธฐ ์์ํ๋ค.
์ค๋์ ํฌ์คํ ์ ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ ์ ์ํ ๊ณ ๋ฏผ์์ ์์๋์๋ค.
์ด๋ฒ์ ์ฐ๋ฆฌ ํ๋ก์ ํธ์ ์ฃผ์ ๋ '์ฌ์ฉ์ ๋ง์ถค ๋ฌ๋ ์ฝ์ค ์ถ์ฒ'์ด๋ค.
๊ฒฝ์ฌ๋ / ์ฌ์ฉ์์ ์ทจํฅ ๋ฑ์ ๋ถ์ํด ์ฌ์ฉ์์๊ฒ ๊ฐ์ฅ ์ ๋ง๋ ๋ฌ๋ ์ฝ์ค๋ค์ ์ถ์ฒํด ์ฃผ๋ ์๋น์ค๋ฅผ ๊ฐ๋ฐํ๊ณ ์๋ค.
๐จ ์์ ํ ๋ถ๋ถ

์ฐ๋ฆฌ ์๋น์ค์ ๋ฉ์ธ ํ๋ฉด์ด๋ค. ์์ฒญ ์ด์ฌํ ๋ง๋ค์๋๋ฐ ๋ง๋ค๊ณ ๋ณด๋ ์กฐ๊ธ ๋ถ์กฑํด๋ณด์ฌ์ ์ถ๊ฐ ๊ธฐ๋ฅ์ ๋ฃ์ด๋ณด๊ธฐ๋ก ํ๋ค.
๊ธฐ์กด์ ์๋น์ค๋ ์ด๋ฏธ์ง ๋ด์ ์ฝ์ค๋ฅผ ํด๋ฆญํ๋ฉด ์์ธ ์กฐํ ํ์ด์ง๋ก ์ด๋ํด ์ฝ์ค๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ฐฉ์์ด๋ค.
์ฝ์ค ์ถ์ฒ์ด๋ผ๋ ์๋น์ค ํน์ฑ ์ ์ฝ์ค๊ฐ ๊ฝค ์ค์ํ๋ฐ, ์์ธ ์กฐํ๋ก ๋ค์ด๊ฐ์ ๋งค๋ฒ ์ฝ์ค๋ฅผ ํ์ธํ๊ณ ๋ค์ ๋์์ ๋ค๋ฅธ ์ฝ์ค๋ฅผ ํ์ธํด์ผ ํ๋ค๋ ๊ฒ์ ๊ฝค ๋ถํธํ ๊ฒ์ด๋ผ๊ณ ์๊ฐ์ด ๋ค์๋ค.
๊ทธ๋์, ์๋น์ค ์ฌ์ฉ์์ ์ฝ์ค ํ์ธ์ ๋ ๊ฐํธํ๊ฒ ๋ง๋ค์ด์ฃผ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ์ฐพ๋ค๊ฐ long press ํจ๊ณผ๋ฅผ ํตํด ๋๋ต์ ์ธ ์ฝ์ค ์ ๋ณด๋ฅผ ํ์ธํ๊ฒ ํ๋ ๋ฐฉ๋ฒ์ ์ ํํ๊ฒ ๋์๋ค.
๐จ ๊ธธ๊ฒ ๋๋ฅด๊ธฐ ํจ๊ณผ๋ฅผ ํตํด overlay ๋์ฐ๊ธฐ
์ด๋ฅผ ์ํด ๊ตฌํํ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค
import 'package:flutter/material.dart';
import 'package:frontend/models/course.dart';
import 'package:frontend/widgets/course/level_badge.dart';
import 'package:get/get.dart';
class CourseCard extends StatelessWidget {
final Course course;
CourseCard({required this.course});
OverlayEntry? _overlayEntry;
void _showOverlay(BuildContext context, Offset position) {
_overlayEntry = OverlayEntry(
builder: (context) => Positioned(
// position ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ์ฉํด ํ์
์์น ์ค์
top: position.dy,
left: position.dx,
child: Material(
color: Colors.transparent,
child: Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.black26,
blurRadius: 10,
offset: Offset(0, 4),
),
],
),
width: 200,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Course Name: ${course.name}'),
Text('Length: ${(course.courseLength * 10).round() / 10} km'),
Text('Level: ${course.level}'),
if (course.courseType == 'user')
Text('By: ${course.memberNickname}'),
Text('Participants: ${course.count}๋ช
์ฐธ์ฌ ์ค'),
],
),
),
),
),
);
Overlay.of(context)?.insert(_overlayEntry!);
}
void _removeOverlay() {
_overlayEntry?.remove();
_overlayEntry = null;
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onLongPressStart: (LongPressStartDetails details) {
// ๊ธธ๊ฒ ๋๋ฅด๊ธฐ ์์ํ ๋ ํด๋ฆญ ์์น์ ์ค๋ฒ๋ ์ด๋ก ํ์
๋์ฐ๊ธฐ
_showOverlay(context, details.globalPosition);
},
onLongPressEnd: (_) {
// ๊ธธ๊ฒ ๋๋ฅด๊ธฐ๋ฅผ ๋๋ผ ๋ ํ์
๋ซ๊ธฐ
_removeOverlay();
},
child: Card(// detail)
);
}
}

๋๋ต์ ์ผ๋ก ์ฝ์ค ์ด๋ฆ, ๊ธธ์ด, ๋์ด๋, ์ฐธ์ฌ ์ค์ธ ์ฌ๋ ์๋ฅผ ํฌํจํด๋ณด์๋ค.
ํด๋ฆญํ ์์น์์ overlay๊ฐ ๋จ๋๋ก ํ๊ธฐ ์ํด onLongPressStart์์ LongPressStartDetails๋ฅผ ๋ฐ์๋ค
<์์์ฝ๋>
onLongPressStart: (LongPressStartDetails details) {
// ๊ธธ๊ฒ ๋๋ฅด๊ธฐ ์์ํ ๋ ํด๋ฆญ ์์น์ ์ค๋ฒ๋ ์ด๋ก ํ์
๋์ฐ๊ธฐ
_showOverlay(context, details.globalPosition);
},
์ด์ overlay๋ฅผ ๊พธ๋ฏธ๊ณ , ์ฝ์ค ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋๋ก ์์ ํด์ผ ํ๋ค.
์ฝ์ค ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ค๋ฅธ ํํธ์ ์ฝ์ค ๋ฑ๋ก์ด ์๋ฃ๋์ด์ผ ํ๊ธฐ ๋๋ฌธ์, ์ง๊ธ์ ์์๋ก ๊ฒ์์ ํ๋ฉด์ผ๋ก ์ฒ๋ฆฌํ์๋ค.

ํ์ํ ์ ๋ณด์ธ ์ ๋ชฉ๊ณผ ๋งต ๋ถ๋ถ์ ์์๋ก Container ์ฒ๋ฆฌ ํด์ ๋์ฐ๊ธฐ๊น์ง ํ๋๋ฐ ํด๋ฆญ ์์น๋ก ๋งต์ ๋์ฐ๋ค ๋ณด๋ ํด๋ฆญ ํ๋ ์์น์ ๋ฐ๋ผ ๋งต์ด ์งค๋ฆฌ๊ฒ ๋๋ ๊ฒฝ์ฐ๊ฐ ์์๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก ์๋์ ๊ฐ์ด ์กฐ๊ฑด๋ฌธ์ ์ค์ ํด์ฃผ์ด pop up์ด ๋ฐ๊นฅ์ผ๋ก ๋๊ฐ์ง ์๋๋ก ํ๋ค
// ํ์
ํฌ๊ธฐ ์ค์
double popupWidth = screenWidth * 1 / 2;
double popupHeight = 210; // ์์๋ก ์ค์ ํ ๋์ด
// ํ๋ฉด ๊ฒฝ๊ณ๋ฅผ ๋์ง ์๋๋ก ์กฐ์
double leftPosition = position.dx;
double topPosition = position.dy;
// ์ค๋ฅธ์ชฝ์ผ๋ก ๋์ง ์๋๋ก ์ฒ๋ฆฌ
if (leftPosition + popupWidth > screenWidth) {
leftPosition = screenWidth - popupWidth - 20; // ์ค๋ฅธ์ชฝ ๊ฒฝ๊ณ์์ 20px ์ฌ์ ๋ฅผ ๋
}
// ์๋์ชฝ์ผ๋ก ๋์ง ์๋๋ก ์ฒ๋ฆฌ
if (topPosition + popupHeight > screenHeight) {
topPosition = screenHeight - popupHeight - 40; // ์๋์ชฝ ๊ฒฝ๊ณ์์ 40px ์ฌ์ ๋ฅผ ๋
}

์ด๋ ๊ฒ ์ต์ข ์์ ํ๋ค !!

'๐ web' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [github] github.io๋ก ๊ฐ๋ฐ์ ํฌํธํด๋ฆฌ์ค ์์ฑํ๊ธฐ ๐๐ป (1) | 2024.09.10 |
|---|---|
| ๊ณ์ฐ๊ธฐ ์น ํ๋ก๊ทธ๋จ ๊ตฌํ - request line (0) | 2023.09.18 |
| web | ์น๊ฐ๋ฐ ์ผ์ง - ์์ํ๊ธฐ, ํ ์คํธ ์ฝ๋ (0) | 2023.08.08 |