From 32eee2bfe2b0642d29cb8f66736c138dc65abbed Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Tue, 9 Sep 2025 23:11:59 +0900 Subject: [PATCH] feat(zipcode): compact column widths for popup; ensure no horizontal scroll within dialog - ZipcodeTable: dynamic widths; shrink columns when target width < standard - Use computed widths for header and rows; actions width fixed - Works with tableMaxWidthFraction from ZipcodeSearchScreen], --- .../zipcode/components/zipcode_table.dart | 85 ++++++++++++++----- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/lib/screens/zipcode/components/zipcode_table.dart b/lib/screens/zipcode/components/zipcode_table.dart index 8365d23..9b682d4 100644 --- a/lib/screens/zipcode/components/zipcode_table.dart +++ b/lib/screens/zipcode/components/zipcode_table.dart @@ -35,15 +35,51 @@ class ZipcodeTable extends StatelessWidget { child: LayoutBuilder( builder: (context, constraints) { // 고정폭 + 마지막 filler - const double minW = 160 + 180 + 180 + 320 + 140 + 24; + // Standard widths + const double zipStd = 160.0; + const double sidoStd = 180.0; + const double guStd = 180.0; + const double etcStd = 320.0; + const double actionsStd = 140.0; + const double fudge = 24.0; // internal paddings/margins + final double viewportW = constraints.maxWidth.isFinite ? constraints.maxWidth : MediaQuery.sizeOf(context).width; - final double cappedW = maxWidthCap != null + final double targetW = maxWidthCap != null ? math.min(viewportW, maxWidthCap!) : viewportW; - final double tableW = cappedW >= minW ? cappedW : minW; - const double etcW = 320.0; + + final double stdMin = zipStd + sidoStd + guStd + etcStd + actionsStd + fudge; + final bool compact = targetW < stdMin; + + // Effective widths + double zipW; + double sidoW; + double guW; + double etcW; + double actionsW; + bool includeFiller; + + if (!compact) { + zipW = zipStd; + sidoW = sidoStd; + guW = guStd; + etcW = etcStd; + actionsW = actionsStd; + includeFiller = true; // use remaining width as filler column + } else { + // Compact widths to fit inside targetW without horizontal scroll + zipW = 110.0; + sidoW = 120.0; + guW = 120.0; + actionsW = 110.0; + final double remaining = targetW - fudge - (zipW + sidoW + guW + actionsW); + etcW = math.max(180.0, remaining); + includeFiller = false; // no filler in compact mode + } + + final double tableW = targetW; return SingleChildScrollView( scrollDirection: Axis.horizontal, @@ -53,17 +89,19 @@ class ZipcodeTable extends StatelessWidget { columnSpanExtent: (index) { switch (index) { case 0: - return const FixedTableSpanExtent(160); // 우편번호 + return FixedTableSpanExtent(zipW); // 우편번호 case 1: - return const FixedTableSpanExtent(180); // 시도 + return FixedTableSpanExtent(sidoW); // 시도 case 2: - return const FixedTableSpanExtent(180); // 구/군 + return FixedTableSpanExtent(guW); // 구/군 case 3: - return const FixedTableSpanExtent(etcW); // 상세주소 + return FixedTableSpanExtent(etcW); // 상세주소 case 4: - return const FixedTableSpanExtent(140); // 작업 + return FixedTableSpanExtent(actionsW); // 작업 case 5: - return const RemainingTableSpanExtent(); // filler + return includeFiller + ? const RemainingTableSpanExtent() + : const FixedTableSpanExtent(0); default: return const FixedTableSpanExtent(100); } @@ -73,15 +111,15 @@ class ZipcodeTable extends StatelessWidget { const ShadTableCell.header(child: Text('시도')), const ShadTableCell.header(child: Text('구/군')), ShadTableCell.header(child: SizedBox(width: etcW, child: const Text('상세주소'))), - const ShadTableCell.header(child: Text('작업')), - const ShadTableCell.header(child: SizedBox.shrink()), + ShadTableCell.header(child: SizedBox(width: actionsW, child: const Text('작업'))), + if (includeFiller) const ShadTableCell.header(child: SizedBox.shrink()), ], children: zipcodes.map((zipcode) { return [ // 우편번호 (오버플로우 방지) ShadTableCell( child: SizedBox( - width: 160, + width: zipW, child: FittedBox( alignment: Alignment.centerLeft, fit: BoxFit.scaleDown, @@ -138,18 +176,21 @@ class ZipcodeTable extends StatelessWidget { ), // 작업 ShadTableCell( - child: ShadButton( - onPressed: () => onSelect(zipcode), - size: ShadButtonSize.sm, - child: const Text('선택', style: TextStyle(fontSize: 11)), + child: SizedBox( + width: actionsW, + child: ShadButton( + onPressed: () => onSelect(zipcode), + size: ShadButtonSize.sm, + child: const Text('선택', style: TextStyle(fontSize: 11)), + ), ), ), - const ShadTableCell(child: SizedBox.shrink()), - ]; - }).toList(), - ), + if (includeFiller) const ShadTableCell(child: SizedBox.shrink()), + ]; + }).toList(), ), - ); + ), + ); }, ), ),