app_商品详情页面布局1

105 阅读3分钟

1.生成页面 get create page content

商品详情页面布局监听滚动条事件改变导航动画

import 'package:flutter/material.dart';
import 'package:flutterdemo/app/services/screenAdapter.dart';

import 'package:get/get.dart';

import '../controllers/content_controller.dart';

class ContentView extends GetView<ContentController> {
  const ContentView({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true, // 实现透明导航
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(ScreenAdapter.height(96)),
        child: Obx(() => 
        AppBar(
          leading: Container(
            alignment: Alignment.center,
            child: SizedBox(
              width: ScreenAdapter.width(88),
              height: ScreenAdapter.width(88),
              child: ElevatedButton(
                onPressed: (){}, 
                style: ButtonStyle(
                  // TODO ??
                  padding: MaterialStateProperty.all( 
                    const EdgeInsets.all(0),
                  ),
                  alignment: Alignment.center,
                  backgroundColor: MaterialStateProperty.all(Colors.black12),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(const CircleBorder()),
                ),
                child: const Icon(Icons.arrow_back_ios_new_outlined)),
            ),
          ),
          title: SizedBox(
            width: ScreenAdapter.width(400),
            height: ScreenAdapter.height(96),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Padding(padding: EdgeInsets.all(0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "商品",
                      style: TextStyle(fontSize: ScreenAdapter.fontSize(36)),
                    ),
                    Container(
                      margin: EdgeInsets.only(
                        top: ScreenAdapter.height(10),      
                      ),
                      width: ScreenAdapter.width(100),
                      height: ScreenAdapter.height(2),
                      color: Colors.red,
                    )
                  ],
                ),
                ),
                Padding(padding: EdgeInsets.all(0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "详情",
                      style: TextStyle(fontSize: ScreenAdapter.fontSize(36)),
                    ),
                    Container(
                      margin: EdgeInsets.only(
                        top: ScreenAdapter.height(10),      
                      ),
                      width: ScreenAdapter.width(100),
                      height: ScreenAdapter.height(2),
                      color: Colors.red,
                    )
                  ],
                ),
                ),
                Padding(padding: EdgeInsets.all(0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "推荐",
                      style: TextStyle(fontSize: ScreenAdapter.fontSize(36)),
                    ),
                    Container(
                      margin: EdgeInsets.only(
                        top: ScreenAdapter.height(10),      
                      ),
                      width: ScreenAdapter.width(100),
                      height: ScreenAdapter.height(2),
                      color: Colors.red,
                    )
                  ],
                ),
                ),
              ],
            ),
          ),
          centerTitle: true,
          backgroundColor: Colors.white.withOpacity(controller.opacity.value), // 实现透明导航
          elevation: 0,
          actions: [
            Container(
              margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
              width: ScreenAdapter.width(88),
              height: ScreenAdapter.width(88),
              child: ElevatedButton(
                onPressed: (){},
                style: ButtonStyle(
                  padding: MaterialStateProperty.all( 
                    const EdgeInsets.all(0),
                  ),
                  alignment: Alignment.center,
                  backgroundColor: MaterialStateProperty.all(Colors.black12),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(const CircleBorder()),
                ), 
                child: const Icon(Icons.file_upload_outlined)
                ),
            ),
            Container(
              margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
              width: ScreenAdapter.width(88),
              height: ScreenAdapter.width(88),
              child: ElevatedButton(
                onPressed: (){},
                style: ButtonStyle(
                  padding: MaterialStateProperty.all( 
                    const EdgeInsets.all(0),
                  ),
                  alignment: Alignment.center,
                  backgroundColor: MaterialStateProperty.all(Colors.black12),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(const CircleBorder()),
                ), 
                child: const Icon(Icons.more_horiz_rounded)
                ),
            )
          ],

        )),
      ),
      body: ListView(
        controller: controller.scrollController,
        children: [
          Container(
            width: ScreenAdapter.width(1080),
            height: ScreenAdapter.height(300),
            color: Colors.orange,
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          Container(
            width: ScreenAdapter.width(1080),
            height: ScreenAdapter.height(300),
            color: Colors.orange,
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          Container(
            width: ScreenAdapter.width(1080),
            height: ScreenAdapter.height(300),
            color: Colors.orange,
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          ),
          ListTile(
            title: Text("我是一个内容列表"),
          )
        ],
      )
    );
  }
}

controller

RxDouble opacity = 0.0.obs;
  final ScrollController scrollController = ScrollController();

  @override
  void onInit() {
    super.onInit();
  }

  // 监听滚动条滚动事件
  void scrollControllerListener(){
    scrollController.addListener(() {
      if(scrollController.position.pixels <=100){
        opacity.value = scrollController.position.pixels/100;
        print(opacity.value);
        update();
      }
    });
  }

image.png

