flutter 搜索栏在两个容器之间浮动

ddrv8njm  于 2023-05-08  发布在  Flutter
关注(0)|答案(1)|浏览(209)

enter image description here
你好
我真的很想把搜索栏做成这样,但我做不到。尽管使用了Stack,结果就像
enter image description here

import 'package:empiregarage_mobile/application_layer/on_going_service/on_going_service.dart';
import 'package:empiregarage_mobile/application_layer/screens/activities/activities.dart';
import 'package:empiregarage_mobile/application_layer/screens/booking/booking_detail.dart';
import 'package:empiregarage_mobile/application_layer/screens/notification/notification.dart';
import 'package:empiregarage_mobile/application_layer/screens/search/search.dart';
import 'package:empiregarage_mobile/application_layer/screens/services/service_details.dart';
import 'package:empiregarage_mobile/application_layer/widgets/homepage_famous_service.dart';
import 'package:empiregarage_mobile/application_layer/widgets/homepage_service_iconbutton.dart';
import 'package:empiregarage_mobile/common/jwt_interceptor.dart';
import 'package:empiregarage_mobile/common/style.dart';
import 'package:empiregarage_mobile/helper/notification_helper.dart';
import 'package:empiregarage_mobile/models/response/activity.dart';
import 'package:empiregarage_mobile/services/activity_services/activity_service.dart';
import 'package:empiregarage_mobile/services/item_service/item_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:page_transition/page_transition.dart';
import '../../../common/colors.dart';
import '../../../models/response/item.dart';

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  List<ItemResponseModel>? _listItem;
  List<ItemResponseModel>? _filteredItem;

  late List<ActivityResponseModel?> _listOngoingActivity;
  bool _loading = false;

  bool isService = true;

  int _notificationCount = 0;

  _fetchData() async {
    _listItem = await ItemService().fetchListItem(true);
    var userId = await getUserId();
    if (userId == null) throw Exception("NOT_FOUND_USER");
    var listActivity = await ActivityService().fetchOnGoingActivity(userId);
    _listOngoingActivity = listActivity
        .where((element) => element != null && element.isOnGoing == true)
        .where((element) => element!.status == null || element.status != 5)
        .toList();
    _filteredItem = _listItem;

    //count notification
    _notificationCount = await countNotification();
    if (!mounted) return;
    setState(() {
      _loading = true;
    });
  }

  @override
  void initState() {
    _fetchData();
    super.initState();
  }

  Future refresh() {
    return _fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return !_loading
        ? const Scaffold(
            body: Center(
            child: CircularProgressIndicator(),
          ))
        : Scaffold(
            backgroundColor: AppColors.lightGrey,
            body: RefreshIndicator(
              onRefresh: refresh,
              child: ListView(
                children: <Widget>[
                  Container(
                    height: 160.h,
                    decoration: BoxDecoration(
                        color: AppColors.welcomeScreenBackGround,
                        borderRadius: BorderRadius.only(
                          bottomLeft: Radius.circular(0.r),
                          bottomRight: Radius.circular(0.r),
                        )),
                    child: Stack(
                      children: <Widget>[
                        SafeArea(
                          child: Column(
                            children: <Widget>[
                              Container(
                                margin:
                                    const EdgeInsets.symmetric(horizontal: 24),
                                child: Stack(
                                  alignment: Alignment.centerLeft,
                                  children: <Widget>[
                                    Image.asset(
                                      "assets/image/app-logo/homepage-icon.png",
                                      height: 100.h,
                                      width: 90.w,
                                    ),
                                    Align(
                                      alignment: Alignment.centerRight,
                                      child: Container(
                                        decoration: BoxDecoration(
                                            borderRadius:
                                                BorderRadius.circular(100),
                                            shape: BoxShape.rectangle,
                                            boxShadow: const [
                                              BoxShadow(
                                                offset: Offset(0, 1),
                                                blurRadius: 1,
                                                color: AppColors.blue600,
                                              )
                                            ]),
                                        child: IconButton(
                                            onPressed: () async {
                                              var userId = await getUserId();
                                              if (userId == null) {
                                                throw Exception(
                                                    "Not found user");
                                              }
                                              // ignore: use_build_context_synchronously
                                              Navigator.push(
                                                context,
                                                MaterialPageRoute(
                                                    builder: (context) =>
                                                        NotificationPage(
                                                          userId: userId,
                                                        )),
                                              );
                                            },
                                            icon: Badge(
                                                backgroundColor:
                                                    _notificationCount == 0
                                                        ? Colors.transparent
                                                        : AppColors.errorIcon,
                                                label: _notificationCount > 0
                                                    ? Text(
                                                        _notificationCount
                                                            .toString(),
                                                        style: const TextStyle(
                                                            color:
                                                                Colors.white),
                                                      )
                                                    : null,
                                                child: const Icon(
                                                  FontAwesomeIcons.bell,
                                                  size: 20,
                                                  color: AppColors
                                                      .whiteButtonColor,
                                                ))),
                                      ),
                                    )
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ),
                        Positioned(
                            bottom: 0,
                            left: 0,
                            right: 0,
                            child: Container(
                              margin:
                                  const EdgeInsets.symmetric(horizontal: 20),
                              width: 335.w,
                              height: 42.h,
                              decoration: BoxDecoration(
                                  color: AppColors.searchBarColor,
                                  borderRadius:
                                      BorderRadius.all(Radius.circular(16.r)),
                                  boxShadow: const [
                                    BoxShadow(
                                      offset: Offset(0, 1),
                                      blurRadius: 5,
                                      color: AppColors.unselectedBtn,
                                    )
                                  ]),
                              child: SizedBox(
                                width: 104.w,
                                height: 24.h,
                                child: TextField(
                                  onSubmitted: (value) {
                                    if (value.isNotEmpty) {
                                      Navigator.push(
                                        context,
                                        MaterialPageRoute(
                                            builder: (context) => SearchPage(
                                                  searchString: value,
                                                )),
                                      );
                                    }
                                  },
                                  //style: searchTextStyle,
                                  decoration: InputDecoration(
                                    border: InputBorder.none,
                                    hintStyle: TextStyle(
                                      fontFamily: 'SFProDisplay',
                                      fontSize: 14.sp,
                                      fontWeight: FontWeight.w400,
                                      color: AppColors.lightTextColor,
                                    ),
                                    hintText: 'Tìm dịch vụ',
                                    prefixIcon: const Icon(
                                      FontAwesomeIcons.magnifyingGlass,
                                      size: 24,
                                      color: AppColors.grey400,
                                    ),
                                  ),
                                ),
                              ),
                            ))
                      ],
                    ),
                  ),
                  SizedBox(
                    height: 20.h,
                  ),
                  Container(
                      margin: const EdgeInsets.symmetric(horizontal: 24),
                      child: const HomePageServiceIconButton()),
                  SizedBox(
                    height: 10.h,
                  ),
                  if (_listOngoingActivity.isNotEmpty)
                    ListTile(
                        title: Text(
                      "Đang hoạt động",
                      style: AppStyles.header600(fontsize: 18.sp),
                    )),
                  if (_listOngoingActivity.isNotEmpty)
                    Padding(
                      padding: EdgeInsets.symmetric(horizontal: 12.w),
                      child: SizedBox(
                        height: 102.h * _listOngoingActivity.length,
                        child: Center(
                          child: ListView.builder(
                            itemCount: _listOngoingActivity.length,
                            physics: const NeverScrollableScrollPhysics(),
                            itemBuilder: (context, index) {
                              var item = _listOngoingActivity[index];
                              return Padding(
                                padding: EdgeInsets.only(bottom: 12.h),
                                child: InkWell(
                                  onTap: () async {
                                    Navigator.of(context).push(PageTransition(
                                        type: PageTransitionType.bottomToTop,
                                        duration:
                                            const Duration(milliseconds: 350),
                                        childCurrent: widget,
                                        child: item.isBooking
                                            ? BookingDetail(
                                                data: item,
                                              )
                                            : OnGoingService(
                                                servicesId: item.id,
                                              )));
                                  },
                                  child: DecoratedBox(
                                    decoration: BoxDecoration(
                                        color: Colors.white,
                                        boxShadow: [
                                          BoxShadow(
                                            color: Colors.grey.withOpacity(0.3),
                                            spreadRadius: 1.h,
                                            blurRadius: 1.2,
                                            offset: Offset(0, 4.h),
                                          )
                                        ],
                                        borderRadius: const BorderRadius.all(
                                            Radius.circular(16))),
                                    child: SizedBox(
                                      height: 90.h,
                                      child: ActivityChip(
                                        carInfo:
                                            '${item!.car!.carBrand} ${item.car!.carModel} ${item.car!.carLisenceNo}',
                                        date: item.date.toString(),
                                        daysLeft: item.date != null
                                            ? DateTime.now()
                                                .toLocal()
                                                .difference(
                                                    item.date as DateTime)
                                                .inDays
                                            : null,
                                        isBooking: item.isBooking,
                                        item: item,
                                        code: item.code != null
                                            ? item.code.toString()
                                            : "#########",
                                      ),
                                    ),
                                  ),
                                ),
                              );
                            },
                          ),
                        ),
                      ),
                    ),
                  Container(
                    margin: const EdgeInsets.symmetric(horizontal: 24),
                    child: Row(
                      children: <Widget>[
                        Text(
                          "Dịch vụ phổ biến",
                          style: TextStyle(
                              fontSize: 18.sp,
                              fontWeight: FontWeight.w600,
                              color: AppColors.blackTextColor,
                              fontFamily: 'SFProDisplay'),
                        ),
                        const Spacer(),
                        TextButton(
                            onPressed: () {},
                            child: Text(
                              "Xem tất cả",
                              style: TextStyle(
                                  fontSize: 14.sp,
                                  fontWeight: FontWeight.w500,
                                  color: AppColors.white100,
                                  fontFamily: 'SFProDisplay'),
                            ))
                      ],
                    ),
                  ),
                  SizedBox(
                    height: 250.h,
                    width: 340.w,
                    child: ListView.separated(
                      reverse: false,
                      scrollDirection: Axis.horizontal,
                      physics: const ClampingScrollPhysics(),
                      shrinkWrap: true,
                      itemCount: _filteredItem!.length,
                      separatorBuilder: (context, index) {
                        return SizedBox(
                          width: 15.w,
                        );
                      },
                      itemBuilder: (context, index) {
                        return InkWell(
                          onTap: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) => ServiceDetails(
                                      itemId: _filteredItem![index].id)),
                            );
                          },
                          child: HomepageFamousService(
                            backgroundImage: _filteredItem![index].photo,
                            title: _filteredItem![index].name,
                            price: _filteredItem![index].prices!.isNotEmpty
                                ? NumberFormat.currency(
                                        decimalDigits: 0, locale: 'vi_VN')
                                    .format(_filteredItem![index]
                                        .prices!
                                        .first
                                        .price)
                                    .toString()
                                : "Liên hệ",
                            usageCount: '182',
                            rating: '4.4',
                            tag: _filteredItem![index].category != null
                                ? _filteredItem![index].category!.name
                                : "Dịch vụ",
                          ),
                        );
                      },
                    ),
                  ),
                  SizedBox(
                    height: 20.h,
                  )
                ],
              ),
            ),
          );
  }
}

