설레는 초보자를 위한 아파트 매물 상세 UI
당신이 다시 여기에 있어서 반가워요
이 에피소드에서는 위의 UI를 함께 살펴보겠습니다. 더 간단한 UI 디자인을 위해 다른 에피소드를 확인하는 것이 좋습니다.
모든 것이 켜져 있으므로github 코드를 다운로드하고 확인할 수 있습니다. 세로 모드만 고려했지만 다른 화면에서 완전히 반응합니다.
화면 구조를 빠르게 분석하기 전에 폴더 구조를 살펴보겠습니다. Assets 폴더(루트 폴더에 있음), screens 폴더(lib 폴더 안에 있음) 및 widgets 폴더(lib 폴더 안에 있음)의 세 가지 폴더가 있습니다. 그런 다음 앱이 실행되는 main.dart가 있습니다. 여기서 고려하고 있는 화면은 상세정보 화면입니다. 우리는 이 화면을 main.dart에서 실행하고 있습니다.
디자인과 그것이 어떻게 달성되었는지 생각해 봅시다.
앱 바부터 시작하겠습니다. 이 앱의 경우 앱 바 위젯을 사용하지 않고 맞춤형 앱 바를 만들었습니다. 화면에 그라데이션과 배경 이미지가 있음을 알 수 있습니다. 유연성을 위해 앱 바 위젯을 사용하지 않았습니다.
우리는 몸에 똑바로 가서 패딩으로 몸을 감쌌습니다.
화면에서 두 가지 유형의 스택을 볼 수 있습니다.
그래서 우리는 패딩의 직계 자식인 열로 시작했습니다(패딩이 몸 전체를 감싸고 있다고 말했던 것을 기억하십니까?).
미디어 쿼리로 화면 높이와 너비를 계산했습니다. 이것은 모든 화면에서 반응합니다.
앱의 첫 번째 구성 요소를 고려해 보겠습니다.
이 첫 번째 구성 요소에는 배경 이미지, 그라디언트 오버레이, 앱 바, 임대 버튼, 아파트 이름 및 주소, 아이콘 및 텍스트 컨테이너가 있습니다.
먼저 스택 위젯을 사용했습니다. 위에서 설명한 것처럼 스택 위젯은 자체에 오버레이되는 하위 위젯을 사용합니다.
스택 위젯의 첫 번째 자식은 배경 이미지 컨테이너이고 그 다음에는 선형 그래디언트 컨테이너입니다.
// background image
Container(
height: height / 2,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
'assets/images/details_img.png',
))),
),
// linear gradient
Container(
height: height * .6,
width: double.infinity,
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black45, Colors.transparent],
begin: Alignment.bottomCenter,
end: Alignment.topCenter),
),
),
그런 다음 헤더라고 하는 앱 바가 있습니다. 화면 상단에 배치하기 위해 배치 위젯을 사용했습니다(스택 위젯은 위치 위젯을 사용하므로 스택 위젯을 사용해야 했습니다).
// header
Positioned(
left: 0,
right: 0,
top: height * 0.06,
child: Padding(
padding: EdgeInsets.all(10),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
CircleIconButton(
height: height * 0.05,
icon: Icons.arrow_back_ios_new_rounded,
),
Row(
children: [
CircleIconButton(
icon: Icons.favorite_border,
height: height * 0.05,
),
SizedBox(
width: width * 0.07,
),
CircleIconButton(
icon: Icons.bookmark_border,
height: height * 0.05)
],
),
],
),
),
),
헤더 옆에는 임대 버튼과 아파트 이름 및 주소가 있습니다.
Positioned(
bottom: height * 0.22,
left: 0,
right: 0,
child: Center(
child: ClipRRect(
// Clip it cleanly.
borderRadius: BorderRadius.circular(20),
child: BackdropFilter(
blendMode: BlendMode.src,
filter: ImageFilter.blur(sigmaX: 2, sigmaY: 2),
child: Container(
padding: const EdgeInsets.all(8),
height: MediaQuery.of(context).size.height * 0.08,
width: MediaQuery.of(context).size.width * 0.5,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.3),
),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Lease',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 16),
),
Text(
"\$175,000.00",
style: TextStyle(
letterSpacing: 1.5,
color: Colors.white,
fontWeight: FontWeight.w900,
fontSize: 16),
)
],
),
),
),
),
),
),
// apartment address
Positioned(
bottom: height * 0.15,
left: 0,
right: 0,
child: Column(
children: const [
Text(
'WestVille Apartments',
style: TextStyle(
fontSize: 20,
letterSpacing: 2.0,
fontWeight: FontWeight.bold,
color: Colors.white),
),
Text(
'3544 NW 24th Street Road',
style: TextStyle(
fontSize: 14,
letterSpacing: 2.0,
//fontWeight: FontWeight.bold,
color: Colors.white54),
),
],
)),
마지막으로 스택에는 icontext 컨테이너가 있습니다. 화면에서 아이콘 텍스트가 일렬로 있음을 알 수 있습니다. 아래를 확인하십시오.
아이콘 텍스트 컨테이너는 화면에서 세 번 반복되므로 재사용 가능한 위젯으로 만들었습니다. 아래 코드를 확인하십시오.
import 'package:flutter/material.dart';
import 'dart:math' as math;
class IconTextContainer extends StatelessWidget {
IconTextContainer({Key? key, required this.icon, required this.text})
: super(key: key);
IconData icon;
String text;
@override
Widget build(BuildContext context) {
return Transform(
//alignment: Alignment.topRight,
transform: Matrix4.skewY(0.4)..rotateZ(-math.pi / 12),
child: Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height * 0.09,
width: MediaQuery.of(context).size.height * 0.09,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(3),
color: Colors.black87,
border: Border.all(color: Colors.grey)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: Colors.white,
),
Container(
// padding: const EdgeInsets.all(8.0),
child: Text(
text,
style: const TextStyle(
color: Colors.white,
),
),
),
],
),
),
);
}
}
다시 position 위젯을 사용하여 스택에 배치한 다음 Row 위젯을 사용하여 수평으로 정렬합니다. 행 위젯은 하위 위젯을 가져와 가로로 정렬합니다.
// icon and text containers
Positioned(
bottom: height * 0.05,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconTextContainer(text: '3', icon: Icons.hotel_sharp),
IconTextContainer(
text: '4', icon: Icons.shopping_cart_sharp),
IconTextContainer(text: '2500', icon: Icons.window),
],
),
)
아직 Column 위젯에 있다는 것을 기억하십니까? 위의 스택 위젯은 첫 번째 자식입니다.
열의 다른 자식을 보자
첫 번째 컨테이너에는 에이전트 이미지, 세부 정보 및 아이콘이 있습니다.
컨테이너는 행 위젯을 래핑합니다. 행 위젯은 다른 행 위젯과 아이콘 위젯을 자식으로 포함합니다.
// agent image, details and icon
Container(
// padding: EdgeInsets.all(10),
height: height * 0.09,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: const Color(0xFF2B2B2B),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// image and text row widget
Row(
children: [
// image
Image.asset('assets/images/shelly_img.png'),
// column of text widget
Padding(
padding: const EdgeInsets.all(4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
'Shelly Butcher',
style: TextStyle(color: Colors.white),
),
Text(
'Agent',
style: TextStyle(color: Colors.grey),
),
],
),
)
],
),
// icon
const Icon(
Icons.arrow_forward_ios_outlined,
color: Colors.grey,
),
]),
),
그런 다음 설명 및 세부 정보에 대한 또 다른 열이 있습니다.
이들은 텍스트 위젯입니다
// description and details
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.symmetric(
vertical: MediaQuery.of(context).size.height * 0.01),
child: Text(
'Description',
style: TextStyle(color: Colors.white, fontSize: 18),
),
),
const Text(
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Egestas ut consectetur integer aliquam integer scelerisque. Nibh malesuada lectus mattis aliquet eget elementum dictum non. Eu, viverra gravida leo vitae non eu laoreet. Egestas lorem amet, diam diam neque vestibulum semper. Dictum fusce tellus eu et viverra ac augue aliquam fusce. Pharetra laoreet arcu vitae interdum id',
style: TextStyle(color: Colors.white70),
),
],
),
마지막으로 적용 버튼입니다. 이 버튼은 텍스트 위젯을 하위로 포함하는 컨테이너입니다.
Container(
alignment: Alignment.center,
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.06,
margin:
EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.01),
// padding: EdgeInsets.only(top: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.topRight,
stops: const [1, 1],
colors: [Colors.red.shade700, Colors.transparent])),
child: const Text(
'Apply',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18),
),
),
모든 것이 명확하지 않을 수 있다는 것을 알고 있습니다. 이해합니다. 당신은 언제나 당신의 질문을 버릴 수 있습니다. 도와드릴 수 있어 기쁩니다. 더 명확하게 보려면 아래 링크의 코드를 살펴보십시오.
Github link
Reference
이 문제에 관하여(설레는 초보자를 위한 아파트 매물 상세 UI), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/elvis_igiebor/apartment-listing-detail-ui-for-beginners-with-flutter-98h텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)