二 顶部tab切换以及使用SingleChildScrollerView实现锚点效果

import 'package:flutter/material.dart';
import 'package:flutterdemo/app/services/screenAdapter.dart';

import 'package:get/get.dart';

import '../controllers/content_controller.dart';

class ContentView extends GetView<ContentController> {
  const ContentView({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true, // 实现透明导航
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(ScreenAdapter.height(96)),
        child: Obx(() => 
        AppBar(
          leading: Container(
            alignment: Alignment.center,
            child: SizedBox(
              width: ScreenAdapter.width(88),
              height: ScreenAdapter.width(88),
              child: ElevatedButton(
                onPressed: (){}, 
                style: ButtonStyle(
                  // TODO ??
                  padding: MaterialStateProperty.all( 
                    const EdgeInsets.all(0),
                  ),
                  alignment: Alignment.center,
                  backgroundColor: MaterialStateProperty.all(Colors.black12),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(const CircleBorder()),
                ),
                child: const Icon(Icons.arrow_back_ios_new_outlined)),
            ),
          ),
          title: SizedBox(
            width: ScreenAdapter.width(400),
            height: ScreenAdapter.height(96),
            child: controller.showTabs.value ? Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: controller.tabsList.map((v){
                return InkWell(
                  onTap: (){
                    controller.changeSelectedTabsIndex(v["id"]);
                    // 跳转到指定的容器
                    if(v["id"] == 1){
                      Scrollable.ensureVisible(
                        controller.gk1.currentContext as BuildContext,
                        duration:const Duration(microseconds: 100)
                      );
                    }else if(v["id"] == 2){
                       Scrollable.ensureVisible(
                        controller.gk2.currentContext as BuildContext,
                        duration:const Duration(microseconds: 100)
                      );
                    }else if(v["id"] == 3){
                       Scrollable.ensureVisible(
                        controller.gk3.currentContext as BuildContext,
                        duration:const Duration(microseconds: 500)
                      );
                    }
                  },
                  child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          "${v["title"]}",
                          style: TextStyle(fontSize: ScreenAdapter.fontSize(36)),
                        ),
                        v["id"] == controller.selectedTabsIndex.value?
                        Container(
                          margin: EdgeInsets.only(
                            top: ScreenAdapter.height(10),      
                          ),
                          width: ScreenAdapter.width(100),
                          height: ScreenAdapter.height(2),
                          color: Colors.red,
                        )
                        : Container(
                          margin: EdgeInsets.only(
                            top: ScreenAdapter.height(10)
                          ),
                          width: ScreenAdapter.width(100),
                          height: ScreenAdapter.height(2),
                        )
                      ],

                  ),
                );
              }).toList()
            ):const Text(""),
          ),
          centerTitle: true,
          backgroundColor: Colors.white.withOpacity(controller.opacity.value), // 实现透明导航
          elevation: 0,
          actions: [
            Container(
              margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
              width: ScreenAdapter.width(88),
              height: ScreenAdapter.width(88),
              child: ElevatedButton(
                onPressed: (){},
                style: ButtonStyle(
                  padding: MaterialStateProperty.all( 
                    const EdgeInsets.all(0),
                  ),
                  alignment: Alignment.center,
                  backgroundColor: MaterialStateProperty.all(Colors.black12),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(const CircleBorder()),
                ), 
                child: const Icon(Icons.file_upload_outlined)
                ),
            ),
            Container(
              margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
              width: ScreenAdapter.width(88),
              height: ScreenAdapter.width(88),
              child: ElevatedButton(
                onPressed: (){},
                style: ButtonStyle(
                  padding: MaterialStateProperty.all( 
                    const EdgeInsets.all(0),
                  ),
                  alignment: Alignment.center,
                  backgroundColor: MaterialStateProperty.all(Colors.black12),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(const CircleBorder()),
                ), 
                child: const Icon(Icons.more_horiz_rounded)
                ),
            )
          ],

        )),
      ),
      body: SingleChildScrollView(
        controller: controller.scrollController,
        child: Column(
          children: [
            Container(
              key: controller.gk1,
              alignment: Alignment.center,
              width: ScreenAdapter.width(1080),
              height: ScreenAdapter.height(1800),
              color: Colors.orange,
              child: Text("商品",style: TextStyle(fontSize: 100)),
            ),
            Container(
              key: controller.gk2,
              alignment: Alignment.center,
              width: ScreenAdapter.width(1080),
              height: ScreenAdapter.height(1800),
              color: Colors.blue,
              child: Text("详情",style: TextStyle(fontSize: 100)),
            ),
            Container(
              key: controller.gk3,
              alignment: Alignment.center,
              width: ScreenAdapter.width(1080),
              height: ScreenAdapter.height(1800),
              color: Colors.red,
              child: Text("推荐",style: TextStyle(fontSize: 100)),
            )
          ],
        ),
      )
    );
  }
}