这是我的代码。你能帮帮我吗
非常感谢
我尝试使用Stack来创建搜索栏,使用Positioned()来移动它的位置

5sxhfpxr

5sxhfpxr1#

class AnotherHome extends StatelessWidget {
AnotherHome({super.key});

//top container height
final topContainerHeight = 160.h;
//search bar height
final searchBarHeight = 52.h;

@override
Widget build(BuildContext context) {
return Scaffold(
    body: SafeArea(
        child: Stack(
  children: [
    Column(
      children: [
        //top container
        Container(
          height: topContainerHeight,
          color: Colors.blue,
          child: Center(
            child: Padding(
              padding: const EdgeInsets.symmetric(horizontal: 10.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  //Empire
                  const Text('Name'),
                  IconButton(
                      onPressed: () {},
                      icon: const Icon(Icons.notification_add))
                ],
              ),
            ),
          ),
        ),
        //main widgets 
        Expanded(
          child: SizedBox(
            height: double.infinity,
            // color: Colors.white,
            child: Padding(
              padding: EdgeInsets.only(top: searchBarHeight),
             //change the list view with your widgets
              child: ListView.builder(
                itemCount: 10,
                itemBuilder: (context, index) {
                  return Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Container(
                      height: 80.h,
                      color: Colors.amber,
                      width: double.infinity,
                    ),
                  );
                },
              ),
            ),
          ),
        ),
      ],
    ),
    //search widget
    Positioned(
      top: topContainerHeight - (searchBarHeight / 2),
      left: 0,
      right: 0,
      child: Padding(
        //add your own padding from left and right
        padding: const EdgeInsets.symmetric(horizontal: 20.0),
        child: SizedBox(
          height: searchBarHeight,
          width: 335.w,
          child: Center(
            child: TextField(
              decoration: InputDecoration(
                contentPadding: const EdgeInsets.symmetric(vertical: 10),
                prefixIcon: const Icon(Icons.search),
                filled: true,
                fillColor: Colors.white,
                hintText: 'Tim',
                hintStyle: const TextStyle(color: Colors.grey),
                focusedBorder: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(12.0),
                    //remove the border side
                    borderSide: const BorderSide(color: Colors.black)),
                border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(12.0),
                    //remove the border side
                    borderSide: const BorderSide(color: Colors.black)),
              ),
            ),
          ),
        ),
      ),
    ),
  ],
)));
}
}

相关问题