स्क्रीन पर एक विजेट के आकार / स्थिति पाने के लिए आपको उपयोग कर सकते हैं GlobalKey
अपने पाने के लिए BuildContext
तो लगता है RenderBox
कि विशिष्ट विजेट है, जो अपनी वैश्विक स्थिति और गाया आकार में शामिल होंगे की।
बस एक बात का ध्यान रखें: यदि विजेट प्रदान नहीं किया गया है तो यह संदर्भ मौजूद नहीं हो सकता है। जो ListView
विजेट के साथ एक समस्या का कारण बन सकते हैं, यदि वे संभावित रूप से दिखाई दे रहे हैं तो ही प्रदान किए जाते हैं।
एक और समस्या यह है कि आप कॉल के RenderBox
दौरान एक विजेट प्राप्त नहीं कर सकते build
क्योंकि विजेट अभी तक प्रदान नहीं किया गया है।
लेकिन मुझे निर्माण के दौरान आकार की आवश्यकता है! मैं क्या कर सकता हूँ?
एक शांत विजेट है जो मदद कर सकता है: Overlay
और इसकी OverlayEntry
। वे सब कुछ के ऊपर विगेट्स प्रदर्शित करने के लिए उपयोग किए जाते हैं (स्टैक के समान)।
लेकिन सबसे अच्छी बात यह है कि वे एक अलग build
प्रवाह पर हैं; वे नियमित विजेट के बाद निर्मित होते हैं ।
इसका एक सुपर कूल निहितार्थ है: OverlayEntry
एक आकार हो सकता है जो वास्तविक विजेट ट्री के विजेट पर निर्भर करता है।
ठीक है। लेकिन OverlayEntry को मैन्युअल रूप से पुनर्निर्माण करने की आवश्यकता नहीं है?
हाँ, वो करते हैं। लेकिन, के बारे में पता होना करने के लिए एक और बात है: ScrollController
करने के लिए पारित Scrollable
, के समान एक सुनने योग्य है AnimationController
।
जिसका अर्थ है कि आप एक के AnimatedBuilder
साथ गठबंधन कर सकते हैं ScrollController
, यह एक स्क्रॉल पर अपने विजेट को स्वचालित रूप से पुनर्निर्माण करने के लिए प्यारा प्रभाव होगा। इस स्थिति के लिए बिल्कुल सही?
एक उदाहरण में सब कुछ मिलाकर:
निम्नलिखित उदाहरण में, आपको एक ओवरले दिखाई देगा जो अंदर एक विजेट का अनुसरण ListView
करता है और समान ऊंचाई साझा करता है।
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final controller = ScrollController();
OverlayEntry sticky;
GlobalKey stickyKey = GlobalKey();
@override
void initState() {
if (sticky != null) {
sticky.remove();
}
sticky = OverlayEntry(
builder: (context) => stickyBuilder(context),
);
SchedulerBinding.instance.addPostFrameCallback((_) {
Overlay.of(context).insert(sticky);
});
super.initState();
}
@override
void dispose() {
sticky.remove();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
controller: controller,
itemBuilder: (context, index) {
if (index == 6) {
return Container(
key: stickyKey,
height: 100.0,
color: Colors.green,
child: const Text("I'm fat"),
);
}
return ListTile(
title: Text(
'Hello $index',
style: const TextStyle(color: Colors.white),
),
);
},
),
);
}
Widget stickyBuilder(BuildContext context) {
return AnimatedBuilder(
animation: controller,
builder: (_,Widget child) {
final keyContext = stickyKey.currentContext;
if (keyContext != null) {
final box = keyContext.findRenderObject() as RenderBox;
final pos = box.localToGlobal(Offset.zero);
return Positioned(
top: pos.dy + box.size.height,
left: 50.0,
right: 50.0,
height: box.size.height,
child: Material(
child: Container(
alignment: Alignment.center,
color: Colors.purple,
child: const Text("^ Nah I think you're okay"),
),
),
);
}
return Container();
},
);
}
}
नोट :
एक अलग स्क्रीन पर नेविगेट करते समय, निम्नलिखित कॉल करें अन्यथा चिपचिपा दिखाई देगा।
sticky.remove();