controller

import 'dart:ffi';

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class ContentController extends GetxController {
  //TODO: Implement ContentController

  // 导航的透明度
  RxDouble opacity = 0.0.obs;
  final ScrollController scrollController = ScrollController();
  GlobalKey gk1 = GlobalKey();
  GlobalKey gk2 = GlobalKey();
  GlobalKey gk3 = GlobalKey();
  // 是否显示tabs
  RxBool showTabs = false.obs;

  List tabsList = [
    {
      "id":1,
      "title":"商品"
    },
    {
      "id":2,
      "title":"详情"
    },
    {
      "id":3,
      "title":"推荐"
    },
  ];
  RxInt selectedTabsIndex = 1.obs;

  @override
  void onInit() {
    super.onInit();
    scrollControllerListener();
  }

  // 监听滚动条滚动事件
  void scrollControllerListener(){
    scrollController.addListener(() {
      print("劲来");
      if(scrollController.position.pixels <=100){
        opacity.value = scrollController.position.pixels/100;
        if(showTabs.value == true){
          showTabs.value = false;
        }
        print(opacity.value);
        update();
      }else{
        if(showTabs.value == false){
          showTabs.value = true;
          update();
        }
      }
    });
  }

  @override
  void onReady() {
    super.onReady();
  }

  @override
  void onClose() {
    super.onClose();
  }

  void changeSelectedTabsIndex(index){
    selectedTabsIndex.value = index;
    update();
  }

 
}

image.png

第三 使用showMenu 弹出菜单,使用定位实现底部浮动导航布局

image.png

import 'package:flutter/material.dart';
import 'package:flutterdemo/app/services/screenAdapter.dart';

import 'package:get/get.dart';

import '../controllers/content_controller.dart';

class ContentView extends GetView<ContentController> {
  const ContentView({Key? key}) : super(key: key);

