I don’t know if you are familiar with the flutter, but THE author has been with flutter for about a week. The most prominent aspect of Flutter is a separate page rendering engine that uses the DART language for multi-end rendering. It also communicates with native systems to handle native system level function calls that are beyond the capabilities of Flutter. If you type the open ios/Runner. Xcworkspace command on the terminal command line under androidStudio, it will open the ios project corresponding to the flutter project. Be familiar with the iOS development friend knows keywindow rootViewController is app project root view, but the root view of flutter open iOS project is FlutterViewController, so it is good to understand, The flutter performs all UI drawing in the root view. Now that you’ve got the root view, you can actually, as an iOS developer, play with it any way you want.
For those who are not familiar with building environments and building flutter projects, check out the Website Flutter.
How do I add a global overlay view as a gray mask
static OverlayEntry? _backOverlayEntry; // Create a render layerCopy the code
OverlayState? overlayState = Overlay.of(context); // Create a coating managerCopy the code
overlayState! .insert(_overlayEntry!) ; // Add the mask coating to the managerCopy the code
// BackoverLayEntry = OverlayEntry(Builder: _backBuilder,);Copy the code
Here the Builder needs to pass in a render function, _backBuilder is a custom render function, tip:_ is private identifier.
Static Widget_backBuilder (BuildContext context){return new Opacity(Opacity: 0.3, child: MaterialApp( debugShowCheckedModeBanner: false, home: new Scaffold( body: new Container( color: Colors.black, ), ), ), ); }Copy the code
The UI, constraints and attributes here are basically componentization management. The so-called componentization management means that some features need to be set and the corresponding component or attribute value needs to be wrapped in the outermost layer to create a component for assignment.
For example: the gray mask needs a opacity to see through the page below, so the mobile side usually sets the opacity of the background color to 0.4 or the entire view to 0.4. The Opacity setting is used here, so the Opacity setting of the inner UI component is placed on the top layer of the Opacity setting.
So here we have the gray mask.
Similarly, create a prompt component based on the above code, also at the top of the screen.
static OverlayEntry? _overlayEntry;
Copy the code
static void alert({required BuildContext context,required dynamic block}) { OverlayState? overlayState = Overlay.of(context); tapBlock = block; If (_backOverlayEntry == null){// Did not create _backOverlayEntry = OverlayEntry(Builder: _backBuilder,); overlayState! .insert(_backOverlayEntry!) ; } else {// There is a refresh _backOverlayEntry! .markNeedsBuild(); } if (_overlayEntry == null) {// There was no creation _overlayEntry = OverlayEntry(Builder: _Builder,); overlayState! .insert(_overlayEntry!) ; } else {// There is a refresh _overlayEntry! .markNeedsBuild(); }}Copy the code
Question two, inside the pop-up box layout how to write?
Here directly on the code, interested in can read, code clumsy, master not spray.
import 'package:flutter/material.dart'; class AlertContentView extends StatefulWidget { dynamic? tapBlock; AlertContentViewState? _alertContentViewState; @override State<StatefulWidget> createState() { _alertContentViewState = new AlertContentViewState(); _alertContentViewState! .tapBlock = (isDone){ if(tapBlock ! = null){ tapBlock(isDone); }}; return _alertContentViewState! ; } } class AlertContentViewState extends State<AlertContentView> with TickerProviderStateMixin { dynamic? tapBlock; AnimationController? controller; Animation<double>? animation; CurvedAnimation? curve; double _addW = 0; @override void initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 100), vsync: this); curve = CurvedAnimation(parent: controller! , curve: Curves.fastOutSlowIn); Animation = Tween(begin: 1.0, end: 1.1). Animate (controller!) ; animation! .addListener(() { setState(() { }); }); controller! .forward(); Future.delayed(Duration(milliseconds: 100), () { controller! .reverse(); }); } @override void dispose() { controller! .dispose(); super.dispose(); } @override Widget? _alertContain; Widget build(BuildContext context) { return new ScaleTransition( scale: animation! , child: new Container( child: new Container( decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(8)),color: Colors.white), width: 280, height: 160, child: new Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[ new Container( margin: EdgeInsets.only(top: 8), //height: 20, color: Colors.white, child: new Row( mainAxisAlignment: MainAxisAlignment center, the children: "Widget > [new Text (" tip", style: new TextStyle (color: Colors. Black, fontSize: 18,fontWeight: FontWeight.bold,decoration: TextDecoration.none),) ], ), ), new Expanded( child: new Container( color: Color. white, child: new Center(child: new Text(' do YOU want to log in? ',style: new TextStyle(color: Color.fromARGB(255, 133, 133, 133),fontWeight: FontWeight.w500,fontSize: 15,decoration: TextDecoration. None),),),)), new Container(color: color. FromARGB (255,238, 238, 238,), height: 0.8, width: 180, ), new Container( margin: EdgeInsets.only(bottom: 0), decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(8)),color: Colors.white), height: 50, child: new Row( crossAxisAlignment: CrossAxisAlignment. Stretch, children: [/ / click components new GestureDetector (child: new Container (decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(8)),color: Colors.white), width:139, height: 45, child: The new Column (mainAxisAlignment: mainAxisAlignment center, children: < Widget > [new Text (' cancel ', style: new TextStyle( color: Color.fromARGB(255, 33, 33, 33), fontWeight: FontWeight.w500, fontSize: 15, decoration: TextDecoration.none) , ) ], ), ), onTap: (){ if(tapBlock != null){ tapBlock(false); } }, ), new Container( color: Color. FromARGB (255,238, 238,), height: 50, width: 0.8,), // Click on the new GestureDetector(child: new Container( decoration: BoxDecoration(borderRadius: BorderRadius.all(Radius.circular(8)),color: Colors.white), width:139, height: 45, child: new Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[new Text(' confirm ', style: new TextStyle(color: color. FromARGB (255, 33, 33, 33), fontWeight: FontWeight.w500, fontSize: 15, decoration: TextDecoration.none), ), ], ), ), onTap: (){ if(tapBlock != null){ tapBlock(true); } }, ) ], ), ) ], ), ), ), ); }}Copy the code
Tip: We added a popover animation to change the scale of the content component of the popover. Here is a brief explanation of the parameters.
When creating the animation control object, you need to pass the vsync parameter, so don’t forget to set the class as follows:
Void initState() {super.initState(); // The component initializes the State class inherited from the StatefulWidget type. controller = AnimationController( duration: const Duration(milliseconds: 100), vsync: this); curve = CurvedAnimation(parent: controller! , curve: Curves.fastOutSlowIn); Animation = Tween(begin: 1.0, end: 1.1). Animate (controller!) ; // Listen and redraw the UI. If you don't listen, you'll get an animation because you've added an animation component to the layout. .addListener(() {// Execute this method to trigger a UI redraw setState(() {}); }); // Start animation amplification animation controller! .forward(); Future.delayed(Duration(milliseconds: 100), () {// Start shrinking the controller animation backwards! .reverse(); }); }Copy the code
Super.dispose () @override void dispose() {controller! .dispose(); super.dispose(); }Copy the code
Click event callback:
dynamic? tapBlock;
Copy the code
Here we add a click event of type Dynamic to the class to call back the click event outward.
Tip: The difference between var and dynamic is that both of them are type inference identifiers. Dynamic can change the value type many times, and var is immutable once the initial assignment is confirmed.
Effect:
Question 3: How do I remove the current mask?
// Mask removes screen _overlayEntry! .remove(); // Set mask to null _overlayEntry = null; // The prompt box removes the screen _backOverlayEntry! .remove(); Backoverlayentry = null;Copy the code
Question 4: How to call?
Alertview. alert(context: context,block: If (isDone == true){if(context, MaterialPageRoute(Builder: (_) {return new Login(ValueKey(" Login ")); })); }});Copy the code
Author dish chicken a, above all the code pure hand, master do not spray, we learn from each other, individual right when summary. Everyone is welcome to correct. [hold][hold][hold]