如何在 Flutter 中创建此 Ui

问题描述 投票:0回答:3

你好,我是 flutter 新手,我想实现这个特定的 UI。从用户界面我可以看到 -

  1. 顶部有一个自定义搜索栏,我不知道它是否是应用程序栏。
  2. 搜索栏下方有一个 SizedBox 或类似的东西。
  3. 它有一个listview.builder(我已经知道如何实现这一点)

所以想问一下如何实现app的前两个内容

这是应用程序的屏幕截图

flutter dart user-interface
3个回答
0
投票

你可以以此为例。类似的设计。

import 'package:flutter/material.dart';

class FirstScreen extends StatefulWidget {
  const FirstScreen({Key? key}) : super(key: key);

  @override
  State<FirstScreen> createState() => _FirstScreenState();
}

class _FirstScreenState extends State<FirstScreen> {
  @override
  Widget build(BuildContext context) {
    return  SingleChildScrollView(
        child: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Column(
            children: [
              const SizedBox(
                height: 30,
              ),
              buildTitleText(context),
              const SizedBox(
                height: 30,
              ),
              buildSearchBar(context),
              const SizedBox(
                height: 30,
              ),
              buildSecondTitle(context),
              const SizedBox(
                height: 10,
              ),
              buildContent(context)
            ],
          ),
        ),

    );
  }

  SizedBox buildSecondTitle(BuildContext context) {
    return SizedBox(
      width: MediaQuery.of(context).size.width - 65,
      child: Row(
        children: const [
          Text(
            'Favorite Places',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          TextButton(
              onPressed: null,
              child: Text(
                'See All',
                style: TextStyle(color: Colors.blue, fontSize: 18),
              )),
        ],
      ),
    );
  }

  Container buildTitleText(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width - 50,
      child: const Text(
        "What you would like to find?",
        style: TextStyle(
          fontWeight: FontWeight.w600,
          fontSize: 30,
        ),
      ),
    );
  }

  SingleChildScrollView buildContent(BuildContext context) {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Row(
        children: [
          const SizedBox(
            width: 25,
          ),
          buildCityCard(context,
              photoName: 'img_istanbul.jpg',
              cityName: 'İstanbul',
              cityActivity: '98 Aktivite',
              cityScore: '4.8'),
          const SizedBox(
            width: 25,
          ),
          buildCityCard(context,
              photoName: 'img_mugla.jpg',
              cityName: 'Muğla',
              cityActivity: '102 Aktivite',
              cityScore: '4.7'),
          const SizedBox(
            width: 25,
          ),
          buildCityCard(context,
              photoName: 'img_antalya.jpg',
              cityName: 'Antalya',
              cityActivity: '98 Aktivite',
              cityScore: '4.5'),
          const SizedBox(
            width: 25,
          ),
        ],
      ),
    );
  }

  Container buildSearchBar(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width - 65,
      child: TextField(
        decoration: InputDecoration(
          prefixIcon: const Icon(
            Icons.search,
          ),
          border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(360),
              borderSide: const BorderSide(
                color: Colors.blueAccent,
                width: 2,
              )),
          labelText: "Locaiton",
        ),
      ),
    );
  }

  Container buildCityCard(BuildContext context,
      {required String photoName,
      required String cityName,
      required String cityActivity,
      required String cityScore}) {
    return Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(30),
        color: Colors.white,
      ),
      height: MediaQuery.of(context).size.height / 2.5,
      width: MediaQuery.of(context).size.height / 3.7,
      child: Column(
        children: [
          Expanded(
            flex: 5,
            child: Container(
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(30),
                color: Colors.blue,
                image: DecorationImage(
                  image: AssetImage("assets/images/${photoName}"),
                  fit: BoxFit.fill,
                ),
              ),
            ),
          ),
          const SizedBox(
            height: 10,
          ),
          Expanded(
            flex: 1,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                const SizedBox(
                  width: 20,
                ),
                Icon(Icons.location_on, color: Colors.blue),
                Text(
                  "${cityName}",
                  style: const TextStyle(
                      fontSize: 16, fontWeight: FontWeight.bold),
                ),
              ],
            ),
          ),
          Expanded(
            flex: 1,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                const SizedBox(
                  width: 20,
                ),
                const Icon(
                  Icons.star,
                  color: Colors.yellow,
                ),
                Text(
                  "${cityScore}",
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const Padding(
                  padding: EdgeInsets.fromLTRB(95, 0, 0, 0),
                  child: Icon(Icons.arrow_forward_ios),
                ),
              ],
            ),
          ),
          const SizedBox(
            height: 10,
          ),
        ],
      ),
    );
  }
}