    Widget _appBar(BuildContext context) {
    return Obx(
      () => AppBar(
      leading: Container(
        alignment: Alignment.center,
        child: SizedBox(
          width: ScreenAdapter.width(88),
          height: ScreenAdapter.width(88),
          child: ElevatedButton(
            onPressed: (){}, 
            style: ButtonStyle(
              // TODO ??
              padding: MaterialStateProperty.all( 
                const EdgeInsets.all(0),
              ),
              alignment: Alignment.center,
              backgroundColor: MaterialStateProperty.all(Colors.black12),
              foregroundColor: MaterialStateProperty.all(Colors.white),
              shape: MaterialStateProperty.all(const CircleBorder()),
            ),
            child: const Icon(Icons.arrow_back_ios_new_outlined)),
        ),
      ),
      title: SizedBox(
        width: ScreenAdapter.width(400),
        height: ScreenAdapter.height(96),
        child: controller.showTabs.value ? Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: controller.tabsList.map((v){
            return InkWell(
              onTap: (){
                controller.changeSelectedTabsIndex(v["id"]);
                // 跳转到指定的容器
                if(v["id"] == 1){
                  Scrollable.ensureVisible(
                    controller.gk1.currentContext as BuildContext,
                    duration:const Duration(microseconds: 100)
                  );
                }else if(v["id"] == 2){
                   Scrollable.ensureVisible(
                    controller.gk2.currentContext as BuildContext,
                    duration:const Duration(microseconds: 100)
                  );
                }else if(v["id"] == 3){
                   Scrollable.ensureVisible(
                    controller.gk3.currentContext as BuildContext,
                    duration:const Duration(microseconds: 500)
                  );
                }
              },
              child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      "${v["title"]}",
                      style: TextStyle(fontSize: ScreenAdapter.fontSize(36)),
                    ),
                    v["id"] == controller.selectedTabsIndex.value?
                    Container(
                      margin: EdgeInsets.only(
                        top: ScreenAdapter.height(10),      
                      ),
                      width: ScreenAdapter.width(100),
                      height: ScreenAdapter.height(2),
                      color: Colors.red,
                    )
                    : Container(
                      margin: EdgeInsets.only(
                        top: ScreenAdapter.height(10)
                      ),
                      width: ScreenAdapter.width(100),
                      height: ScreenAdapter.height(2),
                    )
                  ],
    
              ),
            );
          }).toList()
        ):const Text(""),
      ),
      centerTitle: true,
      backgroundColor: Colors.white.withOpacity(controller.opacity.value), // 实现透明导航
      elevation: 0,
      actions: [
        Container(
          margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
          width: ScreenAdapter.width(88),
          height: ScreenAdapter.width(88),
          child: ElevatedButton(
            onPressed: (){},
            style: ButtonStyle(
              padding: MaterialStateProperty.all( 
                const EdgeInsets.all(0),
              ),
              alignment: Alignment.center,
              backgroundColor: MaterialStateProperty.all(Colors.black12),
              foregroundColor: MaterialStateProperty.all(Colors.white),
              shape: MaterialStateProperty.all(const CircleBorder()),
            ), 
            child: const Icon(Icons.file_upload_outlined)
            ),
        ),
        Container(
          margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
          width: ScreenAdapter.width(88),
          height: ScreenAdapter.width(88),
          child: ElevatedButton(
            onPressed: (){
              showMenu(
                color: Colors.black87.withOpacity(0.7),
                context: context, 
                position: RelativeRect.fromLTRB(  // todo
                  ScreenAdapter.width(800),
                  ScreenAdapter.height(220),
                   ScreenAdapter.width(20), 
                   0), 
                items: [
                    PopupMenuItem(child: Row(
                      children: [
                        Icon(Icons.home,color: Colors.white),
                        Text('首页',style: TextStyle(color: Colors.white),)
                      ],
                    )
                    ),
                    PopupMenuItem(child: Row(
                      children: [
                        Icon(Icons.message,color: Colors.white),
                        Text('消息',style: TextStyle(color: Colors.white),)
                      ],
                    )
                    ),
                    PopupMenuItem(child: Row(
                      children: [
                        Icon(Icons.star,color: Colors.white),
                        Text('收藏',style: TextStyle(color: Colors.white),)
                      ],
                    )
                    ),
                ]
                );
            },
            style: ButtonStyle(
              padding: MaterialStateProperty.all( 
                const EdgeInsets.all(0),
              ),
              alignment: Alignment.center,
              backgroundColor: MaterialStateProperty.all(Colors.black12),
              foregroundColor: MaterialStateProperty.all(Colors.white),
              shape: MaterialStateProperty.all(const CircleBorder()),
            ), 
            child: const Icon(Icons.more_horiz_rounded)
            ),
        )
      ],
    
    )
    );
  }

  Widget _body(){
    return SingleChildScrollView(
        controller: controller.scrollController,
        child: Column(
          children: [
            Container(
              key: controller.gk1,
              alignment: Alignment.center,
              width: ScreenAdapter.width(1080),
              height: ScreenAdapter.height(1800),
              color: Colors.orange,
              child: Text("商品",style: TextStyle(fontSize: 100)),
            ),
            Container(
              key: controller.gk2,
              alignment: Alignment.center,
              width: ScreenAdapter.width(1080),
              height: ScreenAdapter.height(1800),
              color: Colors.blue,
              child: Text("详情",style: TextStyle(fontSize: 100)),
            ),
            Container(
              key: controller.gk3,
              alignment: Alignment.center,
              width: ScreenAdapter.width(1080),
              height: ScreenAdapter.height(1800),
              color: Colors.red,
              child: Text("推荐",style: TextStyle(fontSize: 100)),
            )
          ],
        ),
      );
  }

  Widget _bottom(){
    return Positioned(
      bottom: 0,
      left: 0,
      right: 0,
      child: Container(
      height: ScreenAdapter.height(160),
      decoration: BoxDecoration(
        color: Colors.white,
        border: Border(
          top: BorderSide(
            width: ScreenAdapter.width(2),color: Colors.black12
          )
        )
      ),
      child: Row(
        children: [
          SizedBox(
            width: ScreenAdapter.width(200),
            height: ScreenAdapter.height(160),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Icon(Icons.shopping_cart),
                Text("购物车",style: TextStyle(fontSize: ScreenAdapter.fontSize(32)))
              ],
            ),
          ),
          Expanded(
            flex: 1,
            child: Container(
              height: ScreenAdapter.height(120),
              margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
              child: ElevatedButton(
                style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(
                    const Color.fromRGBO(255, 165, 0, 0.9)
                  ),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(
                    RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))
                  )
                ),
                onPressed: (){}, 
                child: Text("加入购物车")),
            )
            ),
            Expanded(
            flex: 1,
            child: Container(
              height: ScreenAdapter.height(120),
              margin: EdgeInsets.only(right: ScreenAdapter.width(20)),
              child: ElevatedButton(
                style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(
                    const Color.fromRGBO(255, 1, 0, 0.9)
                  ),
                  foregroundColor: MaterialStateProperty.all(Colors.white),
                  shape: MaterialStateProperty.all(
                    RoundedRectangleBorder(borderRadius: BorderRadius.circular(10))
                  )
                ),
                onPressed: (){}, 
                child: Text("立即购买")),
            ))

        ],
      ),
    ));
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true, // 实现透明导航
      appBar: PreferredSize(
        preferredSize: Size.fromHeight(ScreenAdapter.height(120)),
        child: _appBar(context),
      ),
      body: Stack(
        children: [
          _body(),
          _bottom(),
        ],
      )
    );
  }
}