설레는 초보자를 위한 아파트 매물 상세 UI

13923 단어 iosandroidflutter


당신이 다시 여기에 있어서 반가워요
이 에피소드에서는 위의 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

    좋은 웹페이지 즐겨찾기