<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Umar khabiliy on Medium]]></title>
        <description><![CDATA[Stories by Umar khabiliy on Medium]]></description>
        <link>https://medium.com/@khabiliyshakhzod?source=rss-101f5f58dd6c------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*xkTHtNzjxvKtZgFm</url>
            <title>Stories by Umar khabiliy on Medium</title>
            <link>https://medium.com/@khabiliyshakhzod?source=rss-101f5f58dd6c------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 22 May 2026 07:01:16 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@khabiliyshakhzod/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Flutterda GesturDetectorda rasmni zoom va move qilish]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-gesturdetectorda-rasmni-zoom-va-move-qilish-bcdd283b662c?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/bcdd283b662c</guid>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Sun, 08 May 2022 16:53:27 GMT</pubDate>
            <atom:updated>2022-05-08T16:53:27.396Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rDfCJ7OT_nAyAYU3AAZ5Ig.png" /></figure><p>GestureDetector haqida avvalgi postlarda qisqacha tanishib chiqdik, o‘rgangan narsalarimizga qo’shimcha yana bazi bir kerakli qulayliklardan foydalanishni ham ko’rib chiqaylik. Ekranga bitta yoki multitouch(ko’pgina) teginish jestlaridan foydalangan holda widgetlarni scale (masshtablashtirishni) ko’rib chiqamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*qHoHxa082JVJGF75ws-2WA.gif" /></figure><p>GestureDetector haqida avvalgi postlarda qisqacha tanishib chiqdik, o‘rgangan narsalarimizga qo’shimcha yana bazi bir kerakli qulayliklardan foydalanishni ham ko’rib chiqaylik. Ekranga bitta yoki multitouch(ko’pgina) teginish jestlaridan foydalangan holda widgetlarni scale (masshtablashtirishni) ko’rib chiqamiz. Bu qulaylikdan asosan rasmlarni va google map (xarita) yaqinlashtirsh kichraytirish uchun ishlatiladi, misol uchun rasmni ikki marta ursa rasm masshatablashib kattalashadi va yana ikki marta ursa eski holatiga qaytadi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*DTydupcbQe8Ht36tiNETMA.gif" /></figure><p>Buning uchun GestureDetectorni onScaleStart va onScaleUpdate qulayligidan foydalanamiz. Ko’rib chiqadigan misolimizda masshtabni oshirish uchun onDoubleTap-dan foydalanamiz va default holatiga qaytarish uchun onLongPress-dan foydalanamiz.Foydalanuvchi rasmni bosganida jestlar orqali, rasmni joyini o’zgartirish yoki kattalashtirish/kichraytirish mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/576/1*8jBeSZlvCmw7ORQD4SjrqQ.png" /></figure><p>Shu kabi qulaylikdan foydalanish uchun esa Transform widgetidan foydalanamiz. Rasm hajmini o’zgartirish uchun Transform.scale konstruktoridan foydalanamiz va rasmni joyni o’zgartirish uchun Transform.translate konstruktoridan foydalanamiz. Transform.rotate : childga berilgan widgetni 360 darajada aylantirish uchun ishlatilinadi. Default holatda soat yo’nalishi bo’yicha aylanadi. Soat miliga teskari aylantirish uchun manfiy radianni berish kerak. Transform.scale : X o’qi va y o’qi bo’yicha childga berilgan widgetini teng ravishda masshtablashtiradigan konstruktor. 1.0 widgetning asl o’lchami hisoblanadi, 1.0 dan yuqori har qanday qiymatlar widgetni kattalashtiradi va 1.0 dan past qiymatlar widgetni kichraytiradi. 0.0 qiymati vidjetni ko’rinmas qiladi.Transform.translate: Translate yordamida childdagi widgetni ko‘chirish/joylashtirish uchun konstruktor hisoblanadi. Offset argumenti widgetni x va y o’qlarida joylashtirish uchun foydalanamiz, Offset(double dx, double dy) klassi orqali ishlaydi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/652/1*_GMDKz_rTmnckU5vmLSwtA.png" /><figcaption>GestureDetector widgeti onScaleStart, onScaleUpdate, onDoubleTap va onLongPress jestlarini tinglaydi.</figcaption></figure><p>Misolimizda qurilmaning toʻliq kengligini egalaydigan rasm koʻrsatadigan sahifani qilaylik. Rasmni bir teginish orqali siljitish va 2 multitouch yordamida kattalashtirish/kichraytirish mumkin bo’lsin. Ikki marta bosish rasmni kattalashtirish imkonini beradi va bir marta bosish ramsni joylashuvi va masshtablash darajasini default holatga qaytaradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/984/1*SzoT95uHPkrd3C4W4jA6pA.png" /></figure><p><em>_startLastOffset , _lastOffset</em> va <em>currentOffset </em>o’zgaruvchilari<em> </em><strong>Offset</strong><em> typeda </em>bo’lib rasmni joyini kuzatish uchun ishlatamiz<em>. _lastScale</em> va <em>_currentScale </em>o’zgaruvchilari <strong>double</strong> typeda bo’lib rasmni masshtabini kuzatish uchun ishlatamiz. Transform widgeti ikki xil yo’l bilan rasmni joyidan koʻchirish va oʻlchamini oshirishi mumkin. Birinchi usuli Transform.scale va Transform.translate-ni orqali ishlatish, ikkinchi usuli Matrix4 dan foydalangan holda Transform default konstruktoridan foydalanib. Ikkala usul ham bir xil natijani beradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j3nmpyk0oMpHx8h2LPq84A.png" /></figure><p>onScaleStart va onScaleUpdate siljitish va masshtablash jestlarini boshqarish uchun ishlatamiz. onDoubleTap masshtabni kattalashtirish uchun ikki marta bosishni boshqarish uchun ishlatamiz. onLongPress masshtabni default standart qiymatiga qaytarish uchun uzoq bosish jestini bajarish uchun foydalanamiz. <em>onScaleStart(ScaleStartDetails details) metodi rasmni joyini ko‘chirish yoki o‘lchamini oshirishni boshlaganda ishga tushadi. </em>_startLastOffset, <em>_lastOffset va </em>_lastScale o’zgaruvchilarini qiymatlarini o’zgartirib boradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k1O-bxdtooVfKxO43U5HfA.png" /><figcaption>Ushbu metodni tushuntirmaslikga qaror qildim sababi biroz o’zingiz harakat qilib ko’ring, agar qiynalsangiz izohlarda yozing tushuntirib berishga harakat qilaman.</figcaption></figure><p>Soddaroq qilib tushuntiradigan bo’lsak foydalanuvchi rasm masshatablashganini yoki joyi o’zgarganligini bilishni tekshirish uchun desak ham bo’ladi.</p><pre>class GestureScale extends StatefulWidget {<br>  const GestureScale({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  _GestureScaleState createState() =&gt; _GestureScaleState();<br>}</pre><pre>class _GestureScaleState extends State&lt;GestureScale&gt; {<br>  Offset _startLastOffset = Offset.zero;<br>  Offset _lastOffset = Offset.zero;<br>  Offset _currentOffset = Offset.zero;<br>  double _lastScale = 1.0;<br>  double _currentScale = 1.0;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: _buildBody(context),<br>    );<br>  }<br>}</pre><p>Ko’rib turganimizdek koddimizni sodaroq qilish uchun avval o’zgaruvchilarni kiritib olib so’ng asosiy widgetimizni alohida metodlarga bo’lib kodni soddalashtirishga harakat qilganmiz</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LnjQsDREPobptB-foPdHxw.png" /></figure><p>_transformScaleAndTranslate() va _transformMatrix4(), haqida yuqorida nima vazifalar qilishini yozib o’tkan edik, keling endi koddni o’zini ko’raylik. Widgetni ham masshatablashtirish hamda joyidan o’zgarganligi uchun. Ikkala metod ham bir hil vazifani bajaradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2FWIPbQqDuYw7W0SZjVz2g.png" /></figure><p>Ekarnda ma’lumotlarni ko’rib turish uchun esa ushbu widgetdan foydalanamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9C7MFI1oodotjw6b0sg-3Q.png" /></figure><p>Rasmni ikki marta urganda yaqainlashtirish uchun</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u8sbrGth-fnpVaRoz_6yyA.png" /></figure><p>Rasmni bosib turganda eski holatiga default holatga qaytish uchun esa</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DL3bAQRapFlfVCJy309o5g.png" /></figure><p>To’liq kod esa quydagi ko’rinishda</p><pre>class GestureScale extends StatefulWidget {<br>  const GestureScale({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  _GestureScaleState createState() =&gt; _GestureScaleState();<br>}</pre><pre>class _GestureScaleState extends State&lt;GestureScale&gt; {<br>  Offset _startLastOffset = Offset.zero;<br>  Offset _lastOffset = Offset.zero;<br>  Offset _currentOffset = Offset.zero;<br>  double _lastScale = 1.0;<br>  double _currentScale = 1.0;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: _buildBody(context),<br>    );<br>  }<br>  Widget _buildBody(BuildContext context) {<br>    return GestureDetector(<br>      child: Stack(<br>        fit: StackFit.expand,<br>        children: &lt;Widget&gt;[<br>          // _transformScaleAndTranslate(),<br>          _transformMatrix4(),<br>          _positionedStatusBar(context),<br>        ],<br>      ),<br>      onScaleStart: _onScaleStart,<br>      onScaleUpdate: _onScaleUpdate,<br>      onDoubleTap: _onDoubleTap,<br>      onLongPress: _onLongPress,<br>    );<br>  }</pre><pre>Transform _transformScaleAndTranslate() {<br>    return Transform.scale(<br>      scale: _currentScale,<br>      child: Transform.translate(<br>        offset: _currentOffset,<br>        child: const Image(<br>          image: AssetImage(&#39;images/elphant.jpg&#39;),<br>        ),<br>      ),<br>    );<br>  }</pre><pre>Transform _transformMatrix4() {<br>    return Transform(<br>      transform: Matrix4.identity()<br>        ..scale(_currentScale, _currentScale)<br>        ..translate(<br>          _currentOffset.dx,<br>          _currentOffset.dy,<br>        ),<br>      alignment: FractionalOffset.center,<br>      child: const Image(<br>        image: AssetImage(&#39;images/elphant.jpg&#39;),<br>      ),<br>    );<br>  }</pre><pre>Positioned _positionedStatusBar(BuildContext context) {<br>    return Positioned(<br>      top: 0.0,<br>      width: MediaQuery.of(context).size.width,<br>      child: Container(<br>        color: Colors.white54,<br>        height: 50.0,<br>        child: Row(<br>          mainAxisAlignment: MainAxisAlignment.spaceAround,<br>          children: &lt;Widget&gt;[<br>            Text(&#39;Scale: ${_currentScale.toStringAsFixed(4)}&#39;),<br>            Text(&#39;Current: $_currentOffset&#39;),<br>          ],<br>        ),<br>      ),<br>    );<br>  }</pre><pre>void _onScaleStart(ScaleStartDetails details) {<br>    print(&#39;ScaleStartDetails: $details&#39;);<br>    _startLastOffset = details.focalPoint;<br>    _lastOffset = _currentOffset;<br>    _lastScale = _currentScale;<br>  }</pre><pre>void _onScaleUpdate(ScaleUpdateDetails details) {<br>    print(&#39;ScaleUpdateDetails: $details - Scale: ${details.scale}&#39;);<br>    if (details.scale != 1.0) {<br>      double currentScale = _lastScale * details.scale;<br>      if (currentScale &lt; 0.5) {<br>        currentScale = 0.5;<br>      }<br>      setState(() {<br>        _currentScale = currentScale;<br>      });<br>      print(&#39;_scale: $_currentScale - _lastScale: $_lastScale&#39;);<br>    } else if (details.scale == 1.0) {<br>      Offset offsetAdjustedForScale =<br>          (_startLastOffset - _lastOffset) / _lastScale;<br>      Offset currentOffset =<br>          details.focalPoint - (offsetAdjustedForScale * _currentScale);<br>      setState(() {<br>        _currentOffset = currentOffset;<br>      });<br>      print(<br>          &#39;offsetAdjustedForScale: $offsetAdjustedForScale - _currentOffset: $_currentOffset&#39;);<br>    }<br>  }</pre><pre>void _onDoubleTap() {<br>    print(&#39;onDoubleTap&#39;);<br>    double currentScale = _lastScale * 2.0;<br>    if (currentScale &gt; 16.0) {<br>      currentScale = 1.0;<br>      _resetToDefaultValues();<br>    }<br>    _lastScale = currentScale;<br>    setState(() {<br>      _currentScale = currentScale;<br>    });<br>  }</pre><pre>void _onLongPress() {<br>    print(&#39;onLongPress&#39;);<br>    setState(() {<br>      _resetToDefaultValues();<br>    });<br>  }</pre><pre>void _resetToDefaultValues() {<br>    _startLastOffset = Offset.zero;<br>    _lastOffset = Offset.zero;<br>    _currentOffset = Offset.zero;<br>    _lastScale = 1.0;<br>    _currentScale = 1.0;<br>  }</pre><pre>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gYERIIRMGiFcmwrBc_tzeA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/401/1*fH2_et6iFRFmGvgC3dPFtQ.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bcdd283b662c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda Draggable va DragTarget]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-draggable-va-dragtarget-5b3825618db3?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/5b3825618db3</guid>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Wed, 04 May 2022 17:45:04 GMT</pubDate>
            <atom:updated>2022-05-04T17:45:04.137Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zfPUj1LGppiiklngfzTD7Q.png" /></figure><p>Flutterda obyektni bir joydan ikkinchi joyga olib o’tish uchun bir necha yo’llari bor, shulardan biri Draggable widgetini DragTarget widgetiga qo’yish. Har qanday maxsus maʼlumotlarni uzatish uchun data xususiyatidan foydalanamiz va ma’lumotimizni Icon widgeti kabi koʻrsatish uchun child xususiyatidan foydalanamiz. ChildWhenDragging xususiyatini dragg (surmoq) qilinayotgan paytda widgetni ko‘rsatish uchun ishlatiladi. Widget tortilayotgan joyda foydalanuvchiga qayerga qo’yish kerakligi haqidagi vizual ma’lumotni ko’rsatib turish uchun feedback xususiyatidan foydalanamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/607/1*LYK3b_pxv-fZrJOsB_VrSw.png" /></figure><p>Foydalanuvchi barmog’ini DragTarget tepasiga ko’targandan so’ng, target datalarni qabul qilishi mumkin. Ma’lumotni qabul qilishni rad etish uchun foydalanuvchi qo’lni uzmasdan DragTarget-dan uzoqlashsa yetarli. Harkat o’qini boshqarish uchun Draggable axis xususiyatini o’rnatish kifoya qiladi. Buning uchun Axis.vertical yoki Axis.horizontal ga o’zgartirsak yetarli.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PDl0g-pOBWTNZlhrAMNBHA.png" /></figure><p>DragTarget widgeti Draggable widgetini tinglaydi va agar to’g’ri qo’yilgan bo’lsa, ma’lumotlarni oladi. DragTarget builder xususiyati uchta parametrni qabul qiladi: BuildContext , List&lt;dynamic&gt; acceptedData va List&lt;dynamic&gt; rejectedData. Qabul qilingan ma’lumotlar bu Draggable widgetidan uzatiladigan ma’lumotlar bo’lib, u Listni valuesini kutadi. RejectedData qabul qilinmagan ma’lumotlar ro’yxatini o’z ichiga oladi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/1*D1PiCt9inwoJukLgDBjVig.gif" /></figure><p>Ushbu postmizni misolida avvalgi postda qilgan ilovaga qo’shimchalar qo’shib to’ldirib ketamiz. Bu safar yana ikkita widget yaratib uni misolimizga qo’shib qo’yamiz: dragg qilinadigan icon widgeti va ma’lumotlarni qabul qiladigan Text widgeti bo’lsin. Text widgeti ma’lumotlarni qabul qilganda, u rangini och kulrangdan, olov rangga o’zgartiradi, faqat drag qo’yilgan bo’lsa.</p><pre>Draggable&lt;int&gt; _buildDraggable() {<br>    return Draggable(<br>      child: Column(<br>        children: const &lt;Widget&gt;[<br>          Icon(<br>            Icons.palette,<br>            color: Colors.deepOrange,<br>            size: 48.0,<br>          ),<br>          Text(<br>            &#39;Drag Me below to change color&#39;,<br>          ),<br>        ],<br>      ),<br>      childWhenDragging: const Icon(<br>        Icons.palette,<br>        color: Colors.grey,<br>        size: 48.0,<br>      ),<br>      feedback: const Icon(<br>        Icons.brush,<br>        color: Colors.deepOrange,<br>        size: 80.0,<br>      ),<br>      data: Colors.deepOrange.value,<br>    );<br>  }</pre><p>Misolda DragTarget uning ustida Draggable mavjudligini tekshiradi. Agar yo’q bo’lsa, default holatda “Drag To and see the color change” degan xabar text bo’ladi. Agar Draggable uning ustida bo’lsa va ma’lumotlar qiymatiga ega bo’lsa, ma’lumotlarni ko’ramiz.</p><pre>DragTarget&lt;int&gt; _buildDragTarget() {<br>    return DragTarget&lt;int&gt;(<br>      onAccept: (colorValue) {<br>        _paintedColor = Color(colorValue);<br>      },<br>      builder: (BuildContext context, List&lt;dynamic&gt; acceptedData,<br>              List&lt;dynamic&gt; rejectedData) =&gt;<br>          acceptedData.isEmpty<br>              ? Text(<br>                  &#39;Drag To and see color change&#39;,<br>                  style: TextStyle(color: _paintedColor),<br>                )<br>              : Text(<br>                  &#39;Painting Color: $acceptedData&#39;,<br>                  style: TextStyle(<br>                    color: Color(acceptedData[0]),<br>                    fontWeight: FontWeight.bold,<br>                  ),<br>                ),<br>    );<br>  }</pre><p>Ma’lumotlarni qabul qilish uchun DragTargetni onAccept qulayligidan foydalanamiz Color typeda _paintedColor o’zgaruvchisni kiritib olamiz.</p><pre>class GesturSimple extends StatefulWidget {<br>  const GesturSimple({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  State&lt;GesturSimple&gt; createState() =&gt; _GesturSimpleState();<br>}</pre><pre>class _GesturSimpleState extends State&lt;GesturSimple&gt; {<br>  String _gestureDetected = &quot; &quot;;<br>  Color? _paintedColor;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: SafeArea(<br>        child: SingleChildScrollView(<br>          child: Column(<br>            children: &lt;Widget&gt;[<br>              _buildGestureDetector(),<br>              const Divider(color: Colors.black, height: 44.0),<br>              _buildDraggable(),<br>              const Divider(height: 40.0),<br>              _buildDragTarget(),<br>              const Divider(color: Colors.black),<br>            ],<br>          ),<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/374/1*l_NuByrUxi8p4odMJYKlNg.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5b3825618db3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda GesturDetector Widgeti]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-gesturdetector-widgeti-5642052604ad?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/5642052604ad</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Tue, 03 May 2022 19:50:12 GMT</pubDate>
            <atom:updated>2022-05-03T19:50:12.069Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-uUAd1i7H0-akMlZzswRqg.png" /></figure><p>Ushbu postlardan boshlab jestlar(qo’lni harakatlari) orqali mobil ilovamizga interaktivlikni qo’shishni ko’rib chiqamiz. Mobil ilovada jestlar foydalanuvchi bilan dasturni aloqalarini yuragi hisoblanadi jestlar bo’lmasa ilovamiz shunchaki ko’rinishdan boshqa narsa bo’lmaydi, yani bir sahifadan sahifaga o’ta olmaymiz yoki scroll qila olmaymiz va yana bir qancha qulayliklardan foydalana olmaymiz. Kerakli joyga kerakli jestlar qo’shish dasturmizni yaxshi UXga ega dastur qiladi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*gm3EDNU18zjC0IAKXlhgWQ.jpeg" /><figcaption>Shu kabi obyektni bosib turganda biror o’zgarishlarni qila olish uchun ham jestlardan foydalanamiz</figcaption></figure><p>GestureDetector widgeti tap, double tap, long press, pan, vertical drag, horizontal drag va scale kabi jestlarni o’zida ishlata oladi. Child propertysi optional (ixtiyoriy) hisoblanadi, agar child propertysiga widget bersak jestlar berilgan widget uchun tegishli bo’lib qoladi. Agar child qulayligiga bermasak u yuqorisidagi parent widgetga tegishli bo’ladi. Ilovada bir vaqtning o’zida vertikal va gorizontal jestlardan foydalanish kerak bo’lsa, pan qulayligidan foydalanamiz. Agar bitta yo’nalish bo’yicha bo’lsa, vertikal drag yoki horizontal drag foydalanishimiz mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/724/1*KKEklQSXa3_Ff-mMIZrk0Q.png" /></figure><p>Agar bir vaqtning o’zida vertikal drag, horizontal drag va <strong>pan</strong> jestlaridan foydalanmoqchi bo’lsak, Incorrect GestureDetector Arguments error(xatosi)ni olamiz. Biroq, pan jestini vertikal yoki horizontal dragdan biridan foydalansak, hech qanday xatolik olmaymiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*eBnEa8XR1c564SIABCPgXg.gif" /></figure><p>Agar bir vaqtning o’zida vertikal drag, horizontal drag va <strong>scale</strong> jestlaridan foydalanmoqchi bo’lsak ham, xuddi yuqoridagidek xatolikni olamiz. Biroq, agar scaleni yuqoridagidek ikklasidan bittasidan foydalansak, vertikal yoki horizontal dragdan hech qanday xatolik olmaymiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D_71kBBqA0ick22ii_VcuQ.png" /><figcaption>GesturDetectorni bir qancha qulayliklari bor kelajakdagi satrlarda har biriga to’xtash niyatimiz bor.</figcaption></figure><p>Endi misol ko’rib chiqaylik, ekranda bir qancha harakatlar qilib onHorizontalDragEnd qulayligan foydalanib, DragEndDetails orqali obyekt haqida tafsilotlarni olishga harakat qilib ko’raylik. <strong>details.primaryVelocity </strong>orqali foydalanuvchi obyektni qaysi o’q bo’yicha harakatlantiryotganini ko’rib olamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xPn4xgFLB3AsU0mvZ9HxuA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/966/1*yxRLONkbWqL8QvU5xrEGpQ.png" /><figcaption>Shu ko’rinishda o’zgariv boradi.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*SbwSbHgWVCBF4Jn9ha8LkA.png" /></figure><pre>class GesturSimple extends StatefulWidget {<br>  const GesturSimple({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  State&lt;GesturSimple&gt; createState() =&gt; _GesturSimpleState();<br>}</pre><pre>class _GesturSimpleState extends State&lt;GesturSimple&gt; {<br>  String _gestureDetected = &quot; &quot;;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: SafeArea(<br>        child: SingleChildScrollView(<br>          child: Column(<br>            children: &lt;Widget&gt;[<br>              _buildGestureDetector(),<br>              const Divider(color: Colors.black, height: 44.0),<br>            ],<br>          ),<br>        ),<br>      ),<br>    );<br>  }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/592/1*jEGw6BV28I3y4ds-EU1Vlw.png" /></figure><pre>GestureDetector _buildGestureDetector() {<br>    return GestureDetector(<br>      child: Container(<br>        color: Colors.lightGreen.shade100,<br>        width: double.infinity,<br>        padding: const EdgeInsets.all(24.0),<br>        child: Column(<br>          children: &lt;Widget&gt;[<br>            const Icon(Icons.access_alarm, size: 98.0),<br>            Text(_gestureDetected),<br>          ],<br>        ),<br>      ),<br>      onTap: () {<br>        debugPrint(&#39;onTap&#39;);<br>        _displayGestureDetected(&#39;onTap&#39;);<br>      },<br>      onDoubleTap: () {<br>        debugPrint(&#39;onDoubleTap&#39;);<br>        _displayGestureDetected(&#39;onDoubleTap&#39;);<br>      },<br>      onLongPress: () {<br>        debugPrint(&#39;onLongPress&#39;);<br>        _displayGestureDetected(&#39;onLongPress&#39;);<br>      },<br>      // onPanUpdate: (DragUpdateDetails details) {<br>      //   debugPrint(&#39;onPanUpdate: $details&#39;);<br>      //   _displayGestureDetected(&#39;onPanUpdate:\n$details&#39;);<br>      // },</pre><pre>onVerticalDragUpdate: (DragUpdateDetails details) {<br>        print(&#39;onVerticalDragUpdate: $details&#39;);<br>        _displayGestureDetected(&#39;onVerticalDragUpdate:\n$details&#39;);<br>      },<br>      onHorizontalDragUpdate: (DragUpdateDetails details) {<br>        print(&#39;onHorizontalDragUpdate: $details&#39;);<br>        _displayGestureDetected(&#39;onHorizontalDragUpdate:\n$details&#39;);<br>      },<br>      onHorizontalDragEnd: (DragEndDetails details) {<br>        print(&#39;onHorizontalDragEnd: $details&#39;);<br>        if (details.primaryVelocity! &lt; 0) {<br>          print(&#39;Dragging Right to Left: ${details.velocity}&#39;);<br>        } else if (details.primaryVelocity! &gt; 0) {<br>          print(&#39;Dragging Left to Right: ${details.velocity}&#39;);<br>        }<br>      },<br>    );<br>  }</pre><pre>void _displayGestureDetected(String gesture) {<br>    setState(() {<br>      _gestureDetected = gesture;<br>    });<br>  }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/347/1*DiQvVlxKXznE2ZKv8UBzEA.gif" /><figcaption>onHorizontalDragUpdate va onVerticalDragUpdate</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/358/1*D8Qg6tskCxiIIMpZ0vsaug.gif" /><figcaption>onPanUpdate</figcaption></figure><p>Keyini misolarda Draggable va Dragtarget haqida qisqacha tanishib chiqamiz.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5642052604ad" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda widgetlarni to’g’ri joylash va Layout bilan ishlash]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-widgetlarni-tog-ri-joylash-va-layout-bilan-ishlash-daf84b361a06?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/daf84b361a06</guid>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Sun, 03 Apr 2022 13:02:05 GMT</pubDate>
            <atom:updated>2022-04-03T13:02:05.304Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NufcYVhdfzmRhpIJwhNxJA.png" /></figure><p>Ushbu postlarimizda widgetlarni bir-biri bilan bog’lashni professional tarzda o’rganamiz. Ushbu ko’rinish kompozitsiya deb ham ataladi bu Flutterda mobil ilovalarini yaratishni katta qismi hisoblanadi. Odatada vertikal yoki gorizontal vidjetlardan foydalanib yoki ikkalasining kombinatsiyasidan foydalangan holda oddiy yoki murakkab UI yaratamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/1*bzDHWYs4N0SKiLHcdCNdGA.png" /></figure><p>Ushbu misolimizda sahifani ko’rinishini to’g’ri yig’ishga harakat qilib ko’ramiz. UIga muvofiq, UIni poydevorni tashkil etuvchi ketma-ketliklani qismlarini ajratamiz. Mobil qurilmalar turli o’lchamlarda bo’lganligi uchun, SingleChildScrollView foydalanamiz sababi widgetlarimiz ekranimizga sig’may qolsa scroll qilinganida ko’rinishi uchun.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_oUvBivCWmrvgQMprdy0VA.png" /></figure><p>Widgetlarmiz usun shaklda tushishi uchun Column widgetidan foydalanamiz. Columni birinchi widgeti sovga rasmi bo’lgani uchun Image widgetidan foydalanamiz. Textlarmiz widgetlarimiz hoshiyalardan olib qochish uchun SafeArea widgetidan foydalanamiz. Shu tarzda rasmda ko’rsatilgan widgetlarni taxlab chiqamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/796/1*Nxiet8BGi6BWG_nxo8A1zw.png" /></figure><p>Ob havoni ko’rsatib turgan qismini qilish uchun. Row widgetidan foydalanib uni ichini yana to’g’ri widgetlar bilan to’ldirib boramiz. Ikkita Column widgeti va SizedBox widgetini qo’shamiz. Rowni ichidagi birinchi columnda ob-havoni belgisini ko’rsatamiz. Ikkinchi Columnda ikkita Row widgetini qo’shamiz. Birinchi rowda ob-havo harorati va ma’lumotlari ko’rsatiladi. Ikkinchi Rowda ma’nzil ko’rsatiladi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/965/1*8w3Nkz3ZGVADQv5vYL-AWw.png" /></figure><p>Teg widgetlaridan odatda kategoriyalarga bo’lishda yoki ko’p qidirilarigan ma’lumotlarni qidirishni osonlashtirish uchun foydalaniladi. Flutterda teg widgetlari Chip widgeti hisoblanadi, label propertysi required hisoblanadi. Unga odatda Icon yoki Image widgeti beriladi. Default holatida Chip widgeti kulrang borderli ko’rinishda bo’ladi. Chipni shape xususiyati va backgroundColor xususiyatidan foydalanib uni o’zgartirishimiz mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/943/1*R-fcFvRLX1Aano2vm8G9Lw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nDGcTJ1HV1z9lOQ3v6rXJQ.png" /></figure><p>Ushbu loyihada teglarimiz ko’p bo’lgani tufayli uni Wrap widgetini childreniga beramiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/658/1*CxVIFEzwWXHqh09Gtyzyhw.png" /></figure><p>Wrap widgetni qulayligi agar bizda turli uzunlikda yoki nomaʼlum sonli elementlar roʻyxati boʻlsa, ularni Wrap widgetida ishlatish juda qulay hisoblanadi u joyni qurmalaning ekraniga qarab avotmatik tarzada to’lib keyingi qatorga tushib ketaveradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/963/1*M5PUrvCli_U2fIfHGaAo_Q.png" /></figure><p>UI ohirgi yani footer qismida yana Row widgetidan foydalanamiz, uni ichiga esa CircleAvatar widgetini joylashtiramiz va ohiridagi Iconlar uchun esa yana Column widgetidan foydalanamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9cpTYR6DhTQkbXC3ytWcSA.png" /></figure><p>Bizning misolimizda asosiy qism SingleChildScrollView-ni o’z ichiga oladi, va childiga Columni oladi. So’ng ketma-ketlikda Image, SafeArea, Padding widgetlarni joylashtirib boramiz. Har bir qismni alohida ajratib olamiz masalan _buildJournalHeaderImage(), _buildJournalEntry(), _buildJournalWeather(), _buildJournalTags() va _buildJournalFooterImages().</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/812/1*X1DZdD67t6ybVQhe3NeJuQ.png" /></figure><p>Misolda widget daraxtini ichma-ich qilib qiyinlashtirmaslik uchun widget klasslar o‘rniga metodlardan foydalanamiz. UI maqsadi tafsilotlarni ko’rishdir va u page o’zgarishlar talab qilinmaydi, shuning uchun siz widget daraxtini qurishda metodlardan foydalansak bo’ladi. Ammo agar sahifa tashqi maʼlumotlar oʻzgarishlari asosida ekranni yangilab tursa, u holda widjet klasslardan foydalanish yaxshi yechim hisoblanishi mumkin, chunki bunda ekranning faqat oʻzgargan qismi boshqata chizadi.</p><pre>Widget _buildBody() {<br>    return SingleChildScrollView(<br>      child: Column(<br>        children: &lt;Widget&gt;[<br>          _buildJournalHeaderImage(),<br>          SafeArea(<br>            child: Padding(<br>              padding: EdgeInsets.all(16.0),<br>              child: Column(<br>                crossAxisAlignment: CrossAxisAlignment.start,<br>                children: &lt;Widget&gt;[<br>                  _buildJournalEntry(),<br>                  const Divider(),<br>                  _buildJournalWeather(),<br>                  const Divider(),<br>                  _buildJournalTags(),<br>                  const Divider(),<br>                  _buildJournalFooterImages(),<br>                ],<br>              ),<br>            ),<br>          ),<br>        ],<br>      ),<br>    );<br>  }</pre><pre>Image _buildJournalHeaderImage() {<br>    return const Image(<br>      image: AssetImage(&#39;assets/images/present.jpg&#39;),<br>      fit: BoxFit.cover,<br>    );<br>  }</pre><pre>Column _buildJournalEntry() {<br>    return Column(<br>      crossAxisAlignment: CrossAxisAlignment.start,<br>      children: const &lt;Widget&gt;[<br>        Text(<br>          &#39;My Birthday&#39;,<br>          style: TextStyle(<br>            fontSize: 32.0,<br>            fontWeight: FontWeight.bold,<br>          ),<br>        ),<br>        Divider(),<br>        Text(<br>          &quot;It s going to be a great birthday. We are going out for dinner at myfavorite place, then watch a movie after we go to the gelateria for ice cream and espresso &quot;,<br>          style: TextStyle(color: Colors.black54),<br>        ),<br>      ],<br>    );<br>  }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1002/1*MPHKrXWPuxocgcx-VXWzzA.png" /></figure><pre>Row _buildJournalWeather() {<br>    return Row(<br>      crossAxisAlignment: CrossAxisAlignment.start,<br>      children: &lt;Widget&gt;[<br>        Column(<br>          crossAxisAlignment: CrossAxisAlignment.start,<br>          children: const &lt;Widget&gt;[<br>            Icon(<br>              Icons.wb_sunny,<br>              color: Colors.orange,<br>            ),<br>          ],<br>        ),<br>        const SizedBox(<br>          width: 16.0,<br>        ),<br>        Column(<br>          crossAxisAlignment: CrossAxisAlignment.start,<br>          children: &lt;Widget&gt;[<br>            Row(<br>              children: const &lt;Widget&gt;[<br>                Text(<br>                  &#39;81o Clear&#39;,<br>                  style: TextStyle(color: Colors.deepOrange),<br>                ),<br>              ],<br>            ),<br>            Row(<br>              children: const &lt;Widget&gt;[<br>                Text(<br>                  &#39;4500 San Alpho Drive, Dallas, TX United States&#39;,<br>                  style: TextStyle(color: Colors.grey),<br>                ),<br>              ],<br>            ),<br>          ],<br>        ),<br>      ],<br>    );<br>  }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/975/1*x2zIAs_EK3_YCBOHDB85pQ.png" /></figure><pre>Wrap _buildJournalTags() {<br>    return Wrap(<br>      spacing: 8.0,<br>      children: List.generate(7, (int index) {<br>        return Chip(<br>          label: Text(<br>            &#39;Gift ${index + 1}&#39;,<br>            style: const TextStyle(fontSize: 10.0),<br>          ),<br>          avatar: Icon(<br>            Icons.card_giftcard,<br>            color: Colors.blue.shade300,<br>          ),<br>          shape: RoundedRectangleBorder(<br>            borderRadius: BorderRadius.circular(4.0),<br>            side: const BorderSide(color: Colors.grey),<br>          ),<br>          backgroundColor: Colors.grey.shade100,<br>        );<br>      }),<br>    );<br>  }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/985/1*haOlkONMadunHANhrm4EMQ.png" /></figure><pre>Row _buildJournalFooterImages() {<br>    return Row(<br>      mainAxisAlignment: MainAxisAlignment.spaceBetween,<br>      crossAxisAlignment: CrossAxisAlignment.start,<br>      children: &lt;Widget&gt;[<br>        const CircleAvatar(<br>          backgroundImage: AssetImage(&#39;assets/images/salmon.jpg&#39;),<br>          radius: 40.0,<br>        ),<br>        const CircleAvatar(<br>          backgroundImage: AssetImage(&#39;assets/images/asparagus.jpg&#39;),<br>          radius: 40.0,<br>        ),<br>        const CircleAvatar(<br>          backgroundImage: AssetImage(&#39;assets/images/strawberries.jpg&#39;),<br>          radius: 40.0,<br>        ),<br>        SizedBox(<br>          width: 100.0,<br>          child: Column(<br>            crossAxisAlignment: CrossAxisAlignment.end,<br>            children: const &lt;Widget&gt;[<br>              Icon(Icons.cake),<br>              Icon(Icons.star_border),<br>              Icon(Icons.music_note),<br>//Icon(Icons.movie),<br>            ],<br>          ),<br>        ),<br>      ],<br>    );<br>  }</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MDKzNb8YlMTLvY2KGwpz9A.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=daf84b361a06" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda Sliverlar va CustomScrollView widgeti bilan ishlash]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-sliverlar-va-customscrollview-widgeti-bilan-ishlash-cc45c76a1e46?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/cc45c76a1e46</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Sat, 19 Mar 2022 16:58:07 GMT</pubDate>
            <atom:updated>2022-03-19T16:58:07.308Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JGRcg34D5pRitqLkQNTx5w.png" /></figure><p>CustomScrollView widgeti listlardan tashkil topgan widgetlardan foydalanib ListView ga o’xshash scroll imkoniyatini beradi faqat unda ko’proq qulaylik va effektlar bor. Sliver — bu dasutirmizning bizaga kerak bo’lgan qismga scroll effektini beradigan qulayliklar to’plami. Oldingi postlarimizda ListView va GridView widgetlarini alohida alohida ishlatgan edik. Endi savol tug’iladi ularni bitta listda ishtishimiz kerak bo’lsa-chi?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*2ImbddaUrW54KpmFpx7vbQ.gif" /></figure><p>Buning javobi esa, CustomScrollView widgetinig slivers propertysidan foydalangan holda qilishimiz mumkin. U o’zida SliverSafeArea, SliverAppBar, SliverList va SliverGrid widgetlarini ishlata oladi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VpagAIhXAJMjzA-7RfM3YA.png" /></figure><p>SliverList va SliverGrid sliverlari children widgetlarini ikki hil usulda yaratadi biri explicit ikkinchisi lazily. Explicitda listda avval barcha elementlarni tuzib olinadi, keyin ekranda ko’rinadi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-Ma-7M2oU90o1U_IxUDIRA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lJf4j5fu9JzLqjAdaksX6w.png" /></figure><p>Lazily da esa faqat ekranda ko’rinagan elementlarni yaratadi va foydalanuvchi scroll qilsa qolgan elementlar tuziladi, natijada performance yaxshilanadi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QXSnG3LQG9UHPyLrmmJLBQ.png" /></figure><pre>SliverGrid(<br>   delegate: SliverChildBuilderDelegate((<br>              BuildContext context,<br>              int index,<br>            ) {<br>            return const Card();<br>           }, <br>    childCount: _rowsCount),<br>   gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(<br>                crossAxisCount: 3)),</pre><p>SliverList delegate propertysiga ega, SliverGrid ham delegate va gridDelegate propertysiga ega. SliverList va SliverGrid delegate propertysi explicit listlarni yaratish uchun SliverChildListDelegate dan foydalanadi, lazily listlarni yaratish uchun SliverChildBuilderDelegate-dan foydalanamiz. SliverGrid qo’shimcha gridDelegate xususiyati plitkalarni o’lchami va joylashishiga masul bo’ladi. Belgilangan miqdorda plitkalarni yaratish uchun SliverGridDelegateWithFixedCrossAxisCount klassini gridDelegate propertysiga beramiz; SliverGridDelegateWithMaxCrossAxisExtent klassi esa GridView.extent qoidasi bilan bir xil.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3EZ5FYedf5juF6vFSo7ULg.png" /></figure><p>SliverAppBar widgeti expandedHeight va flexibleSpace propertydan foydalib chiloryli effekt beradigan UI chiqazishi mumkin. Bunday effektni parallaks effekt ham deyishadi uni ko’rinshi backgraund da turgan rasmni sekin silliq qilib scroll qilishida.</p><pre>class HomeCustomScroll extends StatelessWidget {<br>  const HomeCustomScroll({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      appBar: AppBar(backgroundColor: Colors.brown,<br>        title: const Text(&#39;CustomScrollView - Slivers&#39;),<br>        elevation: 0.0,<br>      ),<br>      body: const CustomScrollView(<br>        slivers: &lt;Widget&gt;[<br>          SliverAppBarWidget(),<br>          SliverListWidget(),<br>          SliverGridWidget(),<br>        ],<br>      ),<br>    );<br>  }<br>}</pre><p>Ushbu misolda CustomScrollView widgetidan foydalanib SliverAppBar, SliverList, SliverSafeArea va SliverGrid qulayliklarini ko’rib chiqaylik. SliverAppBar widgetini parallaks effektini ko’ramiz. SliverList List.generate konstruktori bilan widgetlar listini chiqazib ko’ramiz. SliverSafeArea dan foydalanib hoshiyalardan qutilamiz. SliverGriddan foydalanib plitkalarni ham chiqazamiz.</p><pre>class SliverAppBarWidget extends StatelessWidget {<br>  const SliverAppBarWidget({<br>    Key? key,<br>  }) : super(key: key);<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return const SliverAppBar(<br>      backgroundColor: Colors.brown,<br>      forceElevated: true,<br>      expandedHeight: 250.0,<br>      flexibleSpace: FlexibleSpaceBar(<br>        title: Text(&#39;Parallax Effect&#39;),<br>        background: Image(<br>          image: AssetImage(&#39;images/desk.jpg&#39;),<br>          fit: BoxFit.cover,<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o8r32yauhQehvPvE4gUXSA.png" /></figure><pre>class SliverListWidget extends StatelessWidget {<br>  const SliverListWidget({<br>    Key? key,<br>  }) : super(key: key);<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return SliverList(<br>      delegate: SliverChildListDelegate(<br>        List.generate(3, (int index) {<br>          return ListTile(<br>            leading: CircleAvatar(<br>              child: Text(&quot;${index + 1}&quot;),<br>              backgroundColor: Colors.lightGreen,<br>              foregroundColor: Colors.white,<br>            ),<br>            title: Text(&#39;Row ${index + 1}&#39;),<br>            subtitle: Text(&#39;Subtitle Row ${index + 1}&#39;),<br>            trailing: const Icon(Icons.star_border),<br>          );<br>        }),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/303/1*vgatyr2Cr84JqEmr8XYWxA.gif" /></figure><pre>class SliverGridWidget extends StatelessWidget {<br>  const SliverGridWidget({<br>    Key? key,<br>  }) : super(key: key);<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return SliverSafeArea(<br>      sliver: SliverGrid(<br>        delegate: SliverChildBuilderDelegate(<br>          (BuildContext context, int index) {<br>            return Card(<br>              child: Column(<br>                mainAxisAlignment: MainAxisAlignment.center,<br>                children: &lt;Widget&gt;[<br>                const  Icon(<br>                    Icons.child_friendly,<br>                    size: 48.0,<br>                    color: Colors.amber,<br>                  ),<br>                  const Divider(),<br>                  Text(&#39;Grid ${index + 1}&#39;),<br>                ],<br>              ),<br>            );<br>          },<br>          childCount: 12,<br>        ),<br>        gridDelegate:<br>           const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),<br>      ),<br>    );<br>  }<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cc45c76a1e46" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda Stack va Positioned widgetlari bilan ishlash]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-stack-va-positioned-widgetlari-bilan-ishlash-9863586981f9?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/9863586981f9</guid>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Thu, 17 Mar 2022 18:11:32 GMT</pubDate>
            <atom:updated>2022-03-17T18:11:32.861Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IPauYoKHq3ymsQVscz3W7A.png" /></figure><p>Stack widgeti bir qancha widgetlarni aralashmasidan tashkil topgan chiroyli widget chiqazish uchun ishlatiladi, ya’ni widgetlarni bir birini usitga chiqazib dizayn berish uchun. Misol uchun bizda online do’koning savatchasida biz buyurtma bergan tovarlarimiz soni turadigan widget bo’lishi mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/242/1*mkeajoZ_vvsbSJ6gvP4lIw.png" /></figure><p>Stack widgeti o’zida children propertysini qabul qiladi bunda default holatda widgetlarimiz joylashtirsak ustma ust joylashib boradi, huddi qog‘oz parchalarini bir-birining ustiga qo‘yib pastdan yuqoriga qarab taxlanadi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/382/1*PtVHns2ud4gTLsJgQW7wig.png" /></figure><p>Ammo uni pozitsiyasini Positoned widgeti orqali kerakli joyga o’zgartirsak bo’ladi. Stackdagi har bir widgetni joylashtirish Positioned widgetiga wrap qilamiz. Top, bottom, left, va right xususiyatlaridan foydalanib, har bir widgetini Stack ichida o’zgartirib boramiz. Positioned widgetining width va height propertylari ham bor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*v9xw894S0D8qyKRINclqJQ.png" /><figcaption>Pozitsiya berilgan holat</figcaption></figure><p>Widgetni asosiy widgetdan qisman tashqariga chiqazish uchun FractionalTranslation klassidan ham foydalansak bo’ladi. FractionalTranslation klassini translation propertysiga Offset(dx, dy) bu widgetimizning hajmiga moslashgan bo’ladi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XrxvhaOO88nsq0RT3xlcAA.png" /></figure><p>Misolimizda ListView widgetidan foydalanib bir nechta Stacklarni ko’ramiz.ListView.builderni itemCount argumentiga 7 qiymatini beramiz. Har bir Stack index qiymatini juft yoki toq ekanligini tekshirib StackWidget() va StackFavoriteWidget() widget klasslarni ishlatamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9RXGs9KYCGdh2HucKfd1RA.png" /></figure><p>Buni qilishimizda maqsad biz bu orqali dasturimizga pullik reklama qo’ymoqchi bo’lsak shu tartibda qo’ysak bo’ladi yani har 10 chi listdan keyin reklama qo’ygin deb. Ushbu reklama turi odamlarni joniga tegmaydi sababi bunda biz listni scroll qilib o’tkazib yuvorsak bo’ladi, ba’zi bir reklama turlari bor, dasturdan foydalanib turgan vaqtimizda to’liq ekranni egalab oladigan reklamalar bular odamni bezor qiluvchi reklamalar turiga kiradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3yYW9gmD1U_Sx0lR2WkleQ.png" /></figure><pre>class StackWidget extends StatelessWidget {<br>  const StackWidget({<br>    Key? key,<br>  }) : super(key: key);<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Stack(<br>      children: const &lt;Widget&gt;[<br>        Image(<br>          image: AssetImage(&#39;images/tree.jpg&#39;),<br>        ),<br>        Positioned(<br>          bottom: 10.0,<br>          left: 10.0,<br>          child: CircleAvatar(<br>            radius: 48.0,<br>            backgroundImage: AssetImage(&#39;images/lion.jpg&#39;),<br>          ),<br>        ),<br>        Positioned(<br>          bottom: 16.0,<br>          right: 16.0,<br>          child: Text(<br>            &#39;Lion&#39;,<br>            style: TextStyle(<br>              fontSize: 32.0,<br>              color: Colors.white30,<br>              fontWeight: FontWeight.bold,<br>            ),<br>          ),<br>        ),<br>      ],<br>    );<br>  }<br>}</pre><p>Stack widgeti pozitsiya berilmagan widgetlarni o’lchamiga qarab moslashib oladi. Stackda postion berilmgan widgetlardan foydalansak, avtomatik ravishda align qonuniyatlariga bo’ysinib ishlaydi (muhitga qarab Top-left yoki Top-right). Har bir Stackning ichidagi widgelar pastdan yuqoriga qarab ye’g’ilib boradi, ya’ni har bir bola widgeti bir-birining ustiga joylashib boradi.</p><pre>class StackFavoriteWidget extends StatelessWidget {<br>  const StackFavoriteWidget({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Container(<br>      color: Colors.black87,<br>      child: Padding(<br>        padding: const EdgeInsets.all(16.0),<br>        child: Stack(<br>          children: const &lt;Widget&gt;[<br>            Image(image: AssetImage(&#39;images/dawn.jpg&#39;)),<br>            Positioned(<br>              top: 0.0,<br>              right: 0.0,<br>              child: FractionalTranslation(<br>                translation: Offset(0.3, -0.3),<br>                child: CircleAvatar(<br>                  radius: 24.0,<br>                  backgroundColor: Colors.white30,<br>                  child: Icon(<br>                    Icons.star,<br>                    size: 24.0,<br>                    color: Colors.white,<br>                  ),<br>                ),<br>              ),<br>            ),<br>            Positioned(<br>              bottom: 10.0,<br>              right: 10.0,<br>              child: CircleAvatar(<br>                radius: 48.0,<br>                backgroundImage: AssetImage(<br>                  &#39;images/eagle.jpg&#39;,<br>                ),<br>              ),<br>            ),<br>            Positioned(<br>              bottom: 16.0,<br>              left: 16.0,<br>              child: Text(<br>                &#39;Bald Eagle&#39;,<br>                style: TextStyle(<br>                  fontSize: 32.0,<br>                  color: Colors.white30,<br>                  fontWeight: FontWeight.bold,<br>                ),<br>              ),<br>            ),<br>          ],<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/357/1*u4vc-bq1bu65xL6X8yQSVA.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9863586981f9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda GridView va uning turlari]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-gridview-va-uning-turlari-a31c847679cf?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/a31c847679cf</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Wed, 16 Mar 2022 19:36:38 GMT</pubDate>
            <atom:updated>2022-03-16T19:36:38.310Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ckDH63bn9SAWTZ0U-q8bwQ.png" /></figure><p>GridView widgeti plitklar formatida scroll qilinadigan widget turi hisoblanadi. GridViewni GridView.count, GridView.extent va GridView.builder kabi turlari mavjud.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/399/1*mulsQtLqh1ZpP3kWLCJuaQ.png" /></figure><p>GridView.count va GridView.extent odatda fiks yoki kichikroq maʼlumotlar bo’lsa ishlatiladi. Odatda o‘zaro o‘qda belgilangan miqdordagi plitkalar bilan kerak bo‘lganda GridView.count dan foydalananiz. GridView.extent-dan portret rejimida ikki-uch plitka, landscape rejimida esa besh-oltita plitka mos kelishini ko’rish uchun foydalanamiz; boshqacha qilib aytganda, u ekran o‘lchamiga qarab ekrandagi plitkalarga moslashtirib boradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RfYQeCpsmC3xaMO8NOPQOQ.png" /></figure><p>GridView.builder kattaroq, yoki nomaʼlum hajmdagi maʼlumotlar to‘plami bilan ishlayotgan vaqtda kerak bo’ladi. Agar maʼlumotlar katta to‘plamda bo‘lsa, builder faqat ko‘rinib turgan widgetlar uchun ishlap turadi, yana scroll qilsak yana widgetlarni build qiladi, bu esa performance ishlash jihatidan juda yaxshi. Qolgan xususiyatlari ListView.builderniki bilan deyarli farq qilmaydi.</p><h3>GridView.count ishlatish</h3><p>GridView.count crossAxisCount va children argumentlari required hisoblanadi. CrossAxisCount plitkalar nechi bo’lak bo’lishini belgilaydi, childrenda esa widgetlar listi bo’ladi. ScrollDirection argumenti o’q yo’nalishini belgilaydi Axis.vertical yoki Axis.horizontal, default holatda vertikal bo’ladi.</p><pre>class HomeGridCount extends StatelessWidget {<br>  const HomeGridCount({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: SafeArea(<br>          child: GridView.count(<br>        crossAxisCount: 3,<br>        padding: const EdgeInsets.all(8.0),<br>        children: List.generate(<br>          7000,<br>          (index) {<br>            debugPrint(&#39;_buildGridView $index&#39;);<br>            return Card(<br>              margin: const EdgeInsets.all(8.0),<br>              child: InkWell(<br>                child: Column(<br>                  mainAxisAlignment: MainAxisAlignment.center,<br>                  children: &lt;Widget&gt;[<br>                    const Icon(<br>                      Icons.coffee,<br>                      //_iconList[0],<br>                      size: 48.0,<br>                      color: Colors.blue,<br>                    ),<br>                    const Divider(),<br>                    Text(<br>                      &#39;Index $index&#39;,<br>                      textAlign: TextAlign.center,<br>                      style: const TextStyle(<br>                        fontSize: 16.0,<br>                      ),<br>                    )<br>                  ],<br>                ),<br>                onTap: () {<br>                  debugPrint(&#39;Row $index&#39;);<br>                },<br>              ),<br>            );<br>          },<br>        ),<br>      )),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3hnGuiJJ2AFMfOtX93DxTg.png" /></figure><p>Children uchun, List.generate dan foydalangan holda widgetlarimizni ko’p miqdorda yaratib olamiz. children argumentida nima uchun GridView.builder foydalanmaganimizni hozir bilib olamiz. Hozir loyihani ishga tushirganimizda ma’lumotlar faqat ko’rinib turgan qismi emas balki barcha widgetlar kelib olgandan keyin chiqishini ko’rishimiz mumkin, buni debugPrint orqali kuzatib borsak bo’ladi. Shunda GridView.count barcha yozuvlar ishlanmaguncha hech qanday ma’lumot ko’rsatmay turadi hammasi kelganidan keyin ekranda widgetlarimiz payod bo’ladi. GridView.builderni faqi ham ana shunda builder bizga faqat ekranda ko’rinib turgan ma’lumotni o’zinigina ko’rsatib turadi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/664/1*TtBaHMMBrhnhJWNl8ccOZQ.gif" /><figcaption>Ko’rib turganingizdek oldin ma’lumotlarni olib kelyapti so’ng widgetni chiqaryapti</figcaption></figure><h3>GridView.extent-dan foydalanish</h3><p>GridView.extent maxCrossAxisExtent va children argumentini talab qiladi ya’ni required. MaxCrossAxisExtent argumenti qurilma uchun har bir plitkaning maksimal hajmini belgilaydi. Misol uchun, portret rejimda ekranimizga ikki-uchta plitka sig’ishi mumkin, lekin landscapeda qurilmani disply o’lchamiga qarab o’zgaradi, beshta-oltita sig’ishi mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-XOn1O1i2fSXa9h-RKwgHw.png" /></figure><pre>class GridExtent extends StatelessWidget {<br>  const GridExtent({Key? key}) : super(key: key);<br><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: SafeArea(<br>        child: GridView.extent(<br>          maxCrossAxisExtent: 175.0,<br>          scrollDirection: Axis.horizontal,<br>          padding: const EdgeInsets.all(8.0),<br>          children: List.generate(20, (index) {<br>            debugPrint(&#39;_buildGridViewExtent $index&#39;);<br>            return Card(<br>              margin: const EdgeInsets.all(8.0),<br>              child: InkWell(<br>                child: Column(<br>                  mainAxisAlignment: MainAxisAlignment.center,<br>                  children: &lt;Widget&gt;[<br>                    const Icon(<br>                      Icons.coffee,<br>                      size: 48.0,<br>                      color: Colors.blue,<br>                    ),<br>                    const Divider(),<br>                    Text(<br>                      &#39;Index $index&#39;,<br>                      textAlign: TextAlign.center,<br>                      style: const TextStyle(<br>                        fontSize: 16.0,<br>                      ),<br>                    )<br>                  ],<br>                ),<br>                onTap: () {<br>                  debugPrint(&#39;Row $index&#39;);<br>                },<br>              ),<br>            );<br>          }),<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/694/1*4ZFhb3kXsY0uaF6yfDc60w.gif" /></figure><h3>GridView.builder foydalanish</h3><p>GridView.builder itemCount, gridDelegate va itemBuilder argumentlarini talab qiladi. itemCount widgetlarimiz soni uchun. gridDelegate SilverGridDelegate bo’lib, u necha qatorli widgetlar chiqishini belgilaydi. GridDelegate argument null bo’lishi mumkin emas; maxCrossAxisExtent o’lchamini beramiz masalan 150.0 piksel. Misol uchun, ekranda uchta plitkani ko’rsatish uchun SliverGridDelegateWithFixedCrossAxisCount klassidan foydalanamiz. Agar maksimal kengligi 150.0 piksel bo’lgan plitkalarni ko’rsatishkerak bo’lsa,SliverGridDelegateWithMaxCrossAxisExtent klassidan foydalanamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ujK-MLPjfx5YKWE2w8j48A.png" /></figure><pre>class HomeGridBuilder extends StatelessWidget {<br>  const HomeGridBuilder({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    List&lt;IconData&gt; _iconList = GridIcons().getIconList();<br>    return Scaffold(<br>      body: SafeArea(<br>        child: GridView.builder(<br>          itemCount: 20,<br>          padding:const EdgeInsets.all(8.0),<br>          gridDelegate:<br>             const SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 150.0),<br>          itemBuilder: (BuildContext context, int index) {<br>            debugPrint(&#39;_buildGridViewBuilder $index&#39;);<br>            return Card(<br>              color: Colors.lightGreen.shade50,<br>              margin: const EdgeInsets.all(8.0),<br>              child: InkWell(<br>                child: Column(<br>                  mainAxisAlignment: MainAxisAlignment.center,<br>                  children: &lt;Widget&gt;[<br>                    Icon(<br>                      _iconList[index],<br>                      size: 48.0,<br>                      color: Colors.lightGreen,<br>                    ),<br>                  const  Divider(),<br>                    Text(<br>                      &#39;Index $index&#39;,<br>                      textAlign: TextAlign.center,<br>                      style: const TextStyle(<br>                        fontSize: 16.0,<br>                      ),<br>                    )<br>                  ],<br>                ),<br>                onTap: () {<br>                  debugPrint(&#39;Row $index&#39;);<br>                },<br>              ),<br>            );<br>          },<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/314/1*VbNoCcU0J-q4rQdZ5AbPKg.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a31c847679cf" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda Card, ListView.builder va ListTile widgetlari]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-card-listview-builder-va-listtile-widgetlari-4cc3ea51c1c0?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/4cc3ea51c1c0</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Wed, 16 Mar 2022 12:19:46 GMT</pubDate>
            <atom:updated>2022-03-16T12:19:46.444Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hAU9IbIQkxj_joXegZRaNg.png" /></figure><p>Ushbu postlarimizda biz foydalanuvchilarga ma’lumotni ko’rish va tanlashda yordam beradigan scroll qilinadigan listlarni qilishni o’rganamiz. Oldingi postda standart ListViewni ko’rgan edik endi ListView.builder foydalanishni ham ko’rib olamiz. GridView widgeti bir yo’nalishda bir biriga bog’langan plitka widgetlari. Stack widgeti odatda widgetlarni bir-biriga ustiga qo’yish uchun ishlatamiz. CustomScrollView widgeti sliver widgetlari roʻyxatidan foydalanib, maxsus scroll effektlarini yaratishga imkon beradi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/356/1*Ws2FccqKHvbAs7EqArUeXQ.gif" /></figure><p>Card widgeti Material Design widgetlaridan hisoblanadi sababi uni ko’rinishidan bilsak bo’ladiki u minimal dumaloqroq burchaklarsiz va soyasi bor widget. Ma’lumotlarni komponentlarga bo’lish yoki guruhlash uchun Card widgeti UI uchun chiroyli yechim hisoblanadi. Card widgetni elevation, shape, color, margin va yana bir qancha propertylarga ega. Elevation double qiymatni oladi, qiymat qanchalik katta bo’lsa, soya ham shunchalik katta bo’ladi. Card widgetining shakli va borderlarni sozlash uchun shape propertysida o’zgartirishlar kiritamz. Misol uchun: StadiumBorder, UnderlineInputBorder, OutlineInputBorder va boshqalar.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3S0Tda6bl2RMvskUzsvTbw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/836/1*O4xB2ucwu17PF2aGCJuIIw.png" /></figure><p>ListView.builder ham standart ListView kabi scroll qilinadidan widget hisoblanadi farqi esa katta ma’lumotlar to’plami bilan ishlaydigan bo’lsak builderdan foydalanishimizda va yana asosiy farqi u fqurilamda ko’rinib turgan widgetlar uchun ishlaydi, ya’ni 20 ta rasmdan iborat widgetimiz bo’lsin ekranda esa 5ta rasm sig’sa faqat 5 ta uchun ishlaydi scroll qilsak qolgan qismi uchun build qiladi. itemBuilder esa bizga child widgetlarimizni yasash uchun kerak bo’ladi. itemBuilder faqat itemCount argumenti noldan katta bo’lsa ishlaydi. itemCount o’zi esa bizda qancha ma’lumot borligni indexlab turadi. Bundan tashqari ScrollDirection argumenti default holatda Axis.vertical da bo’ladi, uni Axis.horizontal ga o’zgartirishimiz mumkin, shunda obyektlarimiz gorizontal yo’nalishda scroll bo’ladi. ListTile widgeti odatda ListView widgeti bilan ham ishlatilinadi. Asosiy propertylari leading, trailing, title va subtitle,va yana boshqalari ham bor. Bundan tashqari, foydalanuvchi harakatni amalga oshirish uchun onTap va onLongPress qulayliklari ham bor. Bunda foydalanuvchi ListTile-ga teginganida biron bir sahifaga o’tadi yoki alertdilaog ochiladi. Odatda leading va trailing propertylariga icon widgeti beriladi ammo bu required emas istalgan widgetimizni bersak bo’ladi.</p><pre>Card(<br>  child: ListTile(<br>    leading: Icon(Icons.flight),<br>    title: Text(&#39;Airplane $index&#39;),<br>    subtitle: Text(&#39;Very Cool&#39;),<br>    trailing: Text(&#39;${index * 7}%&#39;),<br>    onTap: ()=&gt; print(&#39;Tapped on Row $index&#39;),<br>  ),<br>);</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/588/1*mgWZ--i1MDelVnjX-EBBRg.png" /></figure><pre>ListTile(<br>  leading: Icon(Icons.directions_car),<br>  title: Text(&#39;Car $index&#39;),<br>  subtitle: Text(&#39;Very Cool&#39;),<br>  trailing: Icon(Icons.bookmark),<br>  onTap: ()=&gt; print(&#39;Tapped on Row $index&#39;),<br>);</pre><p>Rasmda ko’rinib turganidek birinchi uchta ListTileni leading propertyisda icon turibti, trailingda esa Text widgeti foizlarni ko’rsatib turibdi. Qolgan ListTilelarda esa leading va trailingda iconlar turibti. Title sa subtitle nima ekanligni rasmga qarab tushunib olgan bo’lsangiz kerak.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-s9lm4qxOeImIz-0UsF6qg.png" /></figure><p>Har xil turdagi widgetlarni qanday qo’shish uchun ozgina mantiq operatorlardan foydalanamiz. Misol uchun index teng bo’lsa 0 ga boshqa turdagi widgetni ko’rsat agar 1 ga teng bo’lsa boshqasini shu tartibda kodimizni kiritib olamiz. ItemBuilder-dagi index vazifasi har bir index uchun unique bolgan widgetni tuzishdan iborat.</p><pre>class HeaderWidget extends StatelessWidget {<br>  const HeaderWidget({<br>    Key? key,<br>    required this.index,<br>  }) : super(key: key);<br>  final int index;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Container(<br>      padding: const EdgeInsets.all(16.0),<br>      height: 120.0,<br>      child: Card(<br>        elevation: 8.0,<br>        color: Colors.white,<br>//shape: StadiumBorder(),<br>//shape: UnderlineInputBorder(borderSide: BorderSide(color: Colors.deepOrange)),<br>//shape: OutlineInputBorder(borderSide: BorderSide(color:<br>//Colors.deepOrange.withOpacity(0.5)),),<br>        child: Column(<br>          mainAxisAlignment: MainAxisAlignment.center,<br>          children: const &lt;Widget&gt;[<br>            Text(<br>              &#39;Barista&#39;,<br>              textAlign: TextAlign.center,<br>              style: TextStyle(<br>                fontWeight: FontWeight.bold,<br>                fontSize: 48.0,<br>                color: Colors.orange,<br>              ),<br>            ),<br>            Text(<br>              &#39;Travel Plans&#39;,<br>              textAlign: TextAlign.center,<br>              style: TextStyle(color: Colors.grey),<br>            ),<br>          ],<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Nw5OhjivwbdHHAXV61ZkEw.png" /></figure><pre>class RowWithCardWidget extends StatelessWidget {<br>  const RowWithCardWidget({<br>    Key? key,<br>    required this.index,<br>  }) : super(key: key);<br>  final int index;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Card(<br>      child: ListTile(<br>        leading: const Icon(<br>          Icons.flight,<br>          size: 48.0,<br>          color: Colors.lightBlue,<br>        ),<br>        title: Text(&#39;Airplane $index&#39;),<br>        subtitle: const Text(&#39;Very Cool&#39;),<br>        trailing: Text(<br>          &#39;${index * 7}%&#39;,<br>          style: const TextStyle(color: Colors.lightBlue),<br>        ),<br>//selected: true,<br>        onTap: () {<br>          debugPrint(&#39;Tapped on Row $index&#39;);<br>        },<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/349/1*dDPPH3z1vbcnQb_8j99Vcw.gif" /></figure><pre>class RowWidget extends StatelessWidget {<br>  const RowWidget({<br>    Key? key,<br>    required this.index,<br>  }) : super(key: key);<br>  final int index;<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return ListTile(<br>      leading: const Icon(<br>        Icons.directions_car,<br>        size: 48.0,<br>        color: Colors.lightGreen,<br>      ),<br>      title: Text(&#39;Car $index&#39;),<br>      subtitle: const Text(&#39;Very Cool&#39;),<br>      trailing: (index % 3).isEven<br>          ? const Icon(Icons.bookmark_border)<br>          : const Icon(Icons.bookmark),<br>      selected: false,<br>      onTap: () {<br>        debugPrint(&#39;Tapped on Row $index&#39;);<br>      },<br>    );<br>  }<br>}</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4cc3ea51c1c0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda Drawer va ListView widgetlari]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-drawer-va-listview-widgetlari-9c2807cbab95?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/9c2807cbab95</guid>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[ios-app-development]]></category>
            <category><![CDATA[dart]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Tue, 15 Mar 2022 20:46:15 GMT</pubDate>
            <atom:updated>2022-03-15T20:51:18.810Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4KHHir78cv55aegK5552BQ.png" /></figure><p>Nima uchun ushbu navigatsiya postlarida ListView widgetni endi ishlatayotganimizni sababi bor edi. Sababi Drawer widgeti bir qancha listlardan tashkil topgan bo’ladi. Va aynan shu listlar orqali ListViewni bilib olsak onsonroq bo’ladi. ListView widgetlari roʻyxatdagi elementlarni tanlash uchun ko’p ishlatiladi, misol uchun Detail sahifaga o’tishga o’xshagan holatlarda.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/434/1*_ZA_PtZuQJ9FgWHjx2RLow.gif" /></figure><p>Drawer — Scaffold widgetining qulayligi, odatda qurilma ekranining chap yoki o’ng chetidan gorizontal ravishda chiqib keladigan yarim ekranli dialog desa ham bo’ladi, u Material design paneli hisoblanadi sababi bu qulaylik android qurilmalarida ko’rishimiz mumkin ios esa kamdan kam holatda ko’ramiz. Drawer Scaffoldni tortmasi deb ham atasak bo’ladi uni chapdan chiqazish uchun drawer deb yozsak chap tarafdan chiqazadi, endDrawer deb yozsak o’ng tarafdan chiqazadi. Drawerni o’zimiz istalgancha ehtiyojimizdan kelib chiqib sozlanishimiz mumkin, lekin odatda foydalanuvchi rasmi va ma’lumotlari yoki sozlamalar qismidan foydalanamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/274/1*dmSgmSj72TOwUzeWO0wlXg.gif" /><figcaption>odatda chap tarafdan chiqadigan drawerlarni ko’rganimiz uchun o’ng tomondan chiqadigan misolni keltirdik</figcaption></figure><p>Drawer ga header berish uchun bizda ikkita variant mavjud: UserAccountsDrawerHeader yoki DrawerHeader. UserAccountsDrawerHeader currentAccountPicture, accountName, accountEmail, otherAccountsPictures va decoration xususiyatlarini olgan bu foydalanuvchi maʼlumotlarini koʻrsatish uchun moʻljallangan.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nRQIx4MDvnheUtWfUszeLw.png" /></figure><p>DrawerHeader esa padding, child, decoration va boshqa xususiyatlarni o’z ichiga oladi, umumiy yoki moslashtirilgan ma’lumotlar uchun ishlatiladi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O8XeJYnxXUszC0rQX8QdnA.png" /></figure><p>Misolimizda Scaffoldning drawer va endDrawer xususiyatini ko’rishimiz mumkin. Drawer va endDrawer dan foydalanganimizda TextDirection.ltr ) yoki TextDirection.rtl qulayligni shu yerda nima uchun kerakligini bilib olamiz. UserAccountsDrawerHeaderni (chap tomon) xususiyati uchun ya’ni drawerga va DrawerHeader esa endDrawer (o’ng tomon) xususiyatiga beragnimiz ko’rinib turibdi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tR5C7ydbwL5qJm_u-lp3ZA.png" /></figure><p>Ushbu misolda Scaffoldning drawer va endDrawer xususiyatini ko’rishimiz mumkin. Drawer va endDrawer dan foydalanganimizda TextDirection.ltr ) yoki TextDirection.rtl qulayligni shu yerda nima uchun kerakligini bilib olamiz. UserAccountsDrawerHeaderni (chap tomon) xususiyati uchun ya’ni drawerga va DrawerHeader esa endDrawer (o’ng tomon) xususiyatiga beragnimiz ko’rinib turibdi.</p><pre>class MenuListTile extends StatelessWidget {<br>  const MenuListTile({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Column(<br>      children: &lt;Widget&gt;[<br>        ListTile(<br>          leading: const Icon(Icons.cake),<br>          title: const Text(&#39;Birthdays&#39;),<br>          onTap: () {<br>            Navigator.pop(context);<br>            Navigator.push(<br>              context,<br>              MaterialPageRoute(<br>                builder: (context) =&gt; const Birthdays(),<br>              ),<br>            );<br>          },<br>        ),<br>        ListTile(<br>          leading: const Icon(Icons.sentiment_satisfied),<br>          title: const Text(&#39;Gratitude&#39;),<br>          onTap: () {<br>            Navigator.pop(context);<br>            Navigator.push(<br>              context,<br>              MaterialPageRoute(<br>                builder: (context) =&gt; const Gratitude(),<br>              ),<br>            );<br>          },<br>        ),<br>        ListTile(<br>          leading: const Icon(Icons.alarm),<br>          title: const Text(&#39;Reminders&#39;),<br>          onTap: () {<br>            Navigator.pop(context);<br>            Navigator.push(<br>              context,<br>              MaterialPageRoute(<br>                builder: (context) =&gt; const Reminders(),<br>              ),<br>            );<br>          },<br>        ),<br>        const Divider(color: Colors.grey),<br>        ListTile(<br>          leading: const Icon(Icons.settings),<br>          title: const Text(&#39;Setting&#39;),<br>          onTap: () {<br>            Navigator.pop(context);<br>          },<br>        ),<br>      ],<br>    );<br>  }<br>}</pre><p>Birthdays, Reminders, Gratitude sahifalarini avvalgi postlarimizda kiritb olgan edik, bu safar ham misol tariqasida yana o’sha sahifalardan foydalangan holda misolmizni ishlaymiz.</p><pre>class LeftDrawer extends StatelessWidget {<br>  const LeftDrawer({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Drawer(<br>      child: ListView(<br>        padding: EdgeInsets.zero,<br>        children: const &lt;Widget&gt;[<br>          UserAccountsDrawerHeader(<br>              currentAccountPicture: Icon(<br>                Icons.face,<br>                size: 48.0,<br>                color: Colors.white,<br>              ),<br>              accountName: Text(&#39;Amir Temur&#39;),<br>              accountEmail: Text(&#39;<a href="mailto:temur.temuchin@domainname.com">temur.temuchin@domainname.com</a>&#39;),<br>              otherAccountsPictures: &lt;Widget&gt;[<br>                Icon(<br>                  Icons.bookmark_border,<br>                  color: Colors.white,<br>                )<br>              ],<br>              decoration: BoxDecoration(<br>                image: DecorationImage(<br>                  image: AssetImage(&#39;images/home_top_mountain.jpg&#39;),<br>                  fit: BoxFit.cover,<br>                ),<br>              )),<br>          MenuListTile(),<br>        ],<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xB2npq1Fjl1kfj55sgrhmA.png" /></figure><pre>class RightDrawerWidget extends StatelessWidget {<br>  const RightDrawerWidget({<br>    Key? key,<br>  }) : super(key: key);<br>  <a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Drawer(<br>      child: ListView(<br>        padding: EdgeInsets.zero,<br>        children: const &lt;Widget&gt;[<br>          DrawerHeader(<br>            padding: EdgeInsets.zero,<br>            child: Icon(<br>              Icons.face,<br>              size: 128.0,<br>              color: Colors.white54,<br>            ),<br>            decoration: BoxDecoration(color: Colors.blue),<br>          ),<br>          MenuListTile(),<br>        ],<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HA-42z5nUG2nHQpSOYX1eQ.png" /></figure><p>Menyu elementlari list uchun o’zimiz yasab olgan MenuListTile() widget klassidan foydalandik. Bu widget klassimiz menyu listni yaratish uchun ListTile-dan foydalanildi. ListTile widgetiga leading propertysiga Icon, title esa text berdik va onTap xususiyati uchun esa Drawerni yopish uchun Navigator.pop() ni va tanlangan sahifaga o’tish uchun Navigator.push() ni ishlatdik. Ushbu ilova widget klasslaridan unumli foydalanishni va qanday qilib qayta foydalanishni o’rgangan bo’ldik.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/362/1*cswRt6PqPDv05VX8nQCdmA.gif" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9c2807cbab95" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutterda TabBar va TabBarView]]></title>
            <link>https://medium.com/@khabiliyshakhzod/flutterda-tabbar-va-tabbarview-2ef6cca32dae?source=rss-101f5f58dd6c------2</link>
            <guid isPermaLink="false">https://medium.com/p/2ef6cca32dae</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[flutter-app-development]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[ios]]></category>
            <dc:creator><![CDATA[Umar khabiliy]]></dc:creator>
            <pubDate>Tue, 15 Mar 2022 13:41:34 GMT</pubDate>
            <atom:updated>2022-03-15T13:41:34.313Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gIl-DQYN47CrdtfoGTXDgQ.png" /></figure><p>TabBar widgeti gorizontal qatorlar vkladkar (yorliqlarni) ko’rsatadigan Material Design widgeti hisoblanadi.TabBarnni bir qancha propertylari bor ulardan asosiysi, tabs xususiyati Widgetlar listni oladi va Tab widgetidan foydalangan holda vkladkalarni qoʻshib boramiz. Tab widgetidan foydalanishdan tashqari Flutter tomonidan berilgan widgetlardan foydalansak ham bo’laveradi. BottomNavigationBar kabi tanlagan vkladkamiz default holatida pastki chizig’i bilan belgilanadi.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/606/1*TWeT9d3Kqutbab4t3lyegg.png" /></figure><p>TabBarView widgeti odatda TabBar widgeti bilan birgalikda ishlatiladi ya’ni biz vkladkani tanlasak TabBarView tanlangan vkladkadagi sahifaga o’tkazadi. Foydalanuvchilar kontentni o‘zgartirish uchun chapga yoki o‘ngga surishlari yoki har bir vkladkani bosishlari mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w8qXEMHAOUI3wiqLOdxzDA.png" /></figure><p>TabBar va TabBarView widgetlari TabController-ning controller qulayligidan foydalanadi. TabController TabBar va TabBarView o’rtasida vkladkalarni tanlovlarini sinxronlashtirish uchun javobgar. TabController vkladkalar tanlovlarini sinxronlashtirganligi sababli, klassimizga <br>SingleTickerProviderStateMixinni e’lon qilishimiz kerak. Animatsiyani iloji boricha silliq bo’lishi uchun foydalanishimizni avvalgi postlarimizda aytib o’tgan edik.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/812/1*Gtw0jv41Ti9GS96rOEY_7w.png" /></figure><p>Bu misolda TabBar widgetini bottomNavigationBar bilan ishlatamiz. Bunda TabBar-ni ekranning pastki qismida joylashadi, lekin uni AppBarga yoki istalgan boshqa joyda ham joylashtirib foydalanishimiz mumkin.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/1*U2NWfujuEFP36Hj6GWSpww.gif" /></figure><p>Ushbu misolimizda uchta alohida sahifadan iborat TabBarView kiritamiz. BottomNavigationBar loyihasidagi kabi uchta bir hil sahifani ishlatamiz.<br>TabController typeda _tabController o’zgaruvchisini kiritib olamiz. _tabControllerni ishlatish uchun initState() metodidan foydalanamiz vsync argumentiga this qiymatni va length qiymatga 3 beramiz sahifamiz 3 ta bo’lgani uchun. Length tablar sonini bildiradi biz nechi sonini kiritsak shuncha tabni ko’rishimiz mumkin bo’ladi. Tablardagi o’zgarishlarni bilib turish uchun addListenerdan foydalanamiz, u doimo _tabControllerdagi o’zgarishlarni tinglab poylab turadi. Boshqa sahifada backgrounda _tabController ishlashini to’xtatish uchun dispose() metodidan foydalanamiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*35VLYMkes0UIY6kOBTZh1Q.png" /></figure><pre>class HomeTabs extends StatefulWidget {<br>  const HomeTabs({Key? key}) : super(key: key);</pre><pre><a href="http://twitter.com/override">@override</a><br>  _HomeTabsState createState() =&gt; _HomeTabsState();<br>}</pre><pre>class _HomeTabsState extends State&lt;HomeTabs&gt;<br>    with SingleTickerProviderStateMixin {<br>  TabController? _tabController;<br>  <a href="http://twitter.com/override">@override</a><br>  void initState() {<br>    super.initState();<br>    _tabController = TabController(vsync: this, length: 3);<br>    _tabController!.addListener(_tabChanged);<br>  }</pre><pre><a href="http://twitter.com/override">@override</a><br>  void dispose() {<br>    super.dispose();<br>    _tabController!.dispose();<br>  }</pre><pre>void _tabChanged() {<br>    if (_tabController!.indexIsChanging) {<br>      debugPrint(&#39;tabChanged: ${_tabController!.index}&#39;);<br>    }<br>  }</pre><pre><a href="http://twitter.com/override">@override</a><br>  Widget build(BuildContext context) {<br>    return Scaffold(<br>      body: SafeArea(<br>        child: TabBarView(<br>          controller: _tabController,<br>          children: const [<br>            Birthdays(),<br>            Gratitude(),<br>            Reminders(),<br>          ],<br>        ),<br>      ),<br>      bottomNavigationBar: SafeArea(<br>        child: TabBar(<br>          controller: _tabController,<br>          //label color va  unselectedLabelColor farqiga borish uchun<br>          //amaliyotda ko&#39;proq boshqa ranglarda foydalanib ko&#39;ring<br>          //shunda to&#39;liq farqiga borshingiz oson bo&#39;ladi<br>          labelColor: Colors.black54,<br>          unselectedLabelColor: Colors.black38,<br>          tabs: const [<br>            Tab(<br>              icon: Icon(Icons.cake),<br>              text: &#39;Birthdays&#39;,<br>            ),<br>            Tab(<br>              icon: Icon(Icons.sentiment_satisfied),<br>              text: &#39;Gratitude&#39;,<br>            ),<br>            Tab(<br>              icon: Icon(Icons.access_alarm),<br>              text: &#39;Reminders&#39;,<br>            ),<br>          ],<br>        ),<br>      ),<br>    );<br>  }<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/339/1*VUMflw1AQStrOWqWC5jpjQ.gif" /></figure><p>TabBar va TabBarView birgalikda ishlatilsa, sahifalar avtomatik ravishda bir birga bog’langan bo’ladi. Foydalanuvchi TabBarView-ni chapga yoki o’ngga sursa, sahifa ham o’zgaradi. Qaysi sahifa qaysi vkladkaga tegishli ekanini bilish uchun TabControllerdan foydalandik, bu TabBar va TabBarView o’rtasida bog’liqlikni sinxronlashtiradi. TabBar va TabBarView ikkalasi ham bitta TabController-dan foydalanadi. TabController vsync argumenti va length argumentlari orqali ishga tushadi. Tabda oʻzgarishlarini tinglash uchun TabController addListenerga qoʻshilgan. Buni biz bir vkladkadan ikkinchisiga o’tayotgada birinchi sahifadagi o’zgrishlarni saqlab qolish yoki o’chirib yuborish uchun ishlatishimiz mumkin bo’ladi.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2ef6cca32dae" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>