1、布局
```
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:xiaomishop/app/service/MyScreenExtention.dart';
import '../controllers/gooddetail_controller.dart';
class GooddetailView extends GetView<GooddetailController> {
GooddetailView({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: _appBar(),
body: _body());
}
_appBar() {
return PreferredSize(
key: controller.appBarKey,
preferredSize: Size.fromHeight(110.hh),
child: Obx(() => AppBar(
leading: Container(
alignment: Alignment.center,
child: SizedBox(
width: 78.ww,
height: 78.ww,
child: ElevatedButton(
onPressed: () {
Get.back();
},
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.black12),
foregroundColor:
MaterialStateProperty.all(Colors.white70),
padding: MaterialStateProperty.all(
const EdgeInsets.all(0)),
shape: MaterialStateProperty.all(
const CircleBorder())),
child:
const Icon(Icons.arrow_back_ios_new_outlined)))),
actions: [
Container(
margin: EdgeInsets.only(right: 30.ww),
width: 78.ww,
height: 78.ww,
child: ElevatedButton(
onPressed: () {
Get.back();
},
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.black12),
foregroundColor:
MaterialStateProperty.all(Colors.white70),
padding: MaterialStateProperty.all(
const EdgeInsets.all(0)),
shape: MaterialStateProperty.all(
const CircleBorder())),
child: const Icon(Icons.share))),
Container(
margin: EdgeInsets.only(right: 30.ww),
width: 78.ww,
height: 78.ww,
child: ElevatedButton(
onPressed: () {
Get.back();
},
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.black12),
foregroundColor:
MaterialStateProperty.all(Colors.white70),
padding: MaterialStateProperty.all(
const EdgeInsets.all(0)),
shape: MaterialStateProperty.all(
const CircleBorder())),
child: const Icon(Icons.more_horiz_rounded)))
],
title: controller.showTab.value
? Container(
alignment: Alignment.center,
child: Obx(() => SizedBox(
width: 360.ww,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: controller.titleMap
.map((v) => Expanded(
flex: 1,
child: InkWell(
onTap: () {
controller
.setCurrentTitle(v["id"]!);
if (v["id"] == "1") {
Scrollable.ensureVisible(
controller.key1.currentContext
as BuildContext);
}
if (v["id"] == "2") {
Scrollable.ensureVisible(
controller.key2.currentContext
as BuildContext);
}
if (v["id"] == "3") {
Scrollable.ensureVisible(
controller.key3.currentContext
as BuildContext);
}
},
child: Column(
children: [
Text(v["title"]!,
style: TextStyle(
fontSize: 38.ss)),
v["id"] ==
controller.titleId.value
? Container(
height: 5.hh,
width: 60.ww,
color: Colors.red)
: SizedBox(
height: 5.hh,
width: 60.ww,
)
],
))))
.toList()))))
: const Text(""),
backgroundColor:
Colors.white70.withOpacity(controller.withOpacity.value),
elevation: 0,
)));
}
Widget _body() {
return SingleChildScrollView(
controller: controller.scrollController,
child: Column(
key: controller.containerKey,
children: [
Container(
key: controller.key1,
width: double.infinity,
child: Image.asset("assets/images/xiaomiBanner2.png"),
color: Colors.yellow),
Container(
key: controller.key2,
width: double.infinity,
height: 1080,
color: Colors.red,
),
Container(
key: controller.key3,
width: double.infinity,
height: 1980,
color: Colors.blue,
)
],
));
}
}
```
2、控制滑动
import 'package:flutter/cupertino.dart'
import 'package:get/get.dart'
class GooddetailController extends GetxController {
//TODO: Implement GooddetailController
ScrollController scrollController = ScrollController()
RxDouble withOpacity = 0.0.obs
GlobalKey key1 = GlobalKey()
GlobalKey key2 = GlobalKey()
GlobalKey key3 = GlobalKey()
GlobalKey appBarKey = GlobalKey()
GlobalKey containerKey = GlobalKey()
final titleMap = [
{"id": "1", "title": "商品"},
{"id": "2", "title": "详情"},
{"id": "3", "title": "评价"}
]
Rx<String> titleId = "1".obs
RxBool showTab = false.obs
void setCurrentTitle(String id) {
titleId.value = id
update()
}
final String name = "11"
void setName() {
print('hello world name')
}
@override
void onInit() {
super.onInit()
print('GooddetailController onInit')
WidgetsBinding.instance!.addPostFrameCallback(_afterLayout)
initListener()
}
double h1 = 0
double h2 = 0
double h3 = 0
double appBarH = 0
/**
* 获取SingleChildScrollView 各个元素的高度
*/
void _afterLayout(_) {
final RenderBox? containerRenderBox1 =
key1.currentContext?.findRenderObject() as RenderBox?
if (containerRenderBox1 != null) {
h1 = containerRenderBox1.size.height
}
final RenderBox? containerRenderBox2 =
key2.currentContext?.findRenderObject() as RenderBox?
if (containerRenderBox2 != null) {
h2 = containerRenderBox2.size.height
}
final RenderBox? containerRenderBox3 =
key3.currentContext?.findRenderObject() as RenderBox?
if (containerRenderBox3 != null) {
h3 = containerRenderBox3.size.height
}
final RenderBox? containerRenderBox4 =
appBarKey.currentContext?.findRenderObject() as RenderBox?
if (containerRenderBox4 != null) {
appBarH = containerRenderBox4.size.height
}
print('_afterLayout ${h1} ${h2} ${h3} ${appBarH}')
}
@override
void onReady() {
super.onReady()
print('GooddetailController onReady')
}
@override
void onClose() {
super.onClose()
print('GooddetailController onClose')
}
void initListener() {
scrollController.addListener(() {
var pixels = scrollController.position.pixels
print('${pixels}')
withOpacity.value = pixels / appBarH
if (withOpacity.value > 1) {
withOpacity.value = 1
}
if (withOpacity.value >=0.1) {
if (showTab.value == false) {
showTab.value = true
}
} else {
if (showTab.value == true) {
showTab.value = false
}
}
if (showTab.value) {
if (pixels < h1-appBarH) {
setCurrentTitle("1")
} else if (pixels > h1-appBarH && pixels < h2+h1-appBarH) {
setCurrentTitle("2")
}
if (pixels > h2+h1-appBarH) {
setCurrentTitle("3")
}
}
update()
})
}
}
3、实现效果
