{"id":307705,"date":"2020-07-30T09:00:24","date_gmt":"2020-07-30T09:00:24","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=307705"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=307705","title":{"rendered":"Flutter. RenderObject \u2014 \u0437\u0430\u043c\u0435\u0440\u044f\u0439 \u0438 \u0432\u043b\u0430\u0441\u0442\u0432\u0443\u0439"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/surfstudio\/blog\/513070\/\">\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u0410\u043d\u0434\u0440\u0438\u044f\u043d\u043e\u0432. \u042f Flutter-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 Surf. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 UI \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Flutter. \u041d\u043e \u0431\u044b\u0432\u0430\u044e\u0442 \u0441\u043b\u0443\u0447\u0430\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b \u0438 \u0442\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043a\u043e\u043f\u0430\u0442\u044c \u0432 \u0433\u043b\u0443\u0431\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/oc\/0l\/zx\/oc0lzxeieckovqqthsmonqavkma.png\"><br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h2>\u0412\u0432\u043e\u0434\u043d\u0430\u044f<\/h2>\n<p>  \u0418\u043c\u0435\u0435\u0442\u0441\u044f \u044d\u043a\u0440\u0430\u043d \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u043f\u043e\u043b\u0435\u0439. \u0418\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a 5, \u0442\u0430\u043a \u0438 30. \u041c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/zo\/43\/kz\/zo43kzoximrdsezekqdo9v1k_pg.png\"><\/p>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430<\/h2>\n<p>  <\/p>\n<ul>\n<li>\u041f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0434 \u043a\u043b\u0430\u0432\u0438\u0430\u0442\u0443\u0440\u043e\u0439 \u0431\u043b\u043e\u043a \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u00ab\u0414\u0430\u043b\u0435\u0435\u00bb \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u043f\u043e\u043b\u0435.<\/li>\n<li>\u041f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0444\u043e\u043a\u0443\u0441\u0430 \u043f\u043e\u0434\u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u043a \u0431\u043b\u043e\u043a\u0443 \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u00ab\u0414\u0430\u043b\u0435\u0435\u00bb.<\/li>\n<\/ul>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430<\/h2>\n<p>  \u0411\u043b\u043e\u043a \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435. \u041d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u043a\u0440\u043e\u043b\u043b \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/gn\/v8\/hz\/gnv8hz7edvxd38xtrl4j_fxfwb8.gif\"><\/p>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044e<\/h2>\n<p>  1.\u0412\u043e\u0437\u044c\u043c\u0451\u043c \u044d\u043a\u0440\u0430\u043d \u0438\u0437 20 \u043f\u043e\u043b\u0435\u0439.<\/p>\n<p>  \u041a\u043e\u0434:<\/p>\n<pre><code class=\"dart\">List&lt;String&gt; list = List.generate(20, (index) =&gt; index.toString());  @override Widget build(BuildContext context) {  return Scaffold(    body: SingleChildScrollView(      child: SafeArea(        child: Padding(          padding: const EdgeInsets.all(20),          child: Column(            children: &lt;Widget&gt;[              for (String value in list)                TextField(                  decoration: InputDecoration(labelText: value),                )            ],          ),        ),      ),    ),  ); } <\/code><\/pre>\n<p>  \u041f\u0440\u0438 \u0444\u043e\u043a\u0443\u0441\u0435 \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435 \u0432\u0438\u0434\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u0443:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/le\/fm\/je\/lefmjedjmvo5wl7n1ju6tpfs0bs.png\"><\/p>\n<p>  \u041f\u043e\u043b\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0432\u0438\u0434\u043d\u043e \u0438 \u0432\u0441\u0451 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n<p>  2. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0431\u043b\u043e\u043a \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/xg\/ow\/cc\/xgowcci9iqcb5_1dxl08q0pghoi.png\"><\/p>\n<p>  \u0414\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/Overlay-class.html\">Overlay<\/a>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0448\u043a\u0443 \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0438 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0451\u0440\u0442\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435 Stack. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0443 \u043d\u0430\u0441 \u043d\u0435\u0442 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044f\u043c\u0438 \u0438 \u0431\u043b\u043e\u043a\u043e\u043c \u00ab\u0414\u0430\u043b\u0435\u0435\u00bb.<\/p>\n<p>  \u0425\u043e\u0440\u043e\u0448\u0430\u044f <a href=\"https:\/\/medium.com\/saugo360\/https-medium-com-saugo360-flutter-using-overlay-to-display-floating-widgets-2e6d0e8decb9\">\u0441\u0442\u0430\u0442\u044c\u044f<\/a> \u043f\u0440\u043e Overlay.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e: Overlay \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u043f\u043e\u0432\u0435\u0440\u0445 \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/Stack-class.html\">\u0441\u0442\u0435\u043a<\/a> \u043d\u0430\u043b\u043e\u0436\u0435\u043d\u0438\u044f. <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/OverlayEntry-class.html\">OverlayEntry<\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u0435\u043c\u0443 Overlay.<\/p>\n<p>  \u041a\u043e\u0434:<\/p>\n<pre><code class=\"dart\">bool _isShow = false; OverlayEntry _overlayEntry;  KeyboardListener _keyboardListener;  @override void initState() {  SchedulerBinding.instance.addPostFrameCallback((_) {    _overlayEntry = OverlayEntry(builder: _buildOverlay);    Overlay.of(context).insert(_overlayEntry);    _keyboardListener = KeyboardListener()      ..addListener(onChange: _keyboardHandle);  });  super.initState(); }  @override void dispose() {  _keyboardListener.dispose();  _overlayEntry.remove();  super.dispose(); } Widget _buildOverlay(BuildContext context) {  return Stack(    children: &lt;Widget&gt;[      Positioned(        bottom: MediaQuery.of(context).viewInsets.bottom,        left: 0,        right: 0,        child: AnimatedOpacity(          duration: const Duration(milliseconds: 200),          opacity: _isShow ? 1.0 : 0.0,          child: NextBlock(            onPressed: () {},            isShow: _isShow,          ),        ),      ),    ],  ); void _keyboardHandle(bool isVisible) {  _isShow = isVisible;  _overlayEntry?.markNeedsBuild(); } <\/code><\/pre>\n<p>  3. \u041a\u0430\u043a \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u0431\u043b\u043e\u043a \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0435.<\/p>\n<h2>\u0418\u0434\u0435\u0438 \u043f\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044e<\/h2>\n<p>  1. \u0411\u0440\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u0438\u0437 ScrollController \u0438 \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0442\u044c \u0434\u043e \u043f\u043e\u043b\u044f.<br \/>  \u0420\u0430\u0437\u043c\u0435\u0440\u044b \u043f\u043e\u043b\u044f \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0435\u0441\u043b\u0438 \u043e\u043d\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0435, \u0442\u043e \u0441\u043a\u0440\u043e\u043b\u043b \u043a \u043d\u0435\u043c\u0443 \u0434\u0430\u0441\u0442 \u043d\u0435\u0442\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u0438 \u043d\u0435 \u0433\u0438\u0431\u043a\u0438\u043c.<\/p>\n<p>  2. \u0421\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u0432\u043d\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0443.<br \/>  \u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u0438\u0434\u0436\u0435\u0442\u0430\u043c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0432\u044b\u0441\u043e\u0442\u0443, \u0442\u043e\u0433\u0434\u0430, \u0437\u043d\u0430\u044f \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0438 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0432 \u0437\u043e\u043d\u0435 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438 \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 \u0432\u0438\u0434\u0436\u0435\u0442.<\/p>\n<p>  <b>\u041c\u0438\u043d\u0443\u0441\u044b<\/b>:<\/p>\n<ul>\n<li>\u041f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u0432\u043d\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0438 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0441\u0447\u0435\u0442\u0430\u0445, \u0447\u0442\u043e \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u043c\u0443 \u0434\u0438\u0437\u0430\u0439\u043d\u0443 \u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430.  <\/li>\n<li>\u041f\u0440\u0430\u0432\u043a\u0438 UI \u043f\u0440\u0438\u0432\u0435\u0434\u0443\u0442 \u043a \u043f\u0440\u0430\u0432\u043a\u0430\u043c \u0432 \u0440\u0430\u0441\u0447\u0451\u0442\u0430\u0445.<\/li>\n<\/ul>\n<p>  3. \u0411\u0440\u0430\u0442\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u043f\u043e\u043b\u044f \u0438 \u0431\u043b\u043e\u043a\u0430 \u00ab\u0414\u0430\u043b\u0435\u0435\u00bb \u0438 \u0434\u043e\u0441\u043a\u0440\u0430\u043b\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u0430 \u0440\u0430\u0437\u043d\u0438\u0446\u0443.<\/p>\n<p>  <b>\u041c\u0438\u043d\u0443\u0441<\/b> \u2014 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0442\u0430\u043a\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043d\u0435\u0442.<\/p>\n<p>  4. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0430.<\/p>\n<p>  \u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 <a href=\"https:\/\/habr.com\/ru\/company\/surfstudio\/blog\/501862\/\">\u0441\u0442\u0430\u0442\u044c\u0438<\/a>, Flutter \u0437\u043d\u0430\u0435\u0442, \u043a\u0430\u043a \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0441\u0432\u043e\u0438\u0445 \u043f\u043e\u0442\u043e\u043c\u043a\u043e\u0432 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u044d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0442\u0430\u0449\u0438\u0442\u044c. \u0417\u0430 \u0440\u0435\u043d\u0434\u0435\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 <a href=\"https:\/\/api.flutter.dev\/flutter\/rendering\/RenderObject-class.html\">RenderObject<\/a>, \u043a \u043d\u0435\u043c\u0443 \u0442\u043e \u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u0438\u043c\u0441\u044f. <a href=\"https:\/\/api.flutter.dev\/flutter\/rendering\/RenderBox-class.html\">RenderBox<\/a> \u0438\u043c\u0435\u0435\u0442 \u043f\u043e\u043b\u0435 size \u0441 \u0448\u0438\u0440\u0438\u043d\u043e\u0439 \u0438 \u0432\u044b\u0441\u043e\u0442\u043e\u0439 \u0432\u0438\u0434\u0436\u0435\u0442\u0430. \u041e\u043d\u0438 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0435 \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432: \u0431\u0443\u0434\u044c \u0442\u043e \u0441\u043f\u0438\u0441\u043a\u0438, \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f (\u0434\u0430\u0436\u0435 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0435) \u0438 \u0442.\u0434.<\/p>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c RenderBox \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437   <\/p>\n<pre><code class=\"dart\">context context.findRenderObject() as RenderBox<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e\u043b\u044f \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c GlobalKey.<\/p>\n<p>  <b>\u041c\u0438\u043d\u0443\u0441<\/b>:<\/p>\n<p>  GlobalKey \u043d\u0435 \u0441\u0430\u043c\u0430\u044f \u043b\u0435\u0433\u043a\u0430\u044f \u0448\u0442\u0443\u043a\u0430. \u0418 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0451 \u043b\u0443\u0447\u0448\u0435 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0436\u0435.<\/p>\n<p>  \u00ab\u0412\u0438\u0434\u0436\u0435\u0442\u044b \u0441 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442 \u0441\u0432\u043e\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u044c\u044f, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u044e\u0442\u0441\u044f \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0432 \u0434\u0440\u0443\u0433\u043e\u0435. \u0427\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0451 \u043f\u043e\u0434\u0434\u0435\u0440\u0435\u0432\u043e, \u0432\u0438\u0434\u0436\u0435\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0440\u0438\u0431\u044b\u0442\u044c \u0432 \u0441\u0432\u043e\u0451 \u043d\u043e\u0432\u043e\u0435 \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0432 \u0442\u043e\u043c \u0436\u0435 \u043a\u0430\u0434\u0440\u0435 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d \u0438\u0437 \u0441\u0442\u0430\u0440\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430.<\/p>\n<p>  \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0440\u043e\u0433\u0438 \u0432 \u043f\u043b\u0430\u043d\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u044b \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Key, ValueKey, ObjectKey \u0438\u043b\u0438 UniqueKey.<\/p>\n<p>  \u0412\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u0442\u0435 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0432\u0430 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0432 \u0434\u0435\u0440\u0435\u0432\u043e \u0441 \u043e\u0434\u043d\u0438\u043c \u0438 \u0442\u0435\u043c \u0436\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c. \u041f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u00bb. <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/GlobalKey-class.html\">\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a<\/a>.<\/p>\n<p>  \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0435\u0441\u043b\u0438 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 20 GlobalKey, \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u0442\u0440\u0430\u0448\u043d\u043e\u0433\u043e \u043d\u0435 \u0441\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u043d\u043e \u0440\u0430\u0437 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0442\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043f\u043e\u0438\u0441\u043a\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u0443\u0442\u044c.<\/p>\n<h2>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0431\u0435\u0437 GlobalKey<\/h2>\n<p>  \u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0430. \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u2014 \u043c\u043e\u0436\u0435\u043c \u043b\u0438 \u043c\u044b \u0432\u044b\u0442\u0430\u0449\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0438\u0437 RenderBox \u0438 \u0431\u0443\u0434\u0443\u0442 \u043b\u0438 \u044d\u0442\u043e \u0442\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b.<\/p>\n<p>  \u041a\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0433\u0438\u043f\u043e\u0442\u0435\u0437\u044b:<\/p>\n<pre><code class=\"dart\">FocusNode get focus =&gt; widget.focus;  @override  void initState() {    super.initState();    Future.delayed(const Duration(seconds: 1)).then((_) { \t\/\/ (1)      RenderBox rb = (focus.context.findRenderObject() as RenderBox); \/\/(3)      RenderBox parent = _getParent(rb); \/\/(4)      print('parent = ${parent.size.height}');    });  }  RenderBox _getParent(RenderBox rb) {    return rb.parent is RenderWrapper ? rb.parent : _getParent(rb.parent);  }  Widget build(BuildContext context) {    return Wrapper(      child: Container(        color: Colors.red,        width: double.infinity,        height: 100,        child: Center(          child: TextField(            focusNode: focus,          ),        ),      ),    ); }  \/\/(2) class Wrapper extends SingleChildRenderObjectWidget {  const Wrapper({    Key key,    Widget child,  }) : super(key: key, child: child);  @override  RenderWrapper createRenderObject(BuildContext context) {    return RenderWrapper();  } } class RenderWrapper extends RenderProxyBox {  RenderWrapper({    RenderBox child,  }) : super(child); } <\/code><\/pre>\n<p>  (1) \u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0443\u0436\u043d\u0430 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0430 \u0434\u043e \u043f\u043e\u043b\u044f, \u043d\u0430\u0434\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0435\u0440\u0435\u0437 FocusNode), \u043d\u0430\u0439\u0442\u0438 RenderBox \u0438 \u0432\u0437\u044f\u0442\u044c size. \u041d\u043e \u044d\u0442\u043e size \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0438 \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b \u0442\u0430\u043a\u0436\u0435 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Padding), \u043d\u0430\u0434\u043e \u0432\u0437\u044f\u0442\u044c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 RenderBox \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u043b\u0435 parent.<\/p>\n<p>  (2) \u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c \u043d\u0430\u0448 \u043a\u043b\u0430\u0441\u0441 RenderWrapper \u043e\u0442 <a href=\"https:\/\/api.flutter.dev\/flutter\/widgets\/SingleChildRenderObjectWidget-class.html\">SingleChildRenderObjectWidget<\/a> \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u043c <a href=\"https:\/\/api.flutter.dev\/flutter\/rendering\/RenderProxyBox-class.html\">RenderProxyBox<\/a> \u0434\u043b\u044f \u043d\u0435\u0433\u043e. RenderProxyBox \u0438\u043c\u0438\u0442\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044f \u0435\u0433\u043e \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0435 \u0434\u0435\u0440\u0435\u0432\u0430 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432.<br \/>  Flutter \u0441\u0430\u043c \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432 SingleChildRenderObjectWidget:<br \/>  Align, AnimatedSize, SizedBox, Opacity, Padding.<\/p>\n<p>  (3) \u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u043c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439 \u043f\u043e \u0434\u0435\u0440\u0435\u0432\u0443, \u043f\u043e\u043a\u0430 \u043d\u0435 \u0432\u0441\u0442\u0440\u0435\u0442\u0438\u043c RenderWrapper.<\/p>\n<p>  (4) \u0411\u0435\u0440\u0451\u043c parent.size.height \u2014 \u044d\u0442\u043e \u0432\u044b\u0434\u0430\u0441\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u0443\u044e \u0432\u044b\u0441\u043e\u0442\u0443. \u042d\u0442\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c.<\/p>\n<p>  \u0422\u0430\u043a \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435, \u043d\u0435\u043b\u044c\u0437\u044f.<\/p>\n<p>  <b>\u041d\u043e \u0443 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u043c\u0438\u043d\u0443\u0441\u044b<\/b>:<\/p>\n<ul>\n<li>\u0420\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u043e\u0431\u0445\u043e\u0434 \u0434\u0435\u0440\u0435\u0432\u0430 \u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u043d\u0430\u0440\u0432\u0451\u043c\u0441\u044f \u043d\u0430 \u043f\u0440\u0435\u0434\u043a\u0430 \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u0434\u043e\u0439\u0442\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 \u0438 \u0432\u0441\u0451. \u041a\u0430\u043a-\u0442\u043e \u043d\u0430 \u0442\u0435\u0441\u0442\u0430\u0445 \u044f \u043d\u0430\u0440\u0432\u0430\u043b\u0441\u044f \u043d\u0430 RenderView \u0438 \u0432\u0441\u0451 \u0443\u043f\u0430\u043b\u043e. \u041c\u043e\u0436\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u043a\u0430, \u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430.<\/li>\n<li>\u042d\u0442\u043e \u043d\u0435\u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u0435 \u0438 \u0432\u0441\u0451 \u0435\u0449\u0435 \u043d\u0435 \u0433\u0438\u0431\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 RenderObject<\/h2>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432\u044b\u043b\u0438\u043b\u0441\u044f \u043f\u0430\u043a\u0435\u0442 <a href=\"https:\/\/pub.dev\/packages\/render_metrics\">render_metrics<\/a> \u0438 \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>  <b>\u041b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u044b:<\/b><\/p>\n<p>  1. \u041e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0434\u0436\u0435\u0442 (\u043f\u043e\u0442\u043e\u043c\u043e\u043a \u043a\u043b\u0430\u0441\u0441\u0430 Widget) \u0432 <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/render\/render_metrics.dart\">RenderMetricsObject<\/a>. \u0412\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0432\u0438\u0434\u0436\u0435\u0442 \u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"dart\">RenderMetricsObject(  child: ..., ) <\/code><\/pre>\n<p>  2. \u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0444\u0440\u0435\u0439\u043c\u0430 \u043d\u0430\u043c \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0435\u0433\u043e \u043c\u0435\u0442\u0440\u0438\u043a\u0438. \u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u043b\u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0430 (\u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e\u0435 \u0438\u043b\u0438 \u0432 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0435), \u0442\u043e \u043f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043c\u0435\u0442\u0440\u0438\u043a \u0443\u0436\u0435 \u0431\u0443\u0434\u0443\u0442 \u043d\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435.<\/p>\n<p>  3. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/manager\/render_manager.dart\">RenderManager<\/a> \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043d\u043e \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c id \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u0430.<\/p>\n<pre><code class=\"dart\">RenderMetricsObject(  id: _text1Id,  manager: renderManager,  child: ... <\/code><\/pre>\n<p>  4. \u041c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u0431\u044d\u043a\u0438:<\/p>\n<ul>\n<li>onMount \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 RenderObject. \u0412 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 id (\u0438\u043b\u0438 null, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0434\u0430\u043d) \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 RenderMetricsBox.<\/li>\n<li>onUnMount \u2014 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437 \u0434\u0435\u0440\u0435\u0432\u0430.<\/li>\n<\/ul>\n<p>  \u0412 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 id, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0439 \u0432 RenderMetricsObject. \u042d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u0438\/\u0438\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u043a\u043e\u0433\u0434\u0430 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0438 \u0443\u0434\u0430\u043b\u0438\u043b\u0441\u044f RenderObject \u0438\u0437 \u0434\u0435\u0440\u0435\u0432\u0430.<\/p>\n<pre><code class=\"dart\">RenderMetricsObject(  id: _textBlockId,  onMount: (id, box) {},  onUnMount: (box) {},  child... ) <\/code><\/pre>\n<p>  5. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0440\u0438\u043a. \u041a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/render\/render_metrics.dart\">RenderMetricsBox<\/a> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0433\u0435\u0442\u0442\u0435\u0440 data, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0435\u0440\u0451\u0442 \u0441\u0432\u043e\u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0447\u0435\u0440\u0435\u0437 localToGlobal. localToGlobal \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u0442\u043e\u0447\u043a\u0443 \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e RenderBox \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0430 \u0432 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/kw\/ny\/ah\/kwnyah9mkq2ekzgyd8qpqi0h-6u.png\"><\/p>\n<p>  A \u2014 \u0448\u0438\u0440\u0438\u043d\u0430 width \u0432\u0438\u0434\u0436\u0435\u0442\u0430, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0441\u0430\u043c\u0443\u044e \u043f\u0440\u0430\u0432\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<p>  B \u2014 \u0432\u044b\u0441\u043e\u0442\u0430 height \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u0441\u0430\u043c\u0443\u044e \u043d\u0438\u0436\u043d\u044e\u044e \u0442\u043e\u0447\u043a\u0443 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<pre><code class=\"dart\">class RenderMetricsBox extends RenderProxyBox {  RenderData get data {    Size size = this.size;    double width = size.width;    double height = size.height;    Offset globalOffset = localToGlobal(Offset(width, height));    double dy = globalOffset.dy;    double dx = globalOffset.dx;     return RenderData(      yTop: dy - height,      yBottom: dy,      yCenter: dy - height \/ 2,      xLeft: dx - width,      xRight: dx,      xCenter: dx - width \/ 2,      width: width,      height: height,    );  }   RenderMetricsBox({    RenderBox child,  }) : super(child); } <\/code><\/pre>\n<p>  6. <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/data\/render_data.dart\">RenderData<\/a> \u2014 \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 x \u0438 y \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 double \u0438 \u0442\u043e\u0447\u043a\u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0432 \u0432\u0438\u0434\u0435 <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/data\/coords_metrics.dart\">CoordsMetrics<\/a>.<\/p>\n<p>  7. <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/data\/comparison_diff.dart\">ComparisonDiff<\/a> \u2014 \u043f\u0440\u0438 \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0438 \u0434\u0432\u0443\u0445 RenderData \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 ComparisonDiff \u0441 \u0440\u0430\u0437\u043d\u0438\u0446\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438. \u0422\u0430\u043a\u0436\u0435 \u043e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0433\u0435\u0442\u0442\u0435\u0440 (diffTopToBottom) \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043f\u043e\u0437\u0438\u0446\u0438\u0439 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u0436\u043d\u0438\u043c \u043a\u0440\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0438 \u0432\u0435\u0440\u0445\u043d\u0438\u043c \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442 (diffBottomToTop). diffLeftToRight \u0438 diffRightToLeft \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e.<\/p>\n<p>  8. <a href=\"https:\/\/github.com\/surfstudio\/render_metrics\/blob\/stable\/lib\/src\/manager\/render_parameters_manager.dart\">RenderParametersManager<\/a> \u2014 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a RenderManager. \u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0440\u0438\u043a \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u0438 \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438.<\/p>\n<p>  \u041a\u043e\u0434:<\/p>\n<pre><code class=\"dart\">class RenderMetricsScreen extends StatefulWidget {  @override  State&lt;StatefulWidget&gt; createState() =&gt; _RenderMetricsScreenState(); }  class _RenderMetricsScreenState extends State&lt;RenderMetricsScreen&gt; {  final List&lt;String&gt; list = List.generate(20, (index) =&gt; index.toString());  \/\/\/ \u041c\u0435\u043d\u0435\u0434\u0436\u0435\u0440 \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 render_metrics  \/\/\/ \u0434\u043b\u044f \u0437\u0430\u043c\u0435\u0440\u043e\u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435  final _renderParametersManager = RenderParametersManager();  final ScrollController scrollController = ScrollController();  \/\/\/ id \u0431\u043b\u043e\u043a\u0430 \u0441 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 &quot;\u0414\u0430\u043b\u0435\u0435&quot;  final doneBlockId = 'doneBlockId';  final List&lt;FocusNode&gt; focusNodes = [];   bool _isShow = false;  OverlayEntry _overlayEntry;  KeyboardListener _keyboardListener;  \/\/\/ \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 FocusNode, \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438 \u0441\u043c\u0435\u043d\u0435 \u0444\u043e\u043a\u0443\u0441\u0430  FocusNode lastFocusedNode;   @override  void initState() {    SchedulerBinding.instance.addPostFrameCallback((_) {      _overlayEntry = OverlayEntry(builder: _buildOverlay);      Overlay.of(context).insert(_overlayEntry);      _keyboardListener = KeyboardListener()        ..addListener(onChange: _keyboardHandle);    });     FocusNode node;     for(int i = 0; i &lt; list.length; i++) {      node = FocusNode(debugLabel: i.toString());      focusNodes.add(node);      node.addListener(_onChangeFocus(node));    }     super.initState();  }   @override  void dispose() {    _keyboardListener.dispose();    _overlayEntry.remove();    focusNodes.forEach((node) =&gt; node.dispose());    super.dispose();  }   @override  Widget build(BuildContext context) {    return Scaffold(      body: SingleChildScrollView(        controller: scrollController,        child: SafeArea(          child: Padding(            padding: const EdgeInsets.all(20),            child: Column(              children: &lt;Widget&gt;[                for (int i = 0; i &lt; list.length; i++)                  RenderMetricsObject(                    id: focusNodes[i],                    manager: _renderParametersManager,                    child: TextField(                      focusNode: focusNodes[i],                      decoration: InputDecoration(labelText: list[i]),                    ),                  ),              ],            ),          ),        ),      ),    );  }   Widget _buildOverlay(BuildContext context) {    return Stack(      children: &lt;Widget&gt;[        Positioned(          bottom: MediaQuery.of(context).viewInsets.bottom,          left: 0,          right: 0,          child: RenderMetricsObject(            id: doneBlockId,            manager: _renderParametersManager,            child: AnimatedOpacity(              duration: const Duration(milliseconds: 200),              opacity: _isShow ? 1.0 : 0.0,              child: NextBlock(                onPressed: () {},                isShow: _isShow,              ),            ),          ),        ),      ],    );  }   VoidCallback _onChangeFocus(FocusNode node) =&gt; () {    if (!node.hasFocus) return;    lastFocusedNode = node;    _doScrollIfNeeded();  };   \/\/\/ \u041c\u0435\u0442\u043e\u0434, \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0440\u0430\u0441\u0447\u0451\u0442\u0430 \u0441\u043a\u0440\u043e\u043b\u043b\u0430  \/\/\/ \u044d\u043a\u0440\u0430\u043d\u0430.  void _doScrollIfNeeded() async {    if (lastFocusedNode == null) return;    double scrollOffset;     try {      \/\/\/ \u0415\u0441\u043b\u0438 \u043d\u0435\u0442 \u043d\u0443\u0436\u043d\u043e\u0433\u043e id, \u0442\u043e data \u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u0432\u044b\u0437\u043e\u0432\u0435\u0442\u0441\u044f \u043d\u0430 null      scrollOffset = await _calculateScrollOffset();    } catch (e) {      return;    }     _doScroll(scrollOffset);  }   \/\/\/ \u0418\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u044d\u043a\u0440\u0430\u043d\u0430  void _doScroll(double scrollOffset) {    double offset = scrollController.offset + scrollOffset;    if (offset &lt; 0) offset = 0;    scrollController.position.animateTo(      offset,      duration: const Duration(milliseconds: 200),      curve: Curves.linear,    );  }   \/\/\/ \u0420\u0430\u0441\u0447\u0451\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u043a\u0440\u043e\u043b\u043b\u0430 \u044d\u043a\u0440\u0430\u043d\u0430.  \/\/\/  \/\/\/ \u0421\u043a\u0440\u043e\u043b\u043b \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0435\u0442 \u043f\u0440\u0438 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043e\u0442 \u043f\u043b\u0430\u0448\u043a\u0438 &quot;\u0413\u043e\u0442\u043e\u0432\u043e&quot; \u0432 \u043e\u0431\u0435  \/\/\/ \u0441\u0442\u043e\u0440\u043e\u043d\u044b (\u0432\u0432\u0435\u0440\u0445\/\u0432\u043d\u0438\u0437).  Future&lt;double&gt; _calculateScrollOffset() async {    await Future.delayed(const Duration(milliseconds: 300));     ComparisonDiff diff = _renderParametersManager.getDiffById(      lastFocusedNode,      doneBlockId,    );     lastFocusedNode = null;     if (diff == null || diff.firstData == null || diff.secondData == null) {      return 0.0;    }    return diff.diffBottomToTop;  }   void _keyboardHandle(bool isVisible) {    _isShow = isVisible;    _overlayEntry?.markNeedsBuild();  } } <\/code><\/pre>\n<h2>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c render_metrics<\/h2>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ex\/f6\/g6\/exf6g6gowsoxf_irp4f2ufxx8km.gif\"><\/p>\n<h2>\u0418\u0442\u043e\u0433<\/h2>\n<p>  \u041a\u043e\u043f\u043d\u0443\u0432 \u0433\u043b\u0443\u0431\u0436\u0435 \u0443\u0440\u043e\u0432\u043d\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0441\u043e \u0441\u043b\u043e\u0435\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 UI \u0438 \u043b\u043e\u0433\u0438\u043a\u0443. \u0418\u043d\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0437\u043d\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0438\u0445 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u0434\u0440\u0443\u0433 \u043d\u0430 \u0434\u0440\u0443\u0433\u0430 \u0432\u0438\u0434\u0436\u0435\u0442\u044b. \u0418 \u0434\u0430\u043d\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435 \u044d\u0442\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0438 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447. \u0412 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u043b\u0441\u044f \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0430\u0431\u043e\u0442\u044b, \u043f\u0440\u0438\u0432\u0451\u043b \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u041d\u0430\u0434\u0435\u044e\u0441\u044c \u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0441\u0442\u0430\u0442\u044c\u0438 \u0438 \u043d\u0430 \u0432\u0430\u0448\u0443 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c.<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/surfstudio\/blog\/513070\/\"> https:\/\/habr.com\/ru\/company\/surfstudio\/blog\/513070\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/company\/surfstudio\/blog\/513070\/\">\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u043c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u0410\u043d\u0434\u0440\u0438\u044f\u043d\u043e\u0432. \u042f Flutter-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 Surf. \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 UI \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Flutter. \u041d\u043e \u0431\u044b\u0432\u0430\u044e\u0442 \u0441\u043b\u0443\u0447\u0430\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043a\u0435\u0439\u0441\u044b \u0438 \u0442\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u043a\u043e\u043f\u0430\u0442\u044c \u0432 \u0433\u043b\u0443\u0431\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/oc\/0l\/zx\/oc0lzxeieckovqqthsmonqavkma.png\">  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-307705","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/307705","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=307705"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/307705\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=307705"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=307705"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=307705"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}