这就是家。如果你想使用标签栏。

import 'package:circle_bottom_navigation_bar/circle_bottom_navigation_bar.dart';
import 'package:circle_bottom_navigation_bar/widgets/tab_data.dart';
import 'package:flutter/material.dart';
import 'package:inovatif/third_screen.dart';

import 'first_screen.dart';
import 'second_screen.dart';

class HomeView extends StatefulWidget {
  HomeView({Key? key}) : super(key: key);
  static String routeName = 'home';

  @override
  State<HomeView> createState() => _HomeViewState();
}

class _HomeViewState extends State<HomeView> {
  int currentPage = 0;

  final List<Widget> _pages = [
    FirstScreen(),
    SecondScreen(),
    ThirdScreen(),
  ];

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final viewPadding = MediaQuery.of(context).viewPadding;
    double barHeight;
    double barHeightWithNotch = 67;
    double arcHeightWithNotch = 67;

    if (size.height > 700) {
      barHeight = 70;
    } else {
      barHeight = size.height * 0.1;
    }

    if (viewPadding.bottom > 0) {
      barHeightWithNotch = (size.height * 0.07) + viewPadding.bottom;
      arcHeightWithNotch = (size.height * 0.075) + viewPadding.bottom;
    }
    return Scaffold(
      appBar: AppBar(backgroundColor: Colors.transparent, elevation: 0),
      body: _pages[currentPage],
      bottomNavigationBar: buildCircleBottomNavigationBar(
          viewPadding, barHeightWithNotch, barHeight, arcHeightWithNotch),
    );
  }

  CircleBottomNavigationBar buildCircleBottomNavigationBar(
      EdgeInsets viewPadding,
      double barHeightWithNotch,
      double barHeight,
      double arcHeightWithNotch) {
    return CircleBottomNavigationBar(
      initialSelection: currentPage,
      barHeight: viewPadding.bottom > 0 ? barHeightWithNotch : barHeight,
      arcHeight: viewPadding.bottom > 0 ? arcHeightWithNotch : barHeight,
      itemTextOff: viewPadding.bottom > 0 ? 0 : 1,
      itemTextOn: viewPadding.bottom > 0 ? 0 : 1,
      circleOutline: 15.0,
      shadowAllowance: 0.0,
      circleSize: 50.0,
      blurShadowRadius: 50.0,
      circleColor: Colors.purple,
      activeIconColor: Colors.white,
      inactiveIconColor: Colors.grey,
      tabs: getTabsData(),
      onTabChangedListener: (index) => setState(() => currentPage = index),
    );
  }

  List<TabData> getTabsData() {
    return [
      TabData(
        icon: Icons.home,
        iconSize: 25.0,
        title: 'Home',
        fontSize: 12,
        fontWeight: FontWeight.bold,
      ),
      TabData(
        icon: Icons.phone,
        iconSize: 25,
        title: 'Emergency',
        fontSize: 12,
        fontWeight: FontWeight.bold,
      ),
      TabData(
        icon: Icons.search,
        iconSize: 25,
        title: 'Search Place',
        fontSize: 12,
        fontWeight: FontWeight.bold,
      ),
      // TabData(
      //   icon: Icons.alarm,
      //   iconSize: 25,
      //   title: 'Alarm',
      //   fontSize: 12,
      //   fontWeight: FontWeight.bold,
      // ),
    ];
  }
}

0
投票

要创建这样的页面,您需要了解 Text、SingleChildScrollView 将滚动方向设置为水平、底部导航栏、Banner 等。


0
投票

您应该使用

CustomScrollView
并为其子级使用
Slivers

使用此方法,您可以创建具有强大动画的高级复杂可滚动用户界面。 了解有关条子的信息。

好锁😉

© www.soinside.com 2019 - 2024. All rights reserved.