<?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 Muhammet ÖMER on Medium]]></title>
        <description><![CDATA[Stories by Muhammet ÖMER on Medium]]></description>
        <link>https://medium.com/@mukireus?source=rss-db21aee611de------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Y9CHCsbWoyQF2JoGXRhibA.jpeg</url>
            <title>Stories by Muhammet ÖMER on Medium</title>
            <link>https://medium.com/@mukireus?source=rss-db21aee611de------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 25 May 2026 22:39:30 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@mukireus/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[Taşınıyoruz — Native’den Flutter’a geçiş sürecinde neler yaşadık?]]></title>
            <link>https://medium.com/teamkraken/ta%C5%9F%C4%B1n%C4%B1yoruz-nativeden-flutter-a-ge%C3%A7i%C5%9F-s%C3%BCrecinde-neler-ya%C5%9Fad%C4%B1k-7a41d498786d?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/7a41d498786d</guid>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[development]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Thu, 19 Dec 2024 13:15:20 GMT</pubDate>
            <atom:updated>2024-12-19T13:15:20.119Z</atom:updated>
            <content:encoded><![CDATA[<h3>Taşınıyoruz — Native’den Flutter’a geçiş sürecinde neler yaşadık?</h3><p>Herkese selam! Bu yazımda, Paraşüt uygulamamızı native yani hem Android hem de iOS tabanlı 2 projeden, Flutter framework ile tek projeye nasıl geçiş yaptığımızdan, bu kararı alırken neleri dikkate aldığımızdan ve en önemlisi kullanıcı deneyimini etkilemeden nasıl geçiş yaptığımızdan bahsedeceğim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/0*PGT1cSmAzFV4liQ5.gif" /><figcaption>Source: <a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExcmFqbWlzc2owcmFmZWc2NjZ5MW5zMTdkM29jMHM0ejB5cjZhMzNnOSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/XkEArR5LWqH7ztgCRg/giphy.gif">Spiderman Superhero GIF by Spider-Man: Into The Spider-Verse</a></figcaption></figure><p>Uygulamamızı indirerek incelemek isterseniz aşağıdaki linklerden ulaşabilirsiniz:</p><ul><li><a href="https://play.google.com/store/apps/details?id=com.parasut">Paraşüt Android</a></li><li><a href="https://apps.apple.com/tr/app/para%C5%9F%C3%BCt-%C3%B6n-muhasebe-y%C3%B6netimi/id976151321">Paraşüt iOS</a></li></ul><h4>Neden Flutter?</h4><p>Mart 2021&#39;de yayınlanan <strong><em>Üretim Bandı</em></strong> podcast kanalında “<strong><em>Teknik: Osman Yılmaz &amp; Emir Bostancı — Paraşüt Mobil Takımı (Team Kraken) Nasıl Yazılım Geliştiriyor?” </em></strong>isimli bölümde <a href="https://medium.com/u/227ecd1feb9d">Osman Yılmaz</a> şöyle bahsediyor:</p><blockquote>…Flutter’ın komünitesinin hızlı gelişeceğini ve biz mobil ekip olarak Türkiye’de öncü uygulamaları, daha çok fintech uygulamaları Flutter ile geliştirerek biraz daha ön plana çıkabiliriz…</blockquote><blockquote>… Bu uygulamayı gerçekten çok stabil çalışan ve performansından çok memnun kaldığımız bir ürün olarak çıkarttık. Tamamen umduğumuz bir vakitte çıkarttık. Flutter’ın faydalarını gördük…</blockquote><blockquote>…bahsettiğim gibi öncede bütün uygulamalarımızı gün sonunda Flutter’a çevirmeyi düşünüyoruz. İlerde de Paraşüt’ün zaten uygulaması Flutter tarafında peyderpey çevireceğiz zaten, modül modül tabii bi anda böyle sıfırdan yazacak bir stratejimiz yok orada…</blockquote><p>Özetle bakarsak Flutter’ı tercih etme sebeplerimizden birisi zaman maliyeti. Kısa sürede stabil ve performanslı uygulamalar ortaya çıkartabilmek bizim için çok önemli bir faktör oldu. Çünkü <a href="https://medium.com/u/227ecd1feb9d">Osman Yılmaz</a>’ın da bahsettiği gibi birden fazla uygulama yazıyoruz.</p><p>Podcast bölümünün tamamını dinlemek isterseniz linki buraya bırakıyorum:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fopen.spotify.com%2Fembed%2Fepisode%2F7j62AOBKW6EbUcRHQO2VKl%3Futm_source%3Doembed&amp;display_name=Spotify&amp;url=https%3A%2F%2Fopen.spotify.com%2Fepisode%2F7j62AOBKW6EbUcRHQO2VKl&amp;image=https%3A%2F%2Fi.scdn.co%2Fimage%2Fa5ff6d7ac46dc704f70e17ffd3aa4a13e47add15&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=spotify" width="456" height="152" frameborder="0" scrolling="no"><a href="https://medium.com/media/04d18210c68d32f7b0bc175b8bf0e192/href">https://medium.com/media/04d18210c68d32f7b0bc175b8bf0e192/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*wlgFmLYku6ftIf7d.gif" /><figcaption>Source: <a href="https://giphy.com/gifs/spiderman-spiderverse-into-the-1qErVv5GVUac8uqBJU">Spider-Man Marvel GIF by Spider-Man: Across The Spider-Verse</a></figcaption></figure><h4>Flutter’a geçiş yapmadan önce nelere dikkat ettik?</h4><p>Her şeyden önce modül analizleri ile başladık. Örneğin “Satışlar” modülü “Müşteriler” modülünü etkiliyor mu? “Hizmet ve Ürünler” modülü “Depo” modülünü ne kadar etkiliyor? gibi soruları analiz ederek bir şema oluşturduk. Hangi modül ile başlayacağımıza karar verip bir yol haritası oluşturduk.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/1*KuvFuwOFS1syC5mOiwdlLA.png" /><figcaption><strong>Source</strong>: <a href="https://play.google.com/store/apps/details?id=com.parasut">PlayStore — Paraşüt Ön Muhasebe Yönetimi</a></figcaption></figure><p>Tasarım ekibimizin geliştirdiği, FDS yani <a href="https://framedesignsystem.com/">Frame Design System</a> isimli design systeminde bulunan componentleri, modülleri geliştirdikçe Flutter design system paketimize teker teker ekledik. Örneğin button ihtiyacımız oldu, butonu tasarımıyla birlikte ekledik ve ihtiyacımız olan yerlerde kullandık.</p><p><a href="https://github.com/parasutcom/frame-design-system">GitHub - parasutcom/frame-design-system: Open source design system for financial products and digital experiences.</a></p><blockquote>Flutter ile yazdığımız frame design system paketimiz public değildir.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*EQ5i9Pzfsv_SzlP1.gif" /><figcaption>Source: <a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExYWZ2ejM5ZWs5ZXVmNzd4MGloMmFkNmt3Z2J2aXhtZHozd3B3OGd0aiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/HxkGSu3ExJ0Lz87QLF/giphy.gif">Spider Gwen Marvel GIF by Sony Pictures Animation</a></figcaption></figure><h4>Flutter’a geçiş yaparken nasıl başladık?</h4><p>Modül modül çıkma hedefimiz olduğundan native projeye feature/bugfix geliştirme tasklarına devam ediyorduk. Projeyi bekleme durumuna almadan debug modunda bir yandan çalışabilmemiz gerekiyordu. Bu nedenle Flutter projesini uygulama olarak değil modül olarak oluşturduk.</p><blockquote><strong><em>Modül kavramı kafa karışıklığına neden olmaması için Flutter modül ve Paraşüt modül ayrımına dikkat edilmesi gerekmektedir.</em></strong></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vINSCROSoUII35UtUCBWPQ.png" /><figcaption>Flutter Create &gt; Module</figcaption></figure><p>Ardından oluşturduğumuz Flutter modülü native projelerimize ekledik. Bu adımda biraz native bilgi gerekmektedir. Burada resmi dökümanı takip ettik. Resmi dökümana aşağıdaki linkten ulaşabilirsiniz.</p><p><a href="https://docs.flutter.dev/add-to-app">Add Flutter to an existing app</a></p><p>Android ve iOS için gerekli geliştirmeleri yaptıktan sonra native projelerimiz içerisinde Flutter çalıştırmayı başardık. Ardından paraşüt modül geliştirmelerine başladık.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/0*WEAAQ07qAjjTuRJ-.gif" /><figcaption>Source: <a href="https://tenor.com/view/surprised-doctor-octopus-doc-ock-otto-octavius-spider-man-no-way-home-gif-25179349">Tenor</a></figcaption></figure><p>Önce dashboard ile başladık tabii ki ve planımız da Login -&gt; Dashboard -&gt; Modüller -&gt; Native Routing şeklinde ilerleyip tek tek modülleri Flutter ile yeniden yeni tasarım ile geliştirmek vardı.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JxHoqhVFI-gHhlSQanMqrw.png" /></figure><p>Kullanıcı giriş yaptıktan sonra native ve flutter modüller ile haberleşmesi gerekiyordu. Yani Flutter&#39;da access token veya refresh token gibi tokenları kullanabilmemiz gerekiyordu. Bu aşamalarda hem Android hem iOS hem de Flutter olarak ayrı ayrı geliştirmeler yaptık. MethodChannel burada bize çok fayda sağladı. Örneğin bir fonksiyon ismini iki tarafta da tanımlayıp istek attığımızda, native tarafta dinleyerek istek attığımız method ismine göre fonksiyon çağırıp, dilersek bir değer döndürebilme gibi süper bir avantaja sahiptik. Daha fazla detaylı incelemek isterseniz aşağıya bir link bırakıyorum:</p><p><a href="https://docs.flutter.dev/platform-integration/platform-channels">Writing custom platform-specific code</a></p><p>Bu yöntemi kullanarak routing konusunu çözmüş olduk. Örneğin “Satışlar” modülüne tıkladığımızda method channel ile “Invoices” method isteği gönderdiğimizde native tarafta bu modülün bulunduğu sayfayı açıyorduk. Sonuç olarak native -&gt; flutter, flutter -&gt; native geçişlerimizde bize konfor sağladı.</p><h4>Remote config nerede işimize yaradı?</h4><p>Remote config, uygulamanızın sizin belirttiğiniz ayarlarını uzaktan yönetmenizi sağlayan bir araçtır. Yani kullanıcılar uygulamayı güncellemeye ihtiyaç duymadan, anlık olarak değişiklikler yapabiliyorsunuz. Biz remote config için Firebase tercih ettik.</p><p><a href="https://firebase.google.com/products/remote-config">Firebase Remote Config | Personalize and optimize your app within feature flags</a></p><p>Remote config’in en çok beğendiğimiz özelliklerinden birisi istediğimiz zaman açıp, istediğimiz zaman kapatabilme esnekliğine sahip olmasıydı. En sık kullandığımız yer ise modülleri istediğimiz zaman native istediğimiz zaman Flutter’a yönlendirmek oldu. Kafanız karıştıysa hemen bir görselle açıklamaya çalışayım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J2orgxgTR80KsPpCVjwQuA.png" /></figure><p>Örneğin bizim isExpendituresModuleEnabled isimli bir flagimiz olsun. Routing işlemini yaptığımız yerde bu değere bakıyoruz ve bu değer eğer true ise Flutter ile yazdığımız ekrana, eğer false ise Native ekrana yönlendiriyor. Tabii tamamen Flutter geçiş yaptığımız için şu an bunlara ihtiyaç duymuyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/360/0*4IyDzQPX7M_HmLrU.gif" /><figcaption>Source: <a href="https://giphy.com/gifs/SpiderManMovie-spiderman-spidermannowayhome-no-way-home-zcTrGn54lOrlOABRDB">Confused Tom Holland GIF by Spider-Man</a></figcaption></figure><p>Peki neden modülleri kapatıp açmaya ihtiyaç duyduk derseniz, yukarıda bahsettiğim gibi bazen ön göremediğimiz buglarla karşılaşabiliyoruz ve bu hataları fixleyip yeni sürüm çıkana kadar kullanıcılarımızın problem yaşamalarını minimum seviyede tuttuk. Böylece biz modülleri geliştirirken crash-free oranımızı yüksek tutmamıza yardımcı oldu.</p><h4>Mimari olarak nerelere dikkat ettik?</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rpN8s-OQ08yJRM-6.png" /><figcaption><strong>Source</strong>: <a href="https://x.com/biz84/status/1506285698558660609">Andrea Bizzotto Tweet</a></figcaption></figure><p>Klasör yapımızı feature first yani özelliklere göre tercih ettik. Elbette bunun tercih etmemizin bir sebebi vardı. Andrea’nın tweette de bahsettiği gibi “Belirli bir özellik için, ihtiyaç duyduğumuz tüm dosyalar aynı üst düzey klasör içinde bulunmaktadır.” en başlıca sebeplerdendi.</p><blockquote>For a given feature, all the files we need are found inside the same top-level folder.</blockquote><p>Modüller (feature’lar) üzerinde çalışırken hepsini ayrı ayrı tutmaya çalıştık. Böylelikle ortak kullanılan yerler için ve örneğin sadece satışlar modülünde kullanılacak olan tüm sınıflarımızı, fonksiyonlarımız vs. ayırmış olduk.</p><p><em>Örneğin depoları getirmek için kullandığımız </em><strong><em>GetWarehousesUseCase </em></strong><em>sınıfı hem satışlar modülü hem de depo modülünde kullanılıyorsa bu tür ortak sınıfları </em><strong><em>common feature</em></strong><em> içerisine taşıdık.</em></p><p>Bu konuyu detaylı incelemek isterseniz Andrea’nın yazmış olduğu blog yazısını ve tweetin linkini aşağıya bırakıyorum:</p><p><a href="https://codewithandrea.com/articles/flutter-project-structure/">Flutter Project Structure: Feature-first or Layer-first?</a></p><iframe src="https://cdn.embedly.com/widgets/media.html?type=text%2Fhtml&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;schema=twitter&amp;url=https%3A//x.com/biz84/status/1506285698558660609&amp;image=" width="500" height="281" frameborder="0" scrolling="no"><a href="https://medium.com/media/c54c5bc46ec7b44c2c02acee98d565bc/href">https://medium.com/media/c54c5bc46ec7b44c2c02acee98d565bc/href</a></iframe><h4>Kullandığımız paketleri neden tercih ettik?</h4><p>Tabii ki bu başlığa önemli tercihlerden biri olan state managment ile başlamak istiyorum. Bloc paketini tercih etmemizin en temel sebepleri Bloc paketinin resmi dökümanında da belirtildiği gibi business logicleri, presentation katmanından ayırması, daha hızlı kodlanabilir olması, kolay test edilebilir olması ve yeniden kullanılabilir olması.</p><blockquote>Bloc makes it easy to separate presentation from business logic, making your code <em>fast</em>, <em>easy to test</em>, and <em>reusable</em>.</blockquote><p>Neden Bloc konusuna daha fazla bilgi edinmek isterseniz aşağıdaki resmi dökümanı göz gezdirebilirsiniz.</p><p><a href="https://bloclibrary.dev/why-bloc/">Why Bloc?</a></p><p>Paginated ve daha fazla evente sahip olan sayfalarda Bloc, çok büyük ve komplex olmayan kısımlar için Cubit tercih ettik.</p><p>Localization konusunda daha öncesinde çoğumuzun <a href="https://pub.dev/packages/easy_localization">easy_localization</a> paketinde deneyimi olduğu için bu paketi kullanmaya karar verdik. Tek bir komut ile json dosyasına eklediğimiz değerleri generate ederek çağırıyoruz. Easy localization…</p><ul><li><a href="https://pub.dev/packages/easy_localization">easy_localization | Flutter package</a></li><li><a href="https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization">Internationalizing Flutter apps</a></li></ul><p>Sizde deneyimlerinizi bizimle paylaşmak isterseniz, dinlemek isteriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*mqDhS4dhWxlosonR.gif" /><figcaption>Source: <a href="https://i.giphy.com/media/v1.Y2lkPTc5MGI3NjExZmRxZ3F1cmFnYmI0anExaGQ3ZTU3Mng2OHFqYzNlMTM5djQ2aTRpeSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/PlsZcNzfW6vQYBL1FS/giphy.gif">Spider-Man Thinking GIF by Sony Pictures Animation</a></figcaption></figure><p>Dependency injection için projemizde çok fazla tercih edilen getIt ve injectable paketlerini tercih ettik. <a href="https://medium.com/u/2d9b72765cfc">Buğra Göksu</a>’nun yazısında detaylı olarak kullanımı mevcut incelemek isterseniz linki aşağıya bırakıyorum.</p><ul><li><a href="https://medium.com/teamkraken/flutterda-getit-ve-injectable-ile-dependency-injection-pt-1-fb4dbfa3ad97">Flutter’da GetIt ve Injectable ile Dependency Injection Pt. 1</a></li><li><a href="https://pub.dev/packages/get_it">get_it | Dart package</a></li></ul><p>Navigation and routing konusu bizim için önemli olan diğer konulardan birisiydi. Çünkü uygulama içerisinde modüller arası geçişler, yani satış faturası detayından müşteri detay sayfasına geçişler yapılabilmektedir. Burada biz modül modül ilerlicez fakat native to flutter — flutter to native gibi routingleri nasıl sağlayacağız gibi soru işaretleri doğuyordu. Bu kısımda native ile iletişim sağlamak için MethodChannel kullandık. Tamamen Flutter’a geçiş yapana kadar hem native routing hem de auto_route paketini tercih ettik. Bu paketi tercih etmemizin temel sebebi kodlama tarafında bize hız kazandırmış olmasıydı.</p><p><a href="https://pub.dev/packages/auto_route">auto_route | Flutter package</a></p><p>AutoRoute paketi hakkında detaylı bilgi edinmek isterseniz Yaren Yıldırım’ın (<a href="https://medium.com/u/7ef45e688fd">leo</a>) yazısını okumanızı tavsiye ederim. Linki aşağıya bırakıyorum.</p><p><a href="https://medium.com/teamkraken/see-you-later-navigator-b1ee93b7b63e">AutoRoute ile Basitleştirilmiş Navigator 2.0</a></p><p>Diğer bir yazılım geliştirme süreçlerinden olan lint kuralları, kodun kalitesini artırmak ve ekip üyeleriyle kod yazımında tutarlılığı sağlamak, muhtemel hataları önlemek ve development sürecini optimize etmek için önemli bir role sahip. Biz projemizde technical discussion toplantılarımızda tartışarak karar verdiğimiz lint kurallarını kullanıyoruz. Projelerimizde kullandığımız Kraken Lint paketimiz mevcut ve yeni dart sürümlerinde eklenen lint kurallarını tartışıp ekleme veya çıkartmalar yapıyoruz.</p><p>Ayrıca önceden ücretsiz sürüm olan DCM yani Dart Code Metrics paketini de linter paketimizde kullanıyoruz. Güncel olan aracı incelemek isterseniz, aşağıya bağlantısını bıraktım:</p><ul><li><a href="https://dcm.dev/">DCM - Code Quality Tool for Flutter Developers</a></li><li><a href="https://medium.com/teamkraken/kraken-guideline-6ecc0a51d5">Kraken Guideline</a></li></ul><p>Son olarak önceden yazmış olduğum Kraken Guideline makalemi de yukarıya ekledim. Sanırım daha güncel bir makale daha yazmam gerekiyor :)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/498/0*hnVEef1c9ZdVAVYg.gif" /><figcaption>Source: <a href="https://tenor.com/view/spiderman-ps5-spiderman-miles-morales-spiderman-2-spiderman-spider-man-gif-3180222803682019157">Spiderman Ps5 Spiderman Miles Morales GIF</a></figcaption></figure><p>Logger ve Crashlytics tarafında yaklaşımımız ise <a href="https://medium.com/u/2d9b72765cfc">Buğra Göksu</a>’nun diğer bir makalesinde bahsettiği gibi <a href="https://pub.dev/packages/easy_logger">easy_logger</a> ve Firebase Crashlytics oldu.</p><blockquote>Local log süreci için ise kullandığımız paket <a href="https://pub.dev/packages/easy_logger">easy_logger</a> oldu. Bu paketi seçmemizdeki sebep aslında localization işlemleri için kullandığımız <a href="https://pub.dev/packages/easy_localization">easy_localization</a> paketinin içerisinde default olarak gelmesi. Bu yüzden başka bir paket ihtiyacı hissetmedik.</blockquote><p>Bu konuda <a href="https://medium.com/u/2d9b72765cfc">Buğra Göksu</a>’nun makalesi detaylı bir anlatıma sahip, bu nedenle okumanızı tavsiye ederim.</p><p><a href="https://medium.com/teamkraken/flutterda-firebasecrashlytics-ve-easylogger-ile-geli%C5%9Fmi%C5%9F-log-sistemi-f89d62c1222">Flutter’da FirebaseCrashlytics ve EasyLogger ile Gelişmiş Log Sistemi</a></p><h4>Test süreçlerimiz nasıldı?</h4><p>Öncelikle kod tarafındaki test süreçlerimizden bahsetmek istiyorum. State managment tarafında yukarıda da bahsettiğim gibi bloc kullandığımız için <a href="https://pub.dev/packages/bloc_test">bloc_test</a> paketini kullandık.</p><p><a href="https://pub.dev/packages/bloc_test">bloc_test | Dart package</a></p><p>Testlerimizi yaparken, sıkça kullanılan test tekniği olan ve genellikle bir sınıfın gerçek davranışını taklit etmek için kullanılan mock tekniğini kullandık. Bu tekniği kullanırken <em>dart.dev</em> tarafından yayınlanan <a href="https://pub.dev/packages/mockito">mockito</a> paketi yerine <em>bloc </em>paketinin geliştiricisi tarafından yayınlanan <a href="https://pub.dev/packages/mocktail">mocktail</a> paketini kullandık.</p><ul><li><a href="https://pub.dev/packages/mockito">mockito | Dart package</a></li><li><a href="https://pub.dev/packages/mocktail">mocktail | Dart package</a></li></ul><p>Ayrıca testlerimizde coverage önem verdik ve %80&#39;in üzerinde tutmaya özen gösterdik. Her geliştirmede, coverage yüzdesini yükseltmeye özen göstermeye devam ediyoruz.</p><p>Diğer kullandığımız tekniklerden biri olan golden test tekniğini de uyguladık. Golden test, yazılım geliştirme sürecinde görsel ya da çıktının beklentilere uygunluğunu kontrol etmek için kullanılır. Bu testi, UI bileşenlerinin doğru şekilde görüntülenip görüntülenmediğini kontrol etmek için yaptık. Ayrıca her sayfa ve senaryo için farklı testler ekledik.</p><p>Golden testler için <a href="https://pub.dev/packages/golden_toolkit">golden_toolkit</a> paketini tercih etmiştik fakat uzun süredir update almıyor hatta yakın zamanda “<strong>Discontinued</strong>” durumuna geçti. Şimdilik işimizi görüyor fakat yakın zamanda değişiklik için kraken olarak kendi aramızda bu konuyu tartışacağız. Sizin kullandığınız golden paketi veya tekniği varsa bizimle paylaşırsanız dinlemek isteriz.</p><p>Örnek bir golden testimizi sizinle paylaşmak istiyorum:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8TQyfYEHI0zR2Q8MAcjITQ.png" /></figure><p>Kod tarafında daha fazla test yazımımız ve pratiklerimiz için <a href="https://medium.com/u/2ce793a5c991">Berat Göktuğ Özdemir</a>’in yazmış olduğu makaleyi okumanızı ve Github üzerinden paylaştığı açık kaynaklı projesini incelemenizi şiddetle tavsiye ederim.</p><p><a href="https://bgoktugozdemir.medium.com/0-introduction-testing-in-flutter-54cee436aaa9">0: Introduction — Testing In Flutter</a></p><iframe src="https://cdn.embedly.com/widgets/media.html?type=text%2Fhtml&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;schema=twitter&amp;url=https%3A//x.com/BGoktugOzdemir/status/1508023515680751623&amp;image=" width="500" height="281" frameborder="0" scrolling="no"><a href="https://medium.com/media/1cd7e69e3d58f27ed449b3a2fc037a68/href">https://medium.com/media/1cd7e69e3d58f27ed449b3a2fc037a68/href</a></iframe><h4>Tüm bu süreçlerde hiç bug yok muydu?</h4><p>Yazılım geliştirme, dinamik ve karmaşık bir süreçtir. Hangi programlama dilini kullanırsak kullanalım, kodda hatalar “bug” ortaya çıkabilir. Bu hatalar, basit bir yazım yanlışı veya karmaşık bir mantık hatasından kaynaklanabilir.</p><p>Bazen, bir dilin sunduğu özellikler veya kullanılan kütüphaneler, beklenmedik sonuçlar doğurabilir. Bu nedenle, yazılımın karmaşıklığı ve dillerin çeşitliliği, her zaman hata yapma olasılığını beraberinde getirir. Dillerin çeşitliliğinden kastım bazı paketler cihazın sistemiyle iletişime geçmesi gerekebiliyor örneğin <a href="https://pub.dev/packages/permission_handler">permission_handler</a> paketi native ile iletişime geçiyor. Bu nedenle paket geliştirilirken başka dillerde kullanılmaktadır.</p><p>Önemli olan, bu hataları zamanında tespit etmek ve en erken zamanda çözmektir. Test süreçleri, kod gözden geçirmeleri ve kullanıcı geri bildirimleri, hataları tespit etmek ve düzeltmek için kritik araçlardır. Unutmayalım ki, buglar yazılım geliştirme sürecinin doğal bir parçasıdır. Onları kabul edip, öğrenerek daha iyi çözümler üretmek, yazılımcıların en büyük güçlerinden biridir. O durumlar için test yazmayı ihmal etmeyin 😊</p><p>Bu süreçte, testlerimizi yaparken gözden kaçabilecek hataları yakalamak ve kullanıcılarımızın uygulamayı kullanırken beklenmedik hatalarla karşılaştıklarında, kodda hata kaynağını tespit edebilmek için Firebase Crashlytics kullandık.</p><p>Yukarıda da bahsettiğim gibi <a href="https://medium.com/u/2d9b72765cfc">Buğra Göksu</a>’nun makalesini tekrardan paylaşıyorum.</p><p><a href="https://medium.com/teamkraken/flutterda-firebasecrashlytics-ve-easylogger-ile-geli%C5%9Fmi%C5%9F-log-sistemi-f89d62c1222">Flutter’da FirebaseCrashlytics ve EasyLogger ile Gelişmiş Log Sistemi</a></p><p>Crash-free, bir uygulamanın kullanıcı oturumları sırasında meydana gelen çökme olaylarının, toplam oturum sayısına oranını ifade etmektedir. Yüksek crash-free oranı, uygulamanın stabil olduğunu gösterirken, düşük oran, potansiyel sorunlar veya hatalar olduğunu gösteriyor olabilir.</p><p>Biz uygulamamızda hem Android hem iOS tarafında yüksek bir crash-free oranına sahip olmayı hedeflemiştik. Bizim minimum hedefimiz %90–95 arasındaydı. Hedefimizi tutturduğumuzu hatta beklediğimizden de yüksek olduğunu görünce inanılmaz derece mutlu olmuştuk. Sizlerle son 30 günün hem Android hem de iOS tarafında crash-free oranlarımızı paylaşmak istiyorum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wqxG7lzfAeeIzdpouFTE2A.png" /></figure><h4>Git hooks nereden çıktı şimdi?</h4><p>Git hooks, bazı komutlar verildiğinde otomatik olarak çalışan scriptlerdir. Bu sayede yazılım geliştirme sürecinizi daha verimli/tutarlı hale getirir. Yani, her commit veya push komutunu çalıştırdığınızda belirli işlemleri otomatikleştirebilirsiniz.</p><p>Kullanım amacımız, ekip içinde belirli bir guideline uyumunun sağlanmasının yanı sıra olası hataları önlemektir. Örneğin commit mesajlarımızın bir standart belirledik ve bu standarda uyum sağlıyoruz. İleride geriye dönük bir kod review yapıldığında, kodu ve yapılan işleri kolayca anlamak için Commit Türü: Yapılan İş (Proje-Issue Numarası) formatını kullanıyoruz. Örneğin feat: create button (MUKI-1905)bir commit mesajımız bu şekilde oluyor.</p><p>Ayrıca commitleri ekledikten sonra pushlarken ise testlerimizi çalıştırmayı ve testlerden herhangi birisi hata veriyorsa kodu gönderilmesini engelleyen bir scriptimiz mevcut. Böylelikle kodun bir yerleri bozmuş olmasını da engellemiş oluyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/480/0*OqP4FkiQu65e2YlK.gif" /><figcaption>Source: <a href="https://giphy.com/gifs/SpiderManMovie-spiderman-spidermannowayhome-no-way-home-oJFfKzLKROzhR8Vxuq">Yank Benedict Cumberbatch GIF by Spider-Man</a></figcaption></figure><h4>Store’da puan değişimimiz</h4><p>Flutter ile yeniden yazdığımız uygulamamız, App Store ve Google Play Store’da beklediğimizin çok ötesinde bir başarıya imza attı. Kullanıcı deneyimini ön planda tutarak gerçekleştirdiğimiz bu dönüşüm, sadece puanlarımızda belirgin bir artış sağlamakla kalmadı; aynı zamanda olumlu yorumların sayısında da gözle görülür bir artış yaşandı. Kullanıcılarımızdan gelen geri bildirimler, geliştirdiğimiz yeni özelliklerin ve tasarım değişikliklerinin ne denli etkili olduğunu bizlere gösteriyor. Onların memnuniyetini görmek, ekip olarak bizi son derece mutlu ediyor ve bu başarı, daha iyisini yapma konusunda bize büyük bir motivasyon kaynağı sağlıyor. Gelecekte, kullanıcılarımızın ihtiyaçlarına daha iyi cevap verebilmek için çalışmaya devam edeceğiz.</p><p><a href="https://tr.linkedin.com/posts/parasut_mutlu-patronlar%C4%B1m%C4%B1z%C4%B1n-yorum-ve-de%C4%9Ferlendirmeleri-activity-7249715618050916352-I2Nz">Paraşüt LinkedIn&#39;de: Mutlu Patronlarımızın yorum ve değerlendirmeleri karşısında biz: 🫠 🫠 🫠...</a></p><h4>Teşekkürler</h4><p>Emeği geçen ekip arkadaşlarıma teşekkürü borç bilirim. Team Kraken 💙🐙</p><p><strong>Team Kraken</strong> olarak düzenli bir şekilde paylaşımlarımıza devam edeceğiz.</p><p>Bizi aşağıdaki linklerden takip edebilirsiniz.✋🏻</p><ul><li><a href="https://twitter.com/_teamkraken_">Team Kraken Twitter</a> hesabı</li><li><a href="https://twitter.com/mukireuss">Twitter</a> hesabım</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/proxy/0*qBMKF6VSf8u8JSk_.gif" /><figcaption>Source: <a href="https://giphy.com/gifs/SpiderManMovie-spider-man-spider-man-no-way-home-spiderman-2021-2jSFDq9tXDwz5WN98K">High School Crowd GIF by Spider-Man</a></figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7a41d498786d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/teamkraken/ta%C5%9F%C4%B1n%C4%B1yoruz-nativeden-flutter-a-ge%C3%A7i%C5%9F-s%C3%BCrecinde-neler-ya%C5%9Fad%C4%B1k-7a41d498786d">Taşınıyoruz — Native’den Flutter’a geçiş sürecinde neler yaşadık?</a> was originally published in <a href="https://medium.com/teamkraken">Team Kraken</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: App Review [EN]]]></title>
            <link>https://medium.com/teamkraken/flutter-app-review-en-b1245e8afe14?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/b1245e8afe14</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[app-review]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Tue, 01 Oct 2024 11:29:26 GMT</pubDate>
            <atom:updated>2024-10-01T11:29:26.740Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0C8aGVOV4LL6M5E9xdoJvA.jpeg" /></figure><p>Hi everyone! In this article, your applications in the Play Store and App Store; I will talk about the structure where the user can star and add comments within the application without going to the store.</p><p>The review flow can be triggered at any time within the app. During the stream, the user can rate your application 1 to 5 stars and add comments if desired. After the user submits the review, it can be viewed in the store.</p><p>You can examine the sample flow in detail in the image below. The idea belongs to the Google Play stream, which is the Android store.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aX1He8cPfrk8tzgw.jpg" /><figcaption>Photo by <a href="https://developer.android.com/guide/playcore/in-app-review">Google Play In-App Reviews API</a></figcaption></figure><h4>App Review Flutter Package</h4><p>There are multiple packages for the App Review feature in <a href="https://pub.dev/">pub.dev</a>, which is the official package site that we can use in our Dart and Flutter projects.</p><p>When we type “app review” in the <a href="https://pub.dev/">pub.dev</a> search section, we see that <a href="https://pub.dev/packages/in_app_review">in_app_review</a> and <a href="https://pub.dev/packages/app_review">app_review</a> packages stand out among the packages found in the results.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/709/1*kVpoXcC8BjbCXQz8RcI4Hg.png" /><figcaption>“app review” results found on <a href="https://pub.dev/">pub.dev</a> (13.11.2022)</figcaption></figure><p>In this article, I will talk about the use of the <a href="https://pub.dev/packages/app_review">app_review</a> package. But with the <strong>AppReviewManager </strong>class structure I will explain, even if you change the package, you will be able to continue using it by spending very little time.</p><blockquote>The reason I prefer this package is that the <a href="https://pub.dev/packages/in_app_review">in_app_review</a> package has not been updated for about 10 months. Maybe it got an update while you were reading this article :)</blockquote><h4>Let’s add it to our application</h4><p>First, we open our Flutter project, where we want to add the App Review feature. There are two methods for adding the package to our project:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Ftenor.com%2Fembed%2F22604801&amp;display_name=Tenor&amp;url=https%3A%2F%2Ftenor.com%2Fview%2Fdoctor-strange-dr-strange-strange-benedict-cumberbatch-avengers-gif-22604801&amp;image=https%3A%2F%2Fmedia.tenor.com%2FbuXObXzYetMAAAAM%2Fdoctor-strange-dr-strange.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=tenor" width="600" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/bc8a48e980fbf697dcc4f23cce5fa462/href">https://medium.com/media/bc8a48e980fbf697dcc4f23cce5fa462/href</a></iframe><p>The first method is to run the following command in the terminal.</p><pre>flutter pub add app_review</pre><p>In the second method, we open the pubspec.yaml file in our project and add it to the dependencies section.</p><pre>dependencies:<br> app_review: ^2.1.2+1</pre><p>After adding it we have to run the following command in the terminal.</p><pre>flutter pub get</pre><h4>Let’s create the AppReviewManager class</h4><p>In this section, before we start the development, we need to create the functions we need as a draft. For example, we need to send a request so that the user can see the review flow in the application. We will create a function for this request.</p><p>After thinking in this way, we add the functions we need to our class for now.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44c5949be8004542c45484c4dd51fa6e/href">https://medium.com/media/44c5949be8004542c45484c4dd51fa6e/href</a></iframe><h4>Let’s create the DefaultAppReviewManager class</h4><p>When using our functions that we created with the abstract class, we will call them with the naming here. Next, we will write a class that forces the use of the functions in the AppReviewManager class, where we will define the tasks of these functions.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6630c705b9a69ed5ccda4897df2d2a8c/href">https://medium.com/media/6630c705b9a69ed5ccda4897df2d2a8c/href</a></iframe><p>After filling our functions, we can proceed with their use.</p><h4>Using AppReview</h4><p>On the page where we want to call the functions, we must create a variable of type AppReviewManager.</p><pre>AppReviewManager appReviewManager = DefaultAppReviewManager();</pre><p>Then all we have to do is call the function.</p><pre>onPressed: (){<br>  appReviewManager.requestReview();<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*UsT_irfw_L5wCVfC.PNG" /><figcaption>Photo from <a href="https://pub.dev/packages/app_review">app_review</a> package site</figcaption></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FzGnnFpOB1OjMQ%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FzGnnFpOB1OjMQ%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FzGnnFpOB1OjMQ%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="195" frameborder="0" scrolling="no"><a href="https://medium.com/media/4bcdf625c27e34993bd76a34472eb765/href">https://medium.com/media/4bcdf625c27e34993bd76a34472eb765/href</a></iframe><h4>Easy to use different packages and refactor</h4><p>As I mentioned at the beginning of the article, if you want to use a different package, all you have to do is create a class such as the DefaultAppReviewManager class and create a variable from the class we just created. Since the function name will be the same everywhere, we will update it without making any changes.</p><pre>AppReviewManager appReviewManager = NewAppReviewManager();</pre><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F3ohs86gV8fun7pmioE%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F3ohs86gV8fun7pmioE%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2F3ohs86gV8fun7pmioE%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="252" frameborder="0" scrolling="no"><a href="https://medium.com/media/e82b9a5f67b447156c618cd6590ed505/href">https://medium.com/media/e82b9a5f67b447156c618cd6590ed505/href</a></iframe><p>Thank you for taking the time to read this article. I hope it is helpful. As <strong>Team Kraken</strong>, we will continue to share regularly.</p><p>You can follow us using the links below. ✋🏻</p><ul><li><a href="https://twitter.com/_teamkraken_">Team Kraken Twitter</a> account</li><li>My <a href="https://twitter.com/mukireuss">Twitter</a> account</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b1245e8afe14" width="1" height="1" alt=""><hr><p><a href="https://medium.com/teamkraken/flutter-app-review-en-b1245e8afe14">Flutter: App Review [EN]</a> was originally published in <a href="https://medium.com/teamkraken">Team Kraken</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: App Review]]></title>
            <link>https://medium.com/teamkraken/flutter-app-review-ad03cf2759d5?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/ad03cf2759d5</guid>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[app-review]]></category>
            <category><![CDATA[app-store]]></category>
            <category><![CDATA[play-store]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Thu, 22 Dec 2022 08:32:44 GMT</pubDate>
            <atom:updated>2022-12-22T08:34:17.482Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0C8aGVOV4LL6M5E9xdoJvA.jpeg" /></figure><p>Herkese selam! Bu yazımda, Google Play Store ve Apple App Store’da bulunan uygulamalarınızın; kullanıcının mağazaya gitmesine gerek kalmadan uygulama içerisinde oy verebilmesini ve yorum ekleyebilmesini sağlayan bu özellikten bahsedeceğim.</p><p>Uygulama içerisinde herhangi bir zamanda inceleme akışı tetiklenebilir. Akış sırasında kullanıcı, 1 ila 5 yıldız arasında kullanıcı dilediği rakamı kullanarak uygulamanızı puanlayabilir ve hatta isterse yorum ekleyebilmektedir. İnceleme kullanıcı tarafından gönderildikten sonra mağazada görüntülenir.</p><p>Örnek akışı, aşağıdaki görselde detaylı inceleyebilirsiniz. Görsel Android mağazası olan Google Play’e aittir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aX1He8cPfrk8tzgw.jpg" /><figcaption>Photo by <a href="https://developer.android.com/guide/playcore/in-app-review">Google Play In-App Reviews API</a></figcaption></figure><h4>App Review Flutter Paketi</h4><p>Dart ve Flutter projelerimizde kullanabileceğimiz resmi paket sitesi olan <a href="https://pub.dev/">pub.dev</a> içerisinde, <strong>App Review </strong>özelliği için birden fazla paket bulunmaktadır.</p><p><a href="https://pub.dev/">pub.dev</a> arama kısmına “app review” yazdığımız zaman sonuçlarda bulunan paketlerden, <a href="https://pub.dev/packages/in_app_review">in_app_review</a> ve <a href="https://pub.dev/packages/app_review">app_review</a> paketlerinin öne çıktığını görüyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/709/1*kVpoXcC8BjbCXQz8RcI4Hg.png" /><figcaption><a href="https://pub.dev/">pub.dev</a> sitesinde bulunan “app review” sonuçları (13.11.2022)</figcaption></figure><p>Bu yazımda ise <a href="https://pub.dev/packages/app_review">app_review</a> paketinin kullanımından bahsedeceğim. Fakat anlatacağım <strong>AppReviewManager </strong>sınıf yapısı ile paket değiştirseniz dahi çok az zaman harcayarak kullanmaya devam edebileceksiniz.</p><blockquote>Bu paketi tercih etme sebebim ise <a href="https://pub.dev/packages/in_app_review">in_app_review</a> paketinin yaklaşık 10 aydır update almamış olmasından ve <a href="https://pub.dev/packages/app_review">app_review</a> paketinin arkasında Flutter Community’sinin olmasından kaynaklanmaktadır. Belki siz bu yazıyı okurken güncelleme almış olabilir :)</blockquote><h4>Uygulamamıza ekleyelim</h4><p>İlk olarak <strong>App Review </strong>özelliğini eklemek istediğimiz Flutter projemizi açıyoruz. Paketin projemize eklenmesi için iki yöntem bulunmaktadır:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Ftenor.com%2Fembed%2F22604801&amp;display_name=Tenor&amp;url=https%3A%2F%2Ftenor.com%2Fview%2Fdoctor-strange-dr-strange-strange-benedict-cumberbatch-avengers-gif-22604801&amp;image=https%3A%2F%2Fmedia.tenor.com%2FbuXObXzYetMAAAAM%2Fdoctor-strange-dr-strange.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=tenor" width="600" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/bc8a48e980fbf697dcc4f23cce5fa462/href">https://medium.com/media/bc8a48e980fbf697dcc4f23cce5fa462/href</a></iframe><p>İlk yöntem olarak aşağıdaki komutu terminalde çalıştırıyoruz.</p><pre>flutter pub add app_review</pre><p>2. yöntem ise, projemizde bulunan pubspec.yaml dosyamızı açıyoruz ve dependencies kısmına aşağıdaki kodu ekliyoruz.</p><pre>dependencies:<br> app_review: ^2.1.2+1</pre><p>Ekledikten sonra aşağıdaki komutu terminalde çalıştırmalıyız.</p><pre>flutter pub get</pre><h4>AppReviewManager sınıfını oluşturalım</h4><p>Bu kısımda, geliştirmeye başlamadan önce bizim ihtiyacımız olan fonksiyonları taslak olarak oluşturmamız gerekiyor. Örneğin, uygulama içerisinde kullanıcı inceleme akışını görebilmesi için istek atmamız gerekiyor. Bu istek için bir fonksiyon oluşturacağız.</p><p>Bu şekilde düşündükten sonra şimdilik ihtiyacımız olan fonksiyonları sınıfımıza ekliyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/44c5949be8004542c45484c4dd51fa6e/href">https://medium.com/media/44c5949be8004542c45484c4dd51fa6e/href</a></iframe><h4>DefaultAppReviewManager sınıfını oluşturalım</h4><p>abstract class ile oluşturduğumuz fonksiyonlarımızı kullanırken burada ki isimlendirmeler ile çağıracağız. Sırada ise bu fonksiyonların görevlerini vereceğimiz AppReviewManager sınıfındaki fonksiyonların kullanımına zorlayan bir sınıf yazmak olacaktır.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6630c705b9a69ed5ccda4897df2d2a8c/href">https://medium.com/media/6630c705b9a69ed5ccda4897df2d2a8c/href</a></iframe><p>Fonksiyonlarımızı doldurduktan sonra kullanımına geçebiliriz.</p><h4>AppReview kullanımı</h4><p>Fonksiyonları çağırmak istediğimiz sayfada AppReviewManager tipinde bir değişken oluşturmalıyız.</p><pre>AppReviewManager appReviewManager = DefaultAppReviewManager();</pre><p>Ardından tek yapmamız gereken fonksiyonu çağırmak.</p><pre>onPressed: ()=&gt; appReviewManager.requestReview(),</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/750/0*UsT_irfw_L5wCVfC.PNG" /><figcaption>Photo from <a href="https://pub.dev/packages/app_review">app_review</a> package site</figcaption></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FzGnnFpOB1OjMQ%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FzGnnFpOB1OjMQ%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FzGnnFpOB1OjMQ%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="195" frameborder="0" scrolling="no"><a href="https://medium.com/media/4bcdf625c27e34993bd76a34472eb765/href">https://medium.com/media/4bcdf625c27e34993bd76a34472eb765/href</a></iframe><h4>Farklı paket kullanımı ve refactor kolaylığı</h4><p>Yazının başlarında da bahsettiğim gibi farklı bir paket kullanmak isterseniz tek yapmanız gereken DefaultAppReviewManager sınıfı gibi bir sınıf oluşturmak ve yeni oluşturduğumuz sınıftan değişken oluşturmak olacaktır. Fonksiyon ismi aynı olacağı için her yerde değişiklik yapmadan güncellemiş olacağız.</p><pre>AppReviewManager appReviewManager = InAppReviewManager();</pre><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F3ohs86gV8fun7pmioE%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F3ohs86gV8fun7pmioE%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2F3ohs86gV8fun7pmioE%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="252" frameborder="0" scrolling="no"><a href="https://medium.com/media/e82b9a5f67b447156c618cd6590ed505/href">https://medium.com/media/e82b9a5f67b447156c618cd6590ed505/href</a></iframe><p>Zamanınızı ayırıp bu yazıyı okuduğunuz için teşekkür ederim, faydalı olması dileğiyle. <strong>Team Kraken</strong> olarak düzenli bir şekilde paylaşımlarımıza devam edeceğiz.</p><p>Bizi aşağıdaki linklerden takip edebilirsiniz.✋🏻</p><ul><li><a href="https://twitter.com/_teamkraken_">Team Kraken Twitter</a> hesabı</li><li><a href="https://twitter.com/mukireuss">Twitter</a> hesabım</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ad03cf2759d5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/teamkraken/flutter-app-review-ad03cf2759d5">Flutter: App Review</a> was originally published in <a href="https://medium.com/teamkraken">Team Kraken</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Kraken Guideline]]></title>
            <link>https://medium.com/teamkraken/kraken-guideline-6ecc0a51d5?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/6ecc0a51d5</guid>
            <category><![CDATA[product]]></category>
            <category><![CDATA[kraken]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[dart]]></category>
            <category><![CDATA[guidelines]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Thu, 02 Jun 2022 08:16:15 GMT</pubDate>
            <atom:updated>2022-06-02T08:17:32.660Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*096OVuQnyai8B366E5vmDA.png" /></figure><p>Herkese selam! Bu yazımda, “Proje geliştirirken nelere dikkat ediyoruz?” konu başlığını birkaç maddeye ayırarak bahsedeceğim. Bu konuyu seri haline getirmek istiyorum. Serinin ilk yazısında kullandığımız lint kuralları ve dikkat ettiklerimiz konu başlığına değineceğim.</p><h4>Kod yazarken nelere dikkat ediyoruz?</h4><p>Bildiğiniz üzere biz mobil ekip olarak, projelerimizde Flutter kullanıyoruz. Bu yüzden bu seride anlatılan kod kuralları Flutter/Dart ile ilgili olacaktır.</p><ul><li><strong>Kullanılmayan import satırlarını dosyalardan kaldırıyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cEpXEHTqTmwQqZ0_gDBI8g.png" /></figure><p>Kullanılmayan import satırlarını kaldırmamızın başlıca sebeplerinden birisi temiz kod yani clean code prensiplerine uymaya çalışıyoruz. Diğer bir sebep olarak, her ne kadar derleme sırasında “tree-shaking” ile kaldırılacak olsa da, derleme süresini arttırması olası.</p><ul><li><strong>Print fonksiyonu kullanmıyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vnPakQrQgxduxYpWMfOf1A.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Id2Fsd1ItoENuoTlRO4YNg.png" /></figure><p>Print fonksiyonu yerine, Team Kraken olarak geliştirdiğimiz “Logger” sınıfımızda bulunan fonksiyonları kullanıyoruz. Debug mod ve production mod için farklı sınıflarımız bulunmaktadır. Log için easy_logger paketini kullanıyoruz.</p><p><a href="https://pub.dev/packages/easy_logger">easy_logger | Flutter Package</a></p><p>Ek olarak, <a href="https://dart-lang.github.io/linter/lints/avoid_print.html">avoid_print</a> lint kuralını kullanıyoruz.</p><p>Log sistemimiz ile ilgili detaylı bilgi almak isterseniz, takım arkadaşım <a href="https://medium.com/u/2d9b72765cfc">Buğra Göksu</a>’nun yazdığı “<strong>Flutter’da FirebaseCrashlytics ve EasyLogger ile Gelişmiş Log Sistemi</strong>” makalesini okuyabilirsiniz.</p><p><a href="https://medium.com/teamkraken/flutterda-firebasecrashlytics-ve-easylogger-ile-geli%C5%9Fmi%C5%9F-log-sistemi-f89d62c1222">Flutter’da FirebaseCrashlytics ve EasyLogger ile Gelişmiş Log Sistemi</a></p><ul><li><strong>Kod içerisinde TODO kullanmıyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KB910Je_aPppTnE3Jmrt_Q.png" /></figure><p>TODO yorum satırları yerine proje yönetiminde kullandığımız araç üzerinde, yapacağımız işlemi detaylı ve gerekirse görsel ile anlatım şeklinde issue oluşturuyoruz. Böylece yapacağımız task, planlanarak sprint içerisine ekleniyor.</p><ul><li><strong>Parametresiz Container widget ile sarmaktan kaçınıyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oePs0GqPa_E-3EG4ULA2sg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mb8FzKRoU4Gy3I11zBsevA.png" /></figure><p>Bir widget’ı başka parametresi olmadan Container ile sarmanın hiçbir etkisi yoktur ve kodu gereksiz yere daha karmaşık hale getirir. Bu durumu gözden kaçırmamak için linter paketimize avoid_unnecessary_containers kuralını ekledik.</p><p><a href="https://dart-lang.github.io/linter/lints/avoid_unnecessary_containers.html">avoid_unnecessary_containers</a></p><ul><li><strong>Boşluk eklerken SizedBox kullanıyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Rt-jN-sCi-Ux6kHp" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*cyeZol9QFGXvIxuZ" /></figure><p>Layout içerisinde boşluk eklemek için Container ve Padding yerine SizedBox kullanıyoruz. Container, SizedBox’a nazaran maliyetli bir widget’tır ve bonus olarak, SizedBox’ın bir const kurucusu vardır.</p><p>Daha detaylı olarak Container ve SizedBox arasındaki farkı incelemek isterseniz aşağıdaki linke tıklayarak ulaşabilirsiniz 🙏</p><p><a href="https://stackoverflow.com/questions/55716322/flutter-sizedbox-vs-container-why-use-one-instead-of-the-other">Flutter: SizedBox Vs Container, why use one instead of the other?</a></p><p>Bu durum için linter paketimizde ekli olan sized_box_for_whitespace kuralından faydalanıyoruz.</p><p><a href="https://dart-lang.github.io/linter/lints/sized_box_for_whitespace.html">sized_box_for_whitespace</a></p><ul><li><strong>Yalnızca BoxDecoration eklerken Container yerine DecoratedBox tercih ediyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4pBpV_UGQqt_TNmI" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*avw-S5IvmGKbO5qB" /></figure><p>Container, DecoratedBox’tan daha maliyetli bir widget’tır ve bonus olarak, DecoratedBox’ın bir const kurucusu vardır.</p><p>Linter paketimizde bu durum içinde bir kural mevcut : use_decorated_box</p><p><a href="https://dart-lang.github.io/linter/lints/use_decorated_box.html">use_decorated_box</a></p><ul><li><strong>Yalnızca Color eklerken Container yerine ColoredBox tercih ediyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/371/1*VqktNgHMFMeScy3OtcUUqA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/380/1*Cu3FOy-6uIfvwz3RV5YxjA.png" /></figure><p>Daha önce de belirttiğim gibi Container maliyetli bir widget. Yalnızca renk parametresi olan color tanımlarken Container yerine ColoredBox kullanıyoruz. Ek olarak ColoredBox ’ın bir const kurucusu var.</p><p>Tabii ki bunun içinde bir lint kuralımız mevcut. use_colored_box kuralını kullanıyoruz 🎉</p><p><a href="https://dart-lang.github.io/linter/lints/use_colored_box.html">use_colored_box</a></p><ul><li><strong>Birden fazla parametre olduğunda sona virgül ekliyoruz.</strong></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/0*ekILcSlIO71EgsEJ" /></figure><p>Fonksiyon isminin başlangıcından kapanış parantezine kadar olan fonksiyon çağrısı veya tanımı tek bir satıra sığmıyorsa ve okunurluğu azaltıyorsa, tüm bunlar için sona virgül ekliyoruz.</p><p>Sonunda virgül bulunan kodun, okunurluğu nasıl değiştirdiğini <a href="https://docs.flutter.dev/development/tools/formatting#using-trailing-commas"><em>Flutter</em> sitesindeki <em>Code formatting</em></a> sayfasında bulunan aşağıdaki örnekte inceleyelim:</p><figure><a href="https://docs.flutter.dev/development/tools/formatting#using-trailing-commas"><img alt="" src="https://cdn-images-1.medium.com/max/625/0*00lDpYZk28YJJWaT.png" /></a><figcaption>Virgül eklenmemiş kod örneği</figcaption></figure><figure><a href="https://docs.flutter.dev/development/tools/formatting#using-trailing-commas"><img alt="" src="https://cdn-images-1.medium.com/proxy/0*PFbem2Bu6cdTXv9f.png" /></a><figcaption>Virgül eklenmiş kod örneği</figcaption></figure><p>Bu durum için virgül lint kuralı olan require_trailing_commas kuralını, linter paketimizde kullanıyoruz.</p><p><a href="https://dart-lang.github.io/linter/lints/require_trailing_commas.html">require_trailing_commas</a></p><ul><li><strong>Widget içerisinde fonksiyonların sıralanması</strong></li></ul><p>Uygulama geliştirirken dikkat ettiğimiz diğer hususlardan biri de fonksiyonların sıralamalarıdır. Aşağıdaki örnek görselde sıralamayı ekledim. Sıralamayı aşağıdaki kurallara göre dikkat ediyoruz:</p><ul><li>Olmazsa olmaz olan fonksiyonlar olan initState(), didChangeDependencies() ve dispose() gibi override olan methodları en üst kısımda alfabetik olarak sıralıyoruz.</li><li>Hemen ardından diğer olmazsa olmaz fonksiyon olan build() ekliyoruz.</li><li>Yukarıdaki fonksiyonlardan sonra sınıf içerisinde kullandığımız diğer fonksiyonları alfabetik olarak örnekteki gibi sıralıyoruz.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/485/0*mQIOinTaBJ0SwTzf" /></figure><ul><li><strong>Kod satır uzunluğu değeri 120 olarak kullanıyoruz.</strong></li></ul><p>Yazdığımız kodları formatlarken satır uzunluğu yani <strong>Dart: Line Length </strong>değerini 120 olarak düzenledik. Aşağıda formatlanmamış uzun satırlı bir kod görmekteyiz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/988/0*4mku7aSbYOCGQ-dQ" /></figure><p>Yukarıdaki kodun aynısını formatlanmış bir şekilde aşağıda görebiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/342/0*gmc-fWvvLco9R5FO" /></figure><p>Eğer VS Code kullanıyorsanız bu şekilde düzenleyebilirsiniz:</p><ul><li>VS Code uygulamasında ayarlar butonuna ardından Settings seçeneğine tıklıyoruz.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/325/1*OGekD27mbfAZvCKgcr8vEQ.png" /></figure><ul><li>Ardından açılan sekmede arama alanına Dart line length yazarak filtreliyoruz ve çıkan sonuçlarda bulunan değeri değiştiriyoruz. (Default olarak değer 80&#39;dir).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/633/1*CZLT76JbB9VkDHyN95bT4g.png" /></figure><p>Şimdilik anlatacaklarım bu kadar fakat yazının başında da belirttiğim gibi bu başlığı bir seri haline getirmek istiyoruz. En kısa zamanda yeni yazı çalışmalarına başlayacağız 🎉</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FQAcSylF6vYV4UD4O23%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FQAcSylF6vYV4UD4O23%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FQAcSylF6vYV4UD4O23%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/893e3c55f7bcc9ddefa1f4cebdedc5a9/href">https://medium.com/media/893e3c55f7bcc9ddefa1f4cebdedc5a9/href</a></iframe><p>Zamanınızı ayırıp bu yazıyı okuduğunuz için teşekkür ederim, faydalı olması dileğiyle. <strong>Team Kraken</strong> olarak düzenli bir şekilde paylaşımlarımıza devam edeceğiz.</p><p>Bizi aşağıdaki linklerden takip edebilirsiniz.✋🏻</p><ul><li><a href="https://twitter.com/_teamkraken_">Team Kraken Twitter</a> hesabı</li><li><a href="https://twitter.com/mukireuss">Twitter</a> hesabım</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ecc0a51d5" width="1" height="1" alt=""><hr><p><a href="https://medium.com/teamkraken/kraken-guideline-6ecc0a51d5">Kraken Guideline</a> was originally published in <a href="https://medium.com/teamkraken">Team Kraken</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Widgetbook]]></title>
            <link>https://medium.com/teamkraken/flutter-widgetbook-e885f607f9dc?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/e885f607f9dc</guid>
            <category><![CDATA[widget]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[storybook]]></category>
            <category><![CDATA[widgetbook]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Thu, 23 Dec 2021 12:56:41 GMT</pubDate>
            <atom:updated>2021-12-23T12:56:41.328Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sjr0-mqL-BqdIrdF96-i4A.png" /><figcaption>Örnek bir uygulamanın Widgetbook’unun ekran görüntüsü</figcaption></figure><blockquote>Bu yazı, <a href="https://medium.com/flutter-community/widgetbook-the-storybook-for-flutter-7d27c26c0420">Widgetbook — The Storybook for Flutter</a> makalesinden izin alınarak derlenip, Türkçe’ye çevirilmiştir.</blockquote><p>Bu yazıda <a href="https://pub.dev/packages/widgetbook">widgetbook</a> paketinin kullanımından bahsedeceğim. Developerlar, widgetlarını kataloglamasına, farklı cihazlarda ve temalarda hızlıca test etmesine; tasarımcılar ve müşterilerle kolayca paylaşmasına yardımcı olan Flutter ile yazılmış açık kaynak kodlu pakettir.</p><h3>Widgetbook kullanım senaryoları (Use cases)</h3><h4>Widgetları ayrı ayrı oluşturun ve görsel olarak test edin</h4><p>Widgetbook, UI’ları ayrı ayrı oluşturmak için bir ortam sağlamaktadır. Widgetbook’un kullanıcı arayüzünde widgetları farklı cihazlarda ve temalarda görsel olarak hızlı bir şekilde ön izleyebilir ve test edebilirsiniz. Birden fazla emülator çalıştırmadan, geliştirme yaparken UI kusurları, bugları tespit edebilirsiniz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KL58dV6pq7atyuR2.gif" /><figcaption>Bu örnekte, Widget RecipeInfo yalnızca “Short name” kullanım senaryosu için uygun şekilde uygulanmaktadır. Kullanıcı bu Widgeta uzun bir isim atadığında her iki cihazda da taşma olur.</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AJYnLsVhxguyOy7o.gif" /><figcaption>Bu örnekte, AddIngredientScreen yalnızca light theme tasarım için uygun şekilde uygulanmaktadır. Karanlık tasarımın tasarım kusurları, Widgetbook kullanılarak hızla fark edilebilir.</figcaption></figure><h4>Tüm widgetlarınıza genel bakış</h4><p>Uygulamanız büyüdüğünde ve daha fazla geliştirici uygulama üzerinde çalıştığında, uygulamanızdaki tüm widgetları takip etmek zorlaşıyor. Bu noktada bazı widgetların geliştirilip geliştirilmediğini, en iyi adlandırma kurallarına uymuş olsa bile sorgulamasını engelleyemez. Genellikle bu tür kafa karıştırıcı yapılar kaosa ve geliştiricilerin birden çok kez aynı widgetları oluşturmasına neden olabiliyor.</p><p>Widgetbook’u kullanarak, tüm widgetlarınızı ve ekranlarınızı ve bunların kullanım durumlarını (use case) hızlı bir şekilde önizleyebilirsiniz:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JgqsD0rOSJhvvqrzx3bfHQ.gif" /><figcaption>Geliştiriciler, tüm widgetlarını ve ekranlarını Widgetbook’ta sergileyebilir.</figcaption></figure><h3>Widgetbook nasıl kullanılır?</h3><p>Detaylı dökümantasyona <a href="https://pub.dev/packages/widgetbook">pub.dev</a>’deki paketin sayfasından erişebilirsiniz. Widgetbook’unuzu iki şekilde kurabilir ve bakımını yapabilirsiniz. Birincisi manuel olarak widgetları ekleyerek, ikincisi ise bazı paketlerden alışık olduğumuz annotation ları kullanarak code generation ile hızlı bir şekilde otomatik olarak oluşturabilirsiniz. Eğer ikinci seçeneği tercih ederseniz projeye <a href="https://pub.dev/packages/widgetbook_annotation">widgetbook_annotation</a> ve <a href="https://pub.dev/packages/widgetbook_generator">widgetbook_generator</a> paketlerini de eklemeniz gerekecektir.</p><h4>Widgetbook’unuzu kolayca kurmak ve bakım yapmak için annotationları kullanın</h4><p><strong>@WidgetbookApp</strong></p><p>@WidgetbookApp annotationı yalnızca bir kez ayarlanmalıdır ve kod oluşturma işlemi için zorunludur. Hangi elemente annotation eklendiğinin bir önemi yok fakat @WidgetbookApp kullanıldığı dosyanın konumu, widgetbook_generator paketinin oluşturacağı app.widgetbook.main dosyasının bulunacağı klasörünü tanımlar. app.widgetbook.main dosyası Widgetbook uygulamasını çalıştırmak için otomatik oluşturulmuş tüm kodları içermektedir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/744/1*-GH3LcmAGPbW4FG1lej0zg.png" /></figure><p><em>İçerdiği parametreler</em></p><p>@WidgetbookApp annotationı bir required parametre olan name ve bir de isteğe bağlı devices parametrelerine sahiptir.</p><p>Widgetbook generator, AppInfo oluştururken name parametresinden yararlanacaktır. Widgetbook uygulamanızı çalıştırdığınızda sol üst köşede görünecektir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/299/1*dMrZG-l1m52AIIl4lxIjlw.png" /></figure><p>Aynı zamanda widgetbook generator, uygulamanızda widgetları önizleyebileceğiniz devices parametresine eklediğiniz cihazları oluşturacaktır.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fd33f7700329e62a7098f01c7281b436/href">https://medium.com/media/fd33f7700329e62a7098f01c7281b436/href</a></iframe><p><strong>@WidgetbookUseCase</strong></p><p>@WidgetbookUseCase annotationı, geliştiricilerin fonksiyonları bir kullanım durumu yani usecase olarak işaretlemesine olanak tanır. Bu annotation bir fonksiyona uygulanmalıdır ve bu fonksiyon BuildContext’e sahip olmalıdır.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/813feef369f8251cf3b28809918b67ac/href">https://medium.com/media/813feef369f8251cf3b28809918b67ac/href</a></iframe><p>ya da lambda ifadesi ile tanımlayabilirsiniz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0bd4dd94b137aac35034bcd5c1382a08/href">https://medium.com/media/0bd4dd94b137aac35034bcd5c1382a08/href</a></iframe><p><em>İçerdiği parametreler</em></p><p>@WidgetbookUseCase annotationı iki adetrequired tipinde, name ve type isimli parametrelere sahiptir.</p><p>name parametresi, Widgetbook uygulamamızın sol tarafında bulunan gezinme panelinde kullanım durumunun nasıl görüntüleneceğini belirtmektedir.</p><p>type parametresi ise, kullanım durumunun yani usecase hangi widget tipine ait olduğunu belirtir. Widgetbook generator, bu bilgilerden ve bulundukları dosyanın konumundan faydalanarak, sol tarafta gezinme panelini oluşturucaktır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/365/1*mv2WzV6QTXVAOSj3Hebg7A.png" /></figure><p><em>Örneğin</em></p><p>Dosya yapısının şöyle göründüğünü varsayalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/38a06bb9741fcb76dbd97d54089f4384/href">https://medium.com/media/38a06bb9741fcb76dbd97d54089f4384/href</a></iframe><p>/lib/tiles/awesome_tile.dart dosyası içerisinde bulunan AwesomeTile usecase örneği için, aşağıdaki gibi tanımlandığını varsayalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de970af284542ffd60ec477e72e1d834/href">https://medium.com/media/de970af284542ffd60ec477e72e1d834/href</a></iframe><p>Genellikle widgetınız daha complex bir yapıya sahip olabiliyor. Böyle bir durumda, widgetı ihtiyacınız olan şeylerle sarmaktan çekinmeyin. Bu, Provider, Bloc veya başka bir state management widgeti olabilir.</p><p>Widgetbook için kod oluşturduktan sonra, aşağıdaki içeriğe sahip bir gezinme paneli bulacaksınız.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d40a3132718d1df767e58cb2bb9ade40/href">https://medium.com/media/d40a3132718d1df767e58cb2bb9ade40/href</a></iframe><p>Bir widget için birden fazla kullanım senaryonuz varsa, birden çok @WidgetbookUseCase tanımlayabilirsiniz. Widgetbook içerisinde bu durumları da ayrıca görüntüleyebilirsiniz.</p><p><strong>@WidgetbookTheme</strong></p><p>@WidgetbookTheme, geliştiricilerin uygulamalarının açık ve koyu temasına annotation eklemesine olanak tanır. @WidgetbookUseCase gibi, @WidgetbookTheme bir ThemeData nesnesi döndüren methodlarda kullanılır.</p><p><em>Constructors</em></p><p>@WidgetbookTheme, Widgetbook uygulamamızın açık ve koyu teması arasında ayrım yapmak için @WidgetbookTheme.light() ve @WidgetbookTheme.dark() adlı iki constructora sahiptir.</p><p><em>Örneğin</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/878a3b6697416b7af6fd84281901a01b/href">https://medium.com/media/878a3b6697416b7af6fd84281901a01b/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EjgWTTcTKWmtoSs95duO8w.gif" /></figure><h4>Widgetbook Paketleri</h4><ul><li><a href="https://pub.dev/packages/widgetbook">widgetbook | Flutter Package</a></li><li><a href="https://pub.dev/packages/widgetbook_annotation">widgetbook_annotation | Dart Package</a></li><li><a href="https://pub.dev/packages/widgetbook_generator">widgetbook_generator | Dart Package</a></li></ul><p>Widgetbook hakkında daha fazla detaya aşağıdaki siteden erişebilirsiniz.</p><p><a href="https://www.widgetbook.io/">Review all UI changes of your Flutter app in seconds</a></p><blockquote>Bu yazı, <a href="https://medium.com/flutter-community/widgetbook-the-storybook-for-flutter-7d27c26c0420">Widgetbook — The Storybook for Flutter</a> makalesinden izin alınarak derlenip, Türkçe’ye çevirilmiştir. Desteklerinden dolayı <a href="https://medium.com/u/393e3c577829">Lucas Josefiak</a> ve <a href="https://medium.com/u/227ecd1feb9d">Osman Yılmaz</a>’a teşekkür ederim.</blockquote><p>Zamanınızı ayırıp bu yazıyı okuduğunuz için teşekkür ederim, faydalı olması dileğiyle. <strong>Team Kraken</strong> olarak düzenli bir şekilde paylaşımlarımıza devam edeceğiz.</p><p>Bizi aşağıdaki linklerden takip edebilirsiniz.✋🏻</p><ul><li><a href="https://twitter.com/_teamkraken_">Team Kraken Twitter</a> hesabı</li><li><a href="https://twitter.com/mukireuss">Twitter</a> hesabım</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e885f607f9dc" width="1" height="1" alt=""><hr><p><a href="https://medium.com/teamkraken/flutter-widgetbook-e885f607f9dc">Flutter: Widgetbook</a> was originally published in <a href="https://medium.com/teamkraken">Team Kraken</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Katlanabilir Mobil Cihazlar ve Cutouts]]></title>
            <link>https://medium.com/teamkraken/katlanabilir-mobil-cihazlar-ve-cutouts-d8cb55bedb98?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/d8cb55bedb98</guid>
            <category><![CDATA[mobile-app-development]]></category>
            <category><![CDATA[foldabledevice]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Thu, 16 Sep 2021 07:56:29 GMT</pubDate>
            <atom:updated>2021-09-16T07:56:29.866Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ay6StDedqyjJMfAE" /><figcaption>Photo by <a href="https://unsplash.com/@onurbinay?utm_source=medium&amp;utm_medium=referral">Onur Binay</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Katlanabilir cihazlar yani foldable devices teknolojisi hayatımıza girmeye başladı. Telefon ve tablet üretici firmalar cihazlarını çoktan çıkarmaya başladı bile. Hatta çok kısa süre önce <a href="https://www.samsung.com/tr/smartphones/galaxy-z-fold3-5g/"><strong><em>Galaxy Z Fold3</em></strong></a> tanıtıldı. Biraz zaman alsa da yakın zamanda, biz kullanıcılar olarak daha sık bu cihazları görebiliriz. Peki mobil uygulamaları geliştirirken, tasarımcılar ve uygulama geliştiricileri neler düşünebiliriz? Nelere dikkat etmeliyiz?</p><h4>Katlanabilir Cihaz Türleri</h4><p>Kısaca özetlemek gerekirse üç tip ekran özelliğine sahip cihazlar vardır:</p><ul><li>Ekran Kesikleri (Display Cutouts)</li><li>Menteşeli Katlanabilir Ekran (Hinged Foldable Display)</li><li>Katlanabilir Ekran (Foldable Display)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/0*9jUgiOiHYFETMyhp.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/500/0*etRnAzfa_gqtYHgU.png" /><figcaption>Ekran Kesikleri (Display Cutouts) — Katlanabilir Tek Ekran (Fold) Image Resource : <a href="https://devblogs.microsoft.com/surface-duo/flutter-dual-screen-foldable/#types-of-foldable-devices">Microsoft</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AYwvoM7j_FdFIWAe.png" /><figcaption>Katlanabilir Tek Ekran (Fold) — Katlanabilir İki Ekran (Hinge) Image Resource: <a href="https://developer.android.com/codelabs/android-window-manager-dual-screen-foldables#1">Developer Android</a></figcaption></figure><h4>Ekran Kesikleri (Display Cutouts)</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*V3FXSH_3aKnmqLsk.jpg" /><figcaption>Image Resource : <a href="https://www.sammobile.com/2019/03/14/galaxy-s10-cutout-wallpapers-galaxy-themes-store/">SAMMOBILE</a></figcaption></figure><blockquote>Katlanabilen cihazların en büyük özelliklerinden birisi elbette katlanabilen ekranlardır. Ekran kesikleri de katlanabilen cihazların bir parçası olduğundan dolayı, ekran kesitlerinden de bahsetmemizin aklımızdaki bazı sorulara cevap olacağını düşünüyorum.</blockquote><p>Bazı cihazlarda, cihazın ön tarafında kamera veya önemli sensörler için sağlanan alana display cutouts yani ekran kesikleri denir. Bu durum Android tarafında,API 28 yani <strong><em>Android 9</em></strong> ve sonraki yüksek sürümlerde, iOS’ta ise Iphone X cihazı ile birlikte notch ekranları desteklenmeye başlandı.</p><h4>Cutout alanını Android’te kontrol etme</h4><blockquote>Not: Bu kısımdaki bilgiler <a href="https://developer.android.com/guide/topics/display-cutout">Developer Android : Support display cutouts</a> sayfasından derlenmiştir. Daha fazla detay için ilgili sayfayı ziyaret edebilirsiniz.</blockquote><p>Android 9 çalıştıran cihazlarda uyumluluğu sağlamak için aşağıdaki kurallara uyması gerekiyor:</p><ul><li>Tek bir kenarda en fazla 1 kesik olabilir.</li><li>Bir cihazda ikiden fazla kesik olamaz.</li><li>Portre modda yani cihaz dikey yönlendirmede, Status Bar kadar, kesik yüksekliği kadar olmalıdır.</li><li>Varsayılan olarak, tam ekran veya yatay yönde, tüm kesme alanı letterboxed olmalıdır.</li></ul><p>Android ayrıca içeriğin cutout alanı içinde görüntülenip görüntülenmeyeceğini kontrol etmemizi de sağlıyor. Android projemizin içerisinde layoutInDisplayCutoutMode’u aşağıdaki modlardan birine eşitleyebiliriz.</p><ul><li><a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT">LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT</a> : İçerik, portre modundayken cutout alanına işlenir, fakat yatay moddayken içerik letterboxed şeklini alır.</li><li><a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES">LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES</a>: Pencerenin her zaman ekranın kısa kenarlarındaki DisplayCutout alanlarına uzanmasına izin verir. Pencere asla ekranın uzun kenarlarındaki bir DisplayCutout alanına uzanmaz.</li></ul><blockquote>Bu mod genelde fotoğraflar, videolar, haritalar ve oyunlar gibi bazı içerikler için kullanılır.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/451/0*BIvwXKvKvhhomUzZ.png" /><figcaption>Image Resource : <a href="https://developer.android.com/guide/topics/display-cutout">Developer Android</a></figcaption></figure><ul><li><a href="https://developer.android.com/reference/android/view/WindowManager.LayoutParams#LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER">LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER</a> : Pencerenin DisplayCutout alanıyla çakışmasına asla izin vermez.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/450/0*VgFC2VP5wMvK6AiD.png" /><figcaption>Image Resource : <a href="https://developer.android.com/guide/topics/display-cutout">Developer Android</a></figcaption></figure><h4>Cutout alanını iOS’ta kontrol etme</h4><p>iOS 11 ile birlikte viewleri konumlandırırken yeni <a href="https://developer.apple.com/documentation/uikit/uiview/positioning_content_relative_to_the_safe_area">SafeArea API</a> kullanmamız gerekiyor. Cutout alanını yönetmenin en pratik yolu SafeArea ile kontrol etmek olacaktır. iOS tarafında SafeArea ve cutout tarafında daha fazla detaya <a href="https://medium.com/rosberryapps/ios-safe-area-ca10e919526f">buradan</a> ulaşabilirsiniz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pCq01rlMw-2XepYr.png" /><figcaption>Image Resource : <a href="https://medium.com/rosberryapps/ios-safe-area-ca10e919526f">Medium, iOS Safe Area</a></figcaption></figure><h4>Cutout alanını Flutter ile kontrol etme</h4><p>Flutter’da tek yapmanız gereken WidgetınızıSafeArea ile sarmak.</p><p>Daha detaylı bilgi için aşağıdaki videoyu izleyebilir veya <a href="https://api.flutter.dev/flutter/widgets/SafeArea-class.html">buradan </a><a href="https://api.flutter.dev/flutter/widgets/SafeArea-class.html">SafeArea</a> sınıf detaylarına bakabilirsiniz.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FlkF0TQJO0bA%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DlkF0TQJO0bA&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FlkF0TQJO0bA%2Fhqdefault.jpg&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/e6e2a1d512752175ec2c2559875b23d1/href">https://medium.com/media/e6e2a1d512752175ec2c2559875b23d1/href</a></iframe><p>SafeArea kullanımına örnek vermek gerekirse:</p><blockquote>Bu örnek stack overflow sitesinde bulunan<strong> Using SafeArea in Flutter</strong> başlıklı sorudan alınmıştır. Detaylı incelemek isterseniz <a href="https://stackoverflow.com/questions/49227667/using-safearea-in-flutter">buradan</a> ulaşabilirsiniz.</blockquote><pre>Align(<br>  alignment: Alignment.topLeft,  // and bottomLeft<br>  child: Text(&#39;My Widget: ...&#39;),<br>)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HHMIhFzCZIYMYL87.png" /><figcaption>SafeArea ile sarılmamış bir örnek Image Resource: <a href="https://stackoverflow.com/questions/49227667/using-safearea-in-flutter">Stackoverflow</a></figcaption></figure><pre>SafeArea(<br>  minimum: const EdgeInsets.all(16.0),<br>  child: Text(&#39;My Widget: ...&#39;),<br>)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*33NSC5WE_qhFksDS.png" /><figcaption>SafeArea ile sarılmış bir örnek Image Resource: <a href="https://stackoverflow.com/questions/49227667/using-safearea-in-flutter">Stackoverflow</a></figcaption></figure><h4>Menteşeli Katlanabilir Ekran (Hinged Foldable Display)</h4><p>Bu tür cihazlar iki adet ekrana sahiptirler. Bu iki ekran menteşe ile birbirine bağlanır. Bu tür cihazlara örnek vermek gerekirse en iyi örnek<strong> Microsoft Surface Duo</strong>’dur.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mufysVuZFc9sHulr" /><figcaption>Surface Duo — Image Resource : <a href="https://www.microsoft.com/en-us/surface/devices/surface-duo?activetab=overview">Microsoft Surface Duo</a></figcaption></figure><p>Bu tür cihazlar için dikkat edilmesi gerekenler aşağıda listeledim:</p><blockquote>Not: Bu kısımdaki örnekler Microsoft sitesinde bulunan <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a> yazısından derlenmiştir. Daha fazla detay için ilgili sayfayı ziyaret edebilirsiniz.</blockquote><ul><li>Nesneleri bir tarafa taşıyın.</li></ul><p>Bu nesneler bir diyalog, bildirim, snackbar, action, dropdown menuve bottom sheetolabilir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*iAE5SVhHz96CIxQi.png" /><figcaption>Image Resource : <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*z8eN3y1zIqtrU8gV.png" /><figcaption>Image Resource : <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*deo5xQz4yQuUbMpl.png" /><figcaption>Image Resource : <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a></figcaption></figure><ul><li>Widgetları veya componentleri kenarlara yapıştırın. Kenarlara göre uyarlayın.</li></ul><p>Kullanıcı arayüzü bir grid (ızgara) veya tablo düzenine sahip olduğunda, dikey veya yatay çizgiler ile hizalanırsa, kullanıcının uygulamayı görüntülemesi ve kullanması daha kolay olabilir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aRsSYIys42hBw9Po.png" /><figcaption>Image Resource : <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8KhzKIf645NzJJIh.png" /><figcaption>Image Resource : <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a></figcaption></figure><ul><li>UI öğelerini yeniden düzenleme</li></ul><p>Çift ekranlı cihazlar için optimize etmek için kullanabileceğiniz duyarlı bir düzen tekniği, ekran yönü veya boyutu değiştiğinde içeriğinizi yeniden düzenlemek olacaktır. Aşağıdaki örneğe baktığımızda, cihazın üst kısmında bulunan ListView içerisindeki kutucuklar yeniden düzenlendiğinde GridView ile kullanılmış. Aynı şekilde alt kısımında bulunan ListView içerisindeki ListTile componentler tek tarafa ListView halinde uyarlanmış. Böylelikle componentler daha kullanışlı hale gelmektedir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*r1AhbP6zMz1ri-f_.png" /><figcaption>Image Resource : <a href="https://docs.microsoft.com/tr-tr/dual-screen/introduction">Introduction to dual-screen devices</a></figcaption></figure><h4>Katlanabilir Ekran (Foldable Display)</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*SmuDnbbCNIKbKlhP" /><figcaption>Samsung Galaxy Z Fold — Photo by <a href="https://unsplash.com/@mbaumi?utm_source=medium&amp;utm_medium=referral">Mika Baumeister</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WfM1oglIVEGHgTst" /><figcaption>Samsung Galaxy Z Flip — Photo by <a href="https://unsplash.com/@rmrdnl?utm_source=medium&amp;utm_medium=referral">Daniel Romero</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2jSWCTFnQobGOJYd.jpg" /><figcaption>Huawei Mate X2 — Image Resource : <a href="https://consumer.huawei.com/en/phones/mate-x2/">Huawei</a></figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RpiFGfnRjb6k6K6f.jpg" /><figcaption>Xiaomi Mi Mix Fold — Image Resource : <a href="https://www.notebookcheck-tr.com/Xiaomi-Mi-Mix-Fold.535454.0.html">NotebookCheck</a></figcaption></figure><blockquote>Samsung, 2019 yılında 500 bin adet katlanabilir cihaz satmış. 2020 yılında 4.5 milyon katlanabilir cihaz satacaklarını düşünmüş. Ancak gerçek rakamlar orijinal hedefin sadece %60&#39;ıydı.<em>“ Sammobile, Success of Samsung’s foldable phones depends a lot on Apple”</em> <em>Daha fazla detay için </em><a href="https://www.sammobile.com/news/samsung-foldable-phones-mixed-market-response/?__cf_chl_jschl_tk__=pmd_108a119dc6354c48b1d11c4079d65ab8dcde24b2-1627384190-0-gqNtZGzNAg2jcnBszQ4O"><em>buraya</em></a><em> tıklayın.</em></blockquote><p><strong>Menteşeli Katlanabilir Ekran</strong> bölümünde bahsettiğim gibi kurallar çoğunlukla bu tür cihazlarda da geçerlidir. Aynı şekilde burada da<strong> uygulama sürekliliği</strong> (app continuity) önemli yere sahiptir. Kullanıcıya daha sürükleyici bir deneyim sunar.</p><h4>App Continuity (Uygulama Sürekliliği)</h4><p>Katlanabilir cihazda çalışırken, uygulama otomatik olarak bir ekrandan diğerine geçebilir. Harika bir kullanıcı deneyimi sağlamak için, geçişten sonra mevcut görevin sorunsuz bir şekilde devam etmesi çok önemlidir.</p><p>Bu durumda sistem tetiklendiğinde UI stateleri kaydetmeli ve değişiklerini düzgün bir şekilde desteklemelidir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/860/0*K6MNy1x2__f3XyHO" /><figcaption>Image Resource : <a href="https://developer.android.com/guide/topics/ui/foldables">Developer Android</a></figcaption></figure><h4>Microsoft 365 Developer Day Tanıtımı</h4><p>22 Ocak 2020 yılında yazılan <a href="https://blogs.windows.com/windowsdeveloper/2020/01/22/announcing-dual-screen-preview-sdks-and-microsoft-365-developer-day/">blog yazısında</a> çift ekranlı cihazlar için SDK duyurusu yapmıştı. Ayrıca Windows 10X isimli işletim sisteminden bahsetmişti. Paylaştıkları görsele baktığımızda yakınlarda tanıtılan Windows 11&#39;e benzediğini görebiliriz. Yakın gelecekte Windows ile çalışan katlanabilir cihazlar görebiliriz.</p><blockquote><strong>Flutter</strong> ile geliştirilen uygulamalar, Windows’ta da çalışabilmektedir. <a href="https://flutter.dev/desktop">Desktop support for Flutter</a></blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*w9HqQchsqHeRgd1m.png" /></figure><h3>Foldable Android Emulator Kurulumu</h3><p>Emulatorleri kurmadan önce, Android geliştirme ortamının kurulu ve güncel olması gerekiyor. Eğer Android Studio yüklü değilse <a href="https://developer.android.com/studio">Android Studio Kurulum</a> sayfaya giderek kurulumu yapabilirsiniz.</p><h4>Microsoft Surface Duo Emulator Kurulumu</h4><p><a href="https://www.microsoft.com/en-us/download/details.aspx?id=100847">Surface Duo Emulator</a> indirme sayfasına giderek emulatoru indiriyoruz. Ben bu aşamada MacOS için kurulumu anlatacağım. Windows ve Debian kurulum için <a href="https://docs.microsoft.com/tr-tr/dual-screen/android/emulator/surface-duo-download?tabs=windows#download-and-install-the-surface-duo-emulator-image">burada ki sayfaya</a> giderek inceleyebilirsiniz. Ayrıca Mac için detaylı bilgiye <a href="https://docs.microsoft.com/tr-tr/dual-screen/android/emulator/surface-duo-download?tabs=mac#download-and-install-the-surface-duo-emulator-image">buradan</a> ulaşabilirsiniz.</p><ol><li>İndirdikten sonra SurfaceDuoEmulator_ version _.dmg dosyasını açıyoruz.</li><li>İçerisindeki .jar ve diğer dosyaları Android emulator klasörü içerisinde yeni bir klasöre kopyalıyoruz. Genellikle bu konumda bulunur: /Users/{USER}/Library/Android/sdk</li><li>Eğer Android SDK konumunu değiştirdiysen <a href="https://docs.microsoft.com/tr-tr/dual-screen/android/emulator/surface-duo-download?tabs=mac#update-the-pointer-to-your-android-sdk">buradaki</a> adımları uygulayın.</li><li>Ardından kopyaladığımız SurfaceDuoEmulator_version klasörünü terminalde açıyoruz.</li><li>./run.sh komutunu terminalde çalıştırıyoruz.</li><li>Emulatorun açılmasını bekliyoruz.</li></ol><p>Emulatorun kullanımı hakkında detaylı bilgiye aşağıdaki linkten ulaşabilirsiniz.</p><p><a href="https://docs.microsoft.com/tr-tr/dual-screen/android/emulator/get-started">Use the Surface Duo emulator - Dual-screen</a></p><h4>Android Foldable Emulator Kurulumu</h4><ol><li>Android Studio’yu açıyoruz.</li><li>Açılan panelden Configure seçeneğine tıklıyoruz ve ardından AVD Manager seçeneğine tıklıyoruz.</li><li>Açılan Android Virtual Device Manager penceresinde en altta bulunan Create Virtual Device butonuna tıklıyoruz.</li><li>Açılan Virtual Device Configurationpenceresinde, sol taraftaki kategori alanından Phone seçeneğini seçiyoruz. Sağ taraftaki listenin üzerinde bulunan arama kısmına &quot;Fold&quot;yazdıktan sonra çıkan seçeneklerden istediğimiz cihaza tıklayarak Next butonuna tıklıyoruz.</li><li>Ardından ayarlarımızı yaptıktan sonra Finish butonuna tıklayarak ekliyoruz.</li><li>Emulatorümüzü açarak kullanabiliriz.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/915/1*ulBdFTquZ-oJIXqI31EdGQ.png" /></figure><h4>Flutter Foldable Support</h4><p>Henüz foldable cihazlar için Flutter’da official bir API bulamadım fakat Microsoft’un bu konuda geliştirmeleri mevcut. Geliştirmeleri aşağıdaki PR linkinden inceleyebilirsiniz.</p><p><a href="https://github.com/flutter/flutter/pull/77156">Foldable support &amp; TwoPane Widget by andreidiaconu · Pull Request #77156 · flutter/flutter</a></p><p>Zamanınızı ayırıp bu yazıyı okuduğunuz için teşekkür ederim, faydalı olması dileğiyle. <strong>Team Kraken</strong> olarak düzenli bir şekilde paylaşımlarımıza devam edeceğiz.</p><p>Bizi aşağıdaki linklerden takip edebilirsiniz.✋🏻</p><ul><li><a href="https://twitter.com/_teamkraken_">Team Kraken Twitter</a> hesabı</li><li><a href="https://twitter.com/mukireuss">Twitter</a> hesabım</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d8cb55bedb98" width="1" height="1" alt=""><hr><p><a href="https://medium.com/teamkraken/katlanabilir-mobil-cihazlar-ve-cutouts-d8cb55bedb98">Katlanabilir Mobil Cihazlar ve Cutouts</a> was originally published in <a href="https://medium.com/teamkraken">Team Kraken</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter Engage Özeti]]></title>
            <link>https://medium.com/flutter-t%C3%BCrkiye/flutter-engage-%C3%B6zeti-b515520ad212?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/b515520ad212</guid>
            <category><![CDATA[flutter-engage]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[flutter-2]]></category>
            <category><![CDATA[null-safety]]></category>
            <category><![CDATA[flutter-türkiye]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Thu, 04 Mar 2021 10:59:57 GMT</pubDate>
            <atom:updated>2021-03-11T10:21:58.614Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EEV_91aB7OzDD_zsVYjKcg.jpeg" /><figcaption><a href="https://events.flutter.dev/">https://events.flutter.dev/</a></figcaption></figure><p>Flutter, Twitter hesabından Engage etkinliğini bu tweet ile haber vermişti:</p><h3>JavaScript is not available.</h3><p>Everyone is invited! 🥳 pic.twitter.com/35HWogleoE</p><p>💙 Veee o muhteşem gün geldi çattı. <strong>Flutter Engage</strong> etkinliğinde tanıtılan heyecan verici duyuruları ve yenilikleri, <strong>Türkçe </strong>olarak sizlere sunmak için, etkinliğin sona ermesiyle birlikte <a href="https://twitter.com/Flutter_Turkiye"><strong>Flutter Türkiye</strong></a> olarak bu yazıyı yazmaya karar verdik.</p><blockquote>Not: Bu yazı <a href="https://medium.com/u/db21aee611de">Muhammet ÖMER</a> ve <a href="https://medium.com/u/69de64cd6243">Adem Furkan ÖZCAN</a> tarafından yazılmıştır. <a href="https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65"><strong>What’s New in Flutter 2</strong></a> yazısından derlenmiştir.</blockquote><figure><a href="https://twitter.com/Flutter_Turkiye"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CcVWv4hJesIpGimFx5xhVQ.png" /></a><figcaption><a href="https://twitter.com/Flutter_Turkiye">Flutter Türkiye Twitter hesabı</a></figcaption></figure><p>Yazıya başlamadan önce, sizlere Flutter ile yazılmış çok tatlı bir websitesi paylaşmak istiyoruz. Karşınızda Dashatar…</p><h3>Engage: Dashatar Nedir?</h3><p>Dashatar, etkinliğe özel olarak Flutter ile yapılmış olan Dash Avatar oluşturmaya yarayan bir websitesidir. Aşağıdaki linke veya <a href="https://events.flutter.dev/engage/dashatar">buraya tıklayarak </a>kendi dijital Dash’inizi oluşturabilirsiniz.</p><p><a href="https://events.flutter.dev/engage/dashatar">Flutter Engage - March 3rd</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*alKJHYpP0GQU4DvF.png" /><figcaption><a href="https://flutter.dev/dash">https://flutter.dev/dash</a></figcaption></figure><h3>Flutter 2&#39;deki Yenilikler</h3><p>Bugün, Flutter’ın yeni versiyonu olan Flutter 2 tanıtıldı. Flutter 2 sürümüyle birlikte artık sadece mobil framework olmaktan çıkıyor. Flutter 2 versiyonu ile birlikte gelen yenilikleri aşağıya özetledik:</p><ul><li><strong>Flutter web </strong>artık <strong>stabil</strong>.</li><li><strong>Flutter desktop; Windows, MacOS </strong>ve <strong>Linux </strong>erken erişim ile<strong> stabil</strong>.</li><li><a href="https://pub.dev/packages/google_mobile_ads"><strong>Google Mobile Ads</strong></a><strong>, açık beta </strong>versiyonuna geçti.</li><li><strong>Dart 2.12</strong> versiyonu duyuruldu.</li><li>Yeni iOS widgetları duyuruldu.</li><li>Yeni widgetlar olan <strong>Autocomplete </strong>ve <strong>ScaffoldMessenger </strong>duyuruldu.</li><li>Yeni <strong>Flutter Tool</strong>’ları duyuruldu.</li><li>Flutter 1.22 versiyonun çıktığı Eylül ayından itibaren, <a href="https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65">5807 issue</a> kapatıldı.</li><li>Firebase paketleri <strong>Null-safety</strong> için güncellendi.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*a48KEkcqg7RywDFS" /><figcaption><a href="https://www.youtube.com/watch?v=yll3SNXvQCw">Flutter Engage Live</a></figcaption></figure><ul><li>Flutter ile geliştirilen 150.000&#39;den fazla uygulama, uygulama store’larında yayınlandı.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dACPoNjj4KzigS_t.png" /><figcaption><a href="https://www.youtube.com/watch?v=yll3SNXvQCw">Flutter Engage Live</a></figcaption></figure><ul><li>Flutter, artık <strong>katlanabilir (Foldable)</strong> telefonları destekliyor. Microsoft bu konuda Flutter’a katkıda bulunuyor. <a href="https://devblogs.microsoft.com/surface-duo/flutter-dual-screen-foldable/"><strong>Announcing Flutter support for foldable devices</strong></a> isimli yazıdan detaylara erişebilirsiniz.</li><li>Flutter 2.0 gömülü sistemleri (embedded systems) destekliyor. Toyota, araçları için Flutter ile uygulamalar geliştiriyor.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*XlH7Q1FEXkdP2dPx" /><figcaption>Image: <a href="https://twitter.com/FlutterDev/status/1367174378387988480/photo/1">Flutter Twitter</a></figcaption></figure><h3>Flutter Web</h3><ul><li><strong>Flutter web</strong> artık stable versiyonda.</li><li><a href="https://dartpad.dev/"><strong>DartPad</strong></a><strong> </strong>Flutter Web ile geliştirildi.</li><li>Büyük <strong>performans </strong>iyileştirmeleri yapıldı.</li><li>Flutter 2, <strong>PWA </strong>uygulamalarını destekliyor.</li></ul><p>Daha detaylı Flutter web hakkında bilgi almak isterseniz <a href="https://medium.com/flutter/flutter-web-support-hits-the-stable-milestone-d6b84e83b425">Flutter’ın web destek blog</a> gönderisine göz atabilirsiniz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/864/0*xZ__eg9GXelPXDEu.png" /><figcaption><a href="https://medium.com/flutter/flutter-web-support-hits-the-stable-milestone-d6b84e83b425">Flutter web support hits the stable milestone</a></figcaption></figure><ul><li><a href="https://flutter.gskinner.com/">Flutter Folio Showcase</a></li><li><a href="https://flutterplasma.dev/">Flutter Plasma</a></li><li><a href="https://code.irobot.com/">iRobot Coding</a></li></ul><h3>Flutter Desktop</h3><ul><li><strong>Flutter desktop; Windows, MacOS </strong>ve <strong>Linux </strong>erken erişim ile<strong> stabil</strong>.</li><li>Flutter, <strong>Ubuntu</strong>’nun gelecek uygulamaları için varsayılan olarak tercih edilecek.</li></ul><h3>JavaScript is not available.</h3><p>🤩 Flutter is the default choice for future @ubuntu apps.@kenvandine joins us at #FlutterEngage to tell you about some of @canonical&#39;s contributions to Flutter at #FlutterEngage. On now 👉 https://t.co/T9025C5NCV pic.twitter.com/xVzwIZSCIt</p><ul><li><a href="https://github.com/canonical/ubuntu-desktop-installer"><strong>Ubuntu Installer</strong></a> uygulaması, Flutter ile yeniden geliştirildi.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lMSRQfowkBMRO91II9-W8A.png" /><figcaption><a href="https://github.com/canonical/ubuntu-desktop-installer">https://github.com/canonical/ubuntu-desktop-installer</a></figcaption></figure><h3>Dart <strong>2.12</strong></h3><ul><li><strong>Null safety</strong> artık <strong>stable </strong>versiyonunda.</li><li><strong>Dart FFI </strong>artık <strong>stable </strong>versiyonunda.</li></ul><p>Daha detaylı Dart 2.12 hakkında bilgi almak isterseniz <a href="https://medium.com/dartlang/announcing-dart-2-12-499a6e689c87"><strong>Announcing Dart 2.12</strong></a><strong> </strong>gönderisine göz atabilirsiniz.</p><h3>Flutter Tool</h3><h4>Flutter Fix</h4><p>Flutter 2 ile birlikte sunulan Flutter Fix aracı, kullanımdan kaldırılmış olanları otomatik olarak temizlemeye yardımcı olmaktadır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/277/0*CkI31pt4VYBZKDGV.png" /><figcaption><a href="https://flutter.dev/docs/development/tools/flutter-fix">Flutter Fix</a></figcaption></figure><p><a href="https://flutter.dev/docs/development/tools/flutter-fix">Flutter Fix</a></p><h4>Flutter DevTools</h4><p>Flutter DevTools aracı, artık Android Studio, IntelliJ ve Visual Studio Code’da destekleniyor. Örneğin overflow hataları aldığınızda, DevTools aracına yönlendirerek sorunu düzeltmek için seçenek sunuyor.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KOoy_SldwP5RuW4J" /><figcaption><a href="https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65">What’s New in Flutter 2</a></figcaption></figure><p><a href="https://flutter.dev/docs/development/tools/devtools/overview">DevTools</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xv452X0d0Ipyk4U3" /><figcaption><a href="https://pub.green/">pub.green</a></figcaption></figure><p>Flutter projenizde kullandığınız paketlerin, Flutter sürümüzle uyumlu olup olmadığını <strong>pub.green</strong>’den kontrol edebilirsiniz.</p><ul><li><a href="https://pub.green/">Check pub.dev package compatibility with your Flutter version</a></li><li><a href="https://medium.com/flutter/whats-new-in-flutter-2-0-fe8e95ecc65">What’s New in Flutter 2.0</a></li></ul><p>Yayında bulunun oturumları <strong>Türkçe </strong>olarak izlemek isterseniz, <strong>5 Mart Cuma</strong> günü olacak olan yayına aşağıdaki linkten katılabilirsiniz.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FaYdFJ8_gQ6A%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DaYdFJ8_gQ6A&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaYdFJ8_gQ6A%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/da91d1430ce4fc59a158370abdfb4194/href">https://medium.com/media/da91d1430ce4fc59a158370abdfb4194/href</a></iframe><p>Zamanınızı ayırıp bu yazıyı okuduğunuz için teşekkür ederiz, faydalı olması dileğiyle.</p><p>Bize bu adreslerden ulaşabilirsiniz:</p><ul><li>Muhammet ÖMER <a href="https://twitter.com/mukireuss">Twitter</a> hesabından</li><li>Adem Furkan ÖZCAN <a href="https://twitter.com/AdemOzcanTR">Twitter</a> hesabından</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b515520ad212" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flutter-t%C3%BCrkiye/flutter-engage-%C3%B6zeti-b515520ad212">Flutter Engage Özeti</a> was originally published in <a href="https://medium.com/flutter-t%C3%BCrkiye">Flutter Türkiye</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter:  Clean Code 2]]></title>
            <link>https://medium.com/flutter-t%C3%BCrkiye/flutter-clean-code-2-fb7906b06b07?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb7906b06b07</guid>
            <category><![CDATA[part-of]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[localization]]></category>
            <category><![CDATA[singleton]]></category>
            <category><![CDATA[clean-code]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Sun, 29 Nov 2020 13:36:43 GMT</pubDate>
            <atom:updated>2020-11-29T13:36:43.734Z</atom:updated>
            <content:encoded><![CDATA[<h3>Flutter: Clean Code 2</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*C5SPqd3uzjDS051U" /><figcaption>Photo by <a href="https://unsplash.com/@carlheyerdahl?utm_source=medium&amp;utm_medium=referral">Carl Heyerdahl</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Herkese tekrardan merhaba, Clean Code serimizin ilk yazısını yaklaşık 8 ay önce oluşturmuştum. Her ne kadar kısa gibi gözüksede bu geçen sürede kendimi daha da geliştirdim ve biraz daha <strong>temiz kod </strong>yazmayı öğrendim. Bu bilgileri sizlere de aktarmak istedim. Bir önceki yazıya nazaran elbette yenilikler mevcut. Bu yeniliklerden kısaca bahsedeceğim.</p><blockquote>Serinin ilk yazısı olan <a href="https://medium.com/flutter-t%C3%BCrkiye/flutter-clean-code-c52ff8759c0e">Flutter: Clean Code’u buraya tıklayarak</a> okuyabilirsiniz.</blockquote><p>Hızlıca bahsedeceğim konu başlıklarına bakalım :</p><ul><li>Singleton Design Pattern</li><li>Localization (No Static Strings)</li><li>Part of Pages</li><li>Extensions</li></ul><h3>Singleton Design Pattern</h3><p>Yazdığımız kodda tanımladığımız değişkenler, nesneler ve benzeri değerler RAM’de yani cihazın belleğinde yer kaplamaktadır. Çoğu zaman değişkenleri fonksiyonlar içerisinde kullanıp, fonksiyonda işimiz bittiği zaman otomatik olarak yok olduğunu biliyoruz.</p><p>Fakat bazı değişkenler, nesneleri uygulamanın tamamında kullanıyoruz ve her birisi için tek tek, ayrı ayrı oluşturarak istekte bulunuyoruz. Örnek vermek gerekirse uygulamamızın teması (Text Theme, Icon Theme…)veya Database için oluşturduğumuz bağlantı…</p><p>Singleton Design Pattern ile birlikte bu yapıyı, tek bir örnek alarak kullanılırız. Böylelikle uygulama çalıştığı müddetçe<strong> sadece tek bir örnek oluşur</strong>. İlk kez çağırıldıklarında tek sefer oluşturulurlar.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F26FLbf1Z6Vln7qbdK%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F26FLbf1Z6Vln7qbdK%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2F26FLbf1Z6Vln7qbdK%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/c8ef362b254b5581385d845901e1e577/href">https://medium.com/media/c8ef362b254b5581385d845901e1e577/href</a></iframe><p>Dart’ta nasıl kullanıldığına hep birlikte bakalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2ce2bbbcbb959bef8ce41e054bbe8653/href">https://medium.com/media/2ce2bbbcbb959bef8ce41e054bbe8653/href</a></iframe><p>Yukarıdaki örneği incelediğimizde, bir sınıfımız mevcut ve bu sınıf içerisinde bir adet static olarak oluşturulmuş bir instance var. Bu sınıf içerisindeki cancel veya search değişkenine erişmek istersek aşağıdaki hatayı alırız.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/672/1*qNhbBZFCVxSybmrrEW-1SQ.png" /><figcaption>aldığımız hata</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*87DoKPwcTADhOTUlcyElEQ@2x.png" /></figure><p>Bu hatanın sebebi ise, instance kullanmadan cancel değişkenine erişmeye çalışmamızdan kaynaklanıyor. Yani cancel artık statik değil, statik olan instance ögesinin içerisinde bulunmakta.</p><p>Singleton tasarım deseni hakkında daha detaylı araştırmanızı tavsiye ederim. Stackoverflow’da gördüğüm sorunun altında faydalı cevaplara erişebilirsiniz. Okumak için: <a href="https://stackoverflow.com/questions/12649573/how-do-you-build-a-singleton-in-dart">How do you build a Singleton in Dart?</a></p><h3>Localization (No Static Strings)</h3><p>Bir projeye başlarken <em>genelde </em>kullanıcı arayüzü (UI) tasarımı hazır halde olur. Geliştirici hazır olan tasarıma bakarak projeyi geliştirir. Proje kodlanırken dikkat edilmesi gereken noktalardan bir tanesi ise kullanıcı arayüzdenki kelimeler, cümleler yani kısaca Stringler statik olarak yazılmamalıdır.</p><p>Basit bir sebep ile örneklendirelim. Örneğin bir projede sadece <em>Türkçe </em>dili bulunsun ve Stringler statik olarak verilmiş olsun. İlerleyen zamanlarda ek olarak diğer diller eklenmek istendiğinde ise tek tek bu statik kelimeleri, cümleleri bulup çeviri için düzenlemeniz gerekecektir. Bu durumu projeye başlarken localization ekleyerek çözebiliriz. Böylelikle daha temiz kod yazılmış olur. Geliştirici daha az zaman harcamış olur.</p><p>Peki projeye başlarken ne yapmalıyız? Ben bir projeye başlarken bellirli kütüphaneleri ekliyorum. Localization için <a href="https://pub.dev/packages/easy_localization">easy_localization</a> kütüphanesini projeye ekliyorum. Ardından assets klasör dizinine hangi dilde geliştiriyor isem o dile ait bir json dosyasını oluşturuyorum.</p><pre>assets<br>└── language<br>    ├── {languageCode}.json                  <em>// Sadece dil kodu</em><br>    └── {languageCode}-{countryCode}.json    <em>// Ya da full yerel kod</em></pre><p>Ardından gerekli olan ayarları yaptıktan sonra projeyi geliştirmeye devam ediyorum. Dil eklemek istediğim zaman yapmam gereken tek bir şey kalıyor, yukarıda göstermiş olduğum klasör dizinine o dile ait bir json dosyayı oluşturuyorum. Son olarak çevirilmiş metinleri eklemek kalıyor.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F3o7TKP8JksP0JJktTG%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F3o7TKP8JksP0JJktTG%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2F3o7TKP8JksP0JJktTG%2F200.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="216" frameborder="0" scrolling="no"><a href="https://medium.com/media/ffd27d9ce0e2edffedca21b0d0a693f0/href">https://medium.com/media/ffd27d9ce0e2edffedca21b0d0a693f0/href</a></iframe><h3>Part of Pages</h3><p>Çoğu Dart/Flutter geliştiricisi part kavramını kullanmaktan kaçınırlar. Genellikle bir sayfaya ait kodları tek sayfada yazmayı daha uygundur görürler. Çünkü ileride koda bakım yapılmak istendiğinde, kodun daha kolay bulunacağını düşünürler.</p><p>Bir sayfadaki kodların bir bölümünü ayırmak için part kavramını kullanmayı tercih ederseniz, hangi sayfaya ait olduğunu belirtmeniz gerekiyor. Yani özetlemek istersek, part ve part of kavramını kesinlikle kullanmanız gerekmektedir.</p><blockquote><strong>Part</strong> : Temel sayfaya yazılması gerekmektedir.<br><strong><em>Part of</em></strong> : Parçası olunan sayfaya yazılması gerekmektedir.</blockquote><blockquote><strong>DİKKAT :<em> </em></strong>Bu parçalamayı kullandığınızda aradığınız kodların bulunmasında <strong>karmaşıklığa neden olabilir</strong>. Her zaman ve her yerde <strong>kullanmayınız</strong>.</blockquote><p>Anlaşılması oldukça güç olan bir kavramı örnekle açıklamaya çalışalım. Bir giriş sayfamız olduğunu düşünelim. Giriş sayfamızın içerisinde çok fazla component olduğunu düşünelim. Kodları yazdıkça Login Form kod bloklarımızın kaybolduğunu ve bulmakta zorlandığınızı farkederseniz işte part of pages kullanmanın yeridir. Kodlarla birlikte daha iyi anlaşılacaktır. Hadi kodlayalım!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0mJkncqlqxPzAogRz3X4qw.png" /><figcaption>login_part.dart</figcaption></figure><p>Giriş sayfamızın bu şekilde olduğunu hayal edelim. Yorum satırlarının olduğu yerlerde kod olduğunu varsayalım. Parçalamak istediğimiz zaman yapmamız gereken ilk adım 3. satırda görüldüğü üzere <strong>parçalanacak </strong>sayfaya <strong>part</strong> kavramını eklemek. Bunu ekledikten sonra bir hata <strong>alacaksınız</strong> fakat endişelenmeyin!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/791/1*GhEEchcwPlPq0HS-U6oDEQ.png" /><figcaption>part error</figcaption></figure><p>Bu hatada parçasını bulamadığını söylüyor. Bizden parçası olan sayfaya da <strong>part of</strong> kavramının eklenmesini istiyor. Diğer sayfaya da aşağıdaki <em>örnekteki </em>gibi ekledikten sonra hata <strong>düzelecektir</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LHG6EVtBiDOXjSOudI-qIA.png" /><figcaption>login_part_of.dart</figcaption></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F5xtDarJ7YZVF44Y1LPO%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F5xtDarJ7YZVF44Y1LPO%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2F5xtDarJ7YZVF44Y1LPO%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="245" frameborder="0" scrolling="no"><a href="https://medium.com/media/71ce669340704a6fe3fbae09d37e4ce3/href">https://medium.com/media/71ce669340704a6fe3fbae09d37e4ce3/href</a></iframe><h3>Extensions</h3><p>Extension’lar, Dart diline 2.7 versiyonuyla birlikte geldi. Extension’ları özet geçmek gerekirse varolan veya özel olarak oluşturduğumuz, belirlediğimiz tiplere özgü, yeni özellikler eklememize yaramaktadır. Kendimizde bir extension yazarak, projemizdeki geliştirme hızımızı gözle görülebilir derecede artırabiliriz.</p><p>Diğer yazılarımın birinde extension’lar hakkında yazı yazmıştım. Kendimi tekrarlamamak açısından o yazıyı yönlendirmemi mazur görün. <a href="https://medium.com/hardwareandro/mobil-d%C3%BCnyada-extension-fec7aa75d5d1">Mobil Dünyada Extension</a> yazımı buraya tıklayarak okuyabilirsiniz.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fc4hnCnBbA19du%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fc4hnCnBbA19du%2Fgiphy.gif&amp;image=https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExYnUwMGliM3Fqc3Q0OGl6M3NtcHBjcTFqY2g5OXR5eGVyN28zYXlvdyZlcD12MV9naWZzX2dpZklkJmN0PWc%2Fc4hnCnBbA19du%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="246" frameborder="0" scrolling="no"><a href="https://medium.com/media/d37f059d72828de4e3eedd2057b86ed4/href">https://medium.com/media/d37f059d72828de4e3eedd2057b86ed4/href</a></iframe><p>Zamanınızı ayırıp bu yazıyı okuduğunuz için teşekkür ederim, faydalı olması dileğiyle.</p><p>Bana bu adreslerden ulaşabilirsiniz:</p><ul><li><a href="https://twitter.com/mukireuss">Twitter</a> hesabımdan</li><li><a href="https://www.linkedin.com/in/muhammetomer/">LinkedIn</a> hesabımdan</li></ul><p>Ayrıca <a href="https://github.com/mukireus">GitHub</a> hesabıma buradan ulaşabilirsiniz.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb7906b06b07" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flutter-t%C3%BCrkiye/flutter-clean-code-2-fb7906b06b07">Flutter:  Clean Code 2</a> was originally published in <a href="https://medium.com/flutter-t%C3%BCrkiye">Flutter Türkiye</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Flutter: Native Kamera Yönlendirme ve Galeriden Fotoğraf Seçme]]></title>
            <link>https://medium.com/hardwareandro/flutter-native-kamera-y%C3%B6nlendirme-ve-galeriden-foto%C4%9Fraf-se%C3%A7me-5f9b1e77244d?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/5f9b1e77244d</guid>
            <category><![CDATA[cameras]]></category>
            <category><![CDATA[navigation]]></category>
            <category><![CDATA[flutter]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Wed, 26 Aug 2020 06:42:22 GMT</pubDate>
            <atom:updated>2020-09-10T11:10:54.716Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Py0Xtw6H4WDgaZWB" /><figcaption>Photo by <a href="https://unsplash.com/@joshwp?utm_source=medium&amp;utm_medium=referral">Josh Power</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Herkese merhaba 👋 Bu yazımda sizlere Flutter’da, fotoğraf çekimi için telefonunuzun native kamera uygulamasına nasıl yönlendirebileceğinizi veya galerinizden nasıl fotoğraf seçebileceğinizi göstereceğim.</p><p>Projenizde, kamera işlemlerini çok yoğun olarak kullanmıyorsanız Flutter’ın <a href="https://pub.dev/packages/camera">camera</a> eklentisini kullanmanızı önermiyorum. Henüz hazır olmadığını düşünüyorum. Çok fazla özellik sunamıyor ne yazık ki. Bu özelliklere örnek vermek gerekirse telefonunuzun <strong>flaş </strong>özelliği dahil değil,<strong> otomatik focus </strong>veya tıklanıldığında focus özelliği mevcut değil. <strong>Zoom</strong> özelliği de bulunmuyor. Bu gelişmeleri takip etmek isterseniz <a href="https://github.com/flutter/flutter/issues/31225">buraya</a> tıklayarak ilgili alana ulaşabilirsiniz.</p><p>Yukarıda bir ifade kullandım “…kamera işlemlerini çok yoğun olarak kullanmıyorsanız…” burada yoğun işleme örnek vermek gerekirse Instagram uygulamasında bulunan kamera alanını hepimiz az çok görmüş veya kullanmışızdır. Burada renk efektleri, boomerang özelliği ve benzeri bir çok özellik mevcut.</p><p>Bizim tek isteğimiz fotoğraf çekip yüklemek ise <a href="https://pub.dev/packages/image_picker">image_picker</a> kütüphanesini kullanarak telefonumuzda bulunan kamera uygulamasına yönlendirerek fotoğrafı çektikten sonra yükleyebiliriz. Evet bu kadar basit.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FY1vZ5yzbmtW5lOVcYr%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FY1vZ5yzbmtW5lOVcYr%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FY1vZ5yzbmtW5lOVcYr%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/4b4da3e1216ea127c8c0a7482fa8132e/href">https://medium.com/media/4b4da3e1216ea127c8c0a7482fa8132e/href</a></iframe><h3>Haydi Başlayalım 🚀</h3><p>Projemizde bulunan pubspec.yaml dosyamızı açalım. Ardından dependencies alanına <a href="https://pub.dev/packages/image_picker/install">image_picker</a> isimli kütüphanemizi ekleyelim.</p><blockquote>Güncel sürümü için lütfen <a href="https://pub.dev/packages/image_picker">image_picker</a> kütüphanesinin bulunduğu websiteyi ziyaret ediniz.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/668/1*2l2B1i0HWGmiIIm0hqfQ1Q.png" /><figcaption>pubspec.yaml</figcaption></figure><h4>Dikkat etmemiz gereken birkaç husus bulunuyor.</h4><ul><li>Android :</li></ul><p>Android <strong>API </strong>sürümü <strong>29+</strong> ise projemiz içerisindeki <strong>AndroidManifest.xml </strong>dosyamızda &lt;application&gt; etiketi içerisine android:requestLegacyExternalStorage=&quot;true&quot; eklenmelidir.</p><blockquote>Daha fazla detay için <a href="https://developer.android.com/preview/privacy/storage">Storage updates in Android 11</a> dokümanını inceleyebilirsiniz.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3lJqmpTfzXMJBg7v1zO_wg.png" /><figcaption>AndroidManifest.xml</figcaption></figure><ul><li>iOS :</li></ul><p><strong>iOS </strong>cihazları için bu ifadeleri projemizde bulunan ios &gt; Runner &gt; Info.plist dosyamıza eklememiz gerekmektedir.</p><p>&lt;key&gt;NSCameraUsageDescription&lt;/key&gt; <br>&lt;string&gt;Used to demonstrate image picker plugin&lt;/string&gt;&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;<br>&lt;string&gt;Used to capture audio for image picker plugin&lt;/string&gt;&lt;key&gt;NSPhotoLibraryUsageDescription&lt;/key&gt;<br>&lt;string&gt;Used to demonstrate image picker plugin&lt;/string&gt;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OnMGvRIGn2wny8kmbmmRJA.png" /><figcaption>Info.plist</figcaption></figure><p>UI tarafında geliştirmelerimizi tamamlıyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/fba70636f1eb6b13057d5a6bcd3f651c/href">https://medium.com/media/fba70636f1eb6b13057d5a6bcd3f651c/href</a></iframe><p>Örnek olması açısından hızlı bir tasarım oluşturdum.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*cb0qf-MBn1Ukn8nxd7WRDQ.png" /><figcaption>uygulama kullanıcı arayüzü</figcaption></figure><h3>Fonksiyonu Oluşturalım 📷</h3><p>Projemize <strong>değişken </strong>olarak aşağıdaki satırı ekleyelim.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/724/1*L31k00uPEOS83-R0GdeVKw.png" /><figcaption>değişken</figcaption></figure><h4>onImageButtonPressed Fonksiyonu</h4><p>Bu fonksiyonumuz <strong>ImageSource </strong>tipinde bir parametre içeriyor. Bu parametre ise <strong>Enum </strong>cinsinden oluşmaktadır. İki seçenek bulunmakta:</p><ul><li>camera: Cihazın kamerasını açarak kullanıcının yeni bir fotoğraf çekmesine izin verir.</li><li>gallery: Cihazın fotoğraf galerisini açarak kullanıcının bir fotoğraf seçmesine izin verir.</li></ul><h4>getImage Fonksiyonu</h4><p>Bu fonksiyonumuz ile birlikte <strong>kamera </strong>ile çekilen veya <strong>galeriden </strong>seçilen fotoğrafı elde etmemizi sağlıyor.</p><blockquote>Bu fonksiyon içerisinde yapmak istediğimiz işlemleri gerçekleştirebiliriz. Örneğin <strong>PickedFile </strong>tipinde<strong> </strong>bir liste oluşturduktan sonra seçilen fotoğrafları bu listeye ekleyebiliriz.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1QGDsFEhXnI0C09JGnF-pw.png" /><figcaption>fonksiyon</figcaption></figure><p>Son olarak oluşturduğumuz fonksiyonu, butonlara bağlandıktan sonra kullanabiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*78_EtxGiMc7wPh-nmMIR7g.png" /><figcaption>butonlar</figcaption></figure><h3>Sonuç 🎉</h3><p>Uygulamamız aşağıdaki gibi sonuç vermektedir.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/409/1*9Gy-AAF5RN1p6iuDIrsbLA.gif" /><figcaption>uygulama sonucu</figcaption></figure><p>Buraya kadar zahmet göstererek, yazıyı okuyarak zaman ayırdığınız ve sabırla sonuna kadar geldiğiniz için teşekkür ederim, umarım faydalı olmuştur.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FVJvjBi6SEaKhW%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FVJvjBi6SEaKhW%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FVJvjBi6SEaKhW%2Fgiphy-downsized-large.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="435" frameborder="0" scrolling="no"><a href="https://medium.com/media/fde4ea85c9f6a02d156191594989f1f4/href">https://medium.com/media/fde4ea85c9f6a02d156191594989f1f4/href</a></iframe><p>Bana aşağıdaki adreslerden ulaşabilirsiniz:</p><ul><li><a href="https://twitter.com/mukireuss"><em>Twitter</em></a><em> hesabımdan</em></li><li><a href="https://www.linkedin.com/in/muhammetomer/">LinkedIn</a> hesabımdan</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5f9b1e77244d" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hardwareandro/flutter-native-kamera-y%C3%B6nlendirme-ve-galeriden-foto%C4%9Fraf-se%C3%A7me-5f9b1e77244d">Flutter: Native Kamera Yönlendirme ve Galeriden Fotoğraf Seçme</a> was originally published in <a href="https://medium.com/hardwareandro">HardwareAndro</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Baştan Sona Flutter Projesi: Ezan Vakti (Part 1)]]></title>
            <link>https://medium.com/flutter-t%C3%BCrkiye/ba%C5%9Ftan-sona-flutter-projesi-ezan-vakti-part-1-e03fc991d4c7?source=rss-db21aee611de------2</link>
            <guid isPermaLink="false">https://medium.com/p/e03fc991d4c7</guid>
            <category><![CDATA[ramadan]]></category>
            <category><![CDATA[flutter]]></category>
            <category><![CDATA[mobile]]></category>
            <category><![CDATA[ui-design]]></category>
            <category><![CDATA[mobile-app-development]]></category>
            <dc:creator><![CDATA[Muhammet ÖMER]]></dc:creator>
            <pubDate>Fri, 24 Jul 2020 15:37:19 GMT</pubDate>
            <atom:updated>2020-07-24T15:47:56.024Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bhd0jeNcAaEzfpWGrGJcPw.png" /></figure><h3>Merhabaa! 👋🏻</h3><p>Yepyeni bir seri ile karşınızdayız. Bu serimizde, <a href="https://github.com/flutterturkey">GitHub hesabımızda</a> bulunan “<a href="https://github.com/flutterturkey/prayer-times">Ezan Vakti</a>” isimli projeyi adım adım nasıl geliştirdiğimizi anlatacağım.</p><h3>Uygulama Hakkında Bilgi 📲🕌</h3><p>Uygulamamız,</p><ul><li>kullanıcı tarafından seçilen il ve ilçenin namaz vakitleri göstermektedir,</li><li>namaz vakitlerinden önce bildirim göndermektedir</li><li>ve ayrıca kullanıcı dilerse tema seçimi ve dil seçimi yapabilmektedir.</li></ul><p>Sıkı tutunun başlıyoruz!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fmi6DsSSNKDbUY%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fmi6DsSSNKDbUY%2Fgiphy.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2Fmi6DsSSNKDbUY%2Fgiphy-downsized-large.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/2b1b84e52995150e61eac10a3a88c2e0/href">https://medium.com/media/2b1b84e52995150e61eac10a3a88c2e0/href</a></iframe><h3>Tasarım ve Kodlama Ortamı✒️💻</h3><h4><strong>- UI/UX Tasarım Aracı Kurulumu </strong>✒️</h4><p>Uygulama tasarımını gerçekleştirmek için bir uygulamaya ihtiyacımız var. Bizim birkaç önerimiz var : <a href="https://www.adobe.com/tr/products/xd.html"><strong><em>Adobe XD</em></strong></a> ve <a href="https://www.figma.com/"><strong><em>Figma</em></strong></a><strong> </strong>Biz tasarımımızı <strong>Adobe XD </strong>üzerinde yapacağız.</p><h4>- Kod Editör Kurulumu 💻</h4><p>Uygulamayı kodlamak için, <a href="https://flutter.dev/docs/get-started/editor?tab=emacs">Flutter’ın desteklendiği kod editörleri</a>nden birini kullanmamız gerekmektedir. Biz uygulamayı kodlarken <strong>VS Code</strong> isimli editörü kullanacağız. Siz de bize eşlik etmek istiyorsanız ve bilgisayarınızda VS Code yüklü değilse <a href="https://code.visualstudio.com/"><strong>buraya tıklayarak</strong></a> indirebilirsiniz.</p><h4>- Flutter Kurulumu 💙</h4><p>Samimi olmak gerekirse, bu kurulumu en iyi Flutter’ın sitesindeki yönlendirmeler ile yapabilirsiniz. Henüz dil destekleri arasında Türkçe bulunmuyor. Fakat üzülmeyin takıldığınız yer olursa <a href="https://t.me/fluttertr"><strong>Flutter Türkiye Telegram</strong></a> üzerinden yardım alabilirsiniz.</p><h3>Uygulama Tasarımı✒️👨🏻‍🎨</h3><p>Uygulamayı tasarlamadan önce, kağıtta hızlı ve basit bir mockup hazırladım. Artık az çok neler gerektiğini biliyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/877/1*zhtquXobpSCdgfbVoMrJIA.jpeg" /><figcaption>Mockup</figcaption></figure><p>Tasarımımızı Material Design prensiplerine göre yapıyoruz.</p><blockquote>Material Design nedir?</blockquote><blockquote>Materyal Tasarım, tasarımla ilgili en iyi pratikleri, genel olarak benimsenmiş kuralları ve herhangi bir cihazda evinizdeymiş gibi rahat hissetmenizi sağlayacak etkileyici uygulamalar oluşturmanıza yardımcı olacak görsel öğeleri içerir. [<a href="https://developer.android.com/distribute/best-practices/develop/use-material-design?hl=tr#why-it-works">Materyal Tasarım, Google Developers</a>]</blockquote><p>Şimdi <strong>Adobe XD</strong>’de tasarlamaya başlayabiliriz. <em>(Renk paleti ve logo seçimi daha önceden yapılmıştır.)</em></p><h4>- Başlatma Ekranı (Splash Screen) ⏰</h4><p>Splash screen, bir uygulama arka planda açılırken kullanıcıya boş bir ekran göstermek yerine hazırlanan tasarımını kullanarak ana sayfaya geçiş yapmamızı sağlayan ekrandır. Dikkat etmemiz gereken nokta ise, başlatma ekranında uzun bir yükleme süresi kullanıcıların duygularına negatif bir etki yansıtabilir. Bu durum kullanıcı deneyimi ile doğru orantılıdır. <a href="https://material.io/design/communication/launch-screen.html#usage">Materyal Tasarım</a>’da verilen tavsiyelere bakıldığında ise marka logosu veya uygulamayı temsil eden bir görsel eklemek en doğru seçimdir.</p><p>Böylelikle seçimimiz bu şekilde olacaktır:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/820/1*kyOsWoCO2w_9SXXvhqCWxg.png" /><figcaption>Splash Screen of PrayerTimes App</figcaption></figure><h4>- Bilgilendirme Ekranı (Onboarding Screen)</h4><p>Bu kısımda aklımıza birkaç soru işareti gelebilir. <strong>Bu ekran nedir? Bu ekrana neden ihtiyacımız var?</strong></p><p>Bu ekran, uygulama kullanıcısıyla ilk temas ettiği noktadır. Kullanıcıya “Hoş Geldiniz” demek için bir fırsat da diyebiliriz 🎉. Bu nedenle uygulama üzerinde harika bir izlenim bırakmak için gereklidir ve oldukça basit hale getirmek önemli bir yere sahiptir. Bu ekran ile birlikte kullanıcıya, uygulamanın işlevleri hakkında bilgiler verebilirsiniz.</p><blockquote>Bu ekranı, uygulamayı ilk kez kullanan kullanıcılarda göstermelisiniz. Geri dönen kullanıcılara göstermemelisiniz. Yani uygulama kapandıktan sonra geri açılınca hemen ana sayfaya yönlendirilmelidir.</blockquote><blockquote>Bilgilendirme ekranı hakkında detaylı bilgi için <a href="https://material.io/design/communication/onboarding.html">buraya tıklayın</a>.</blockquote><p>Şimdi sıra bu ekranı tasarlamakta. Peki kullanıcıya ne tür bilgiler verebiliriz? Kullanıcı uygulamayı açtıktan sonra konum bilgilerini manuel bir şekilde girmesi gerekmektedir. Bu durumdan bahsedebiliriz. Diğer bir husus ise kullanıcıyı namaz saatlerinden bildirim alacağını haberdar edebiliriz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/901/1*5Sas-P1zd6d60zRv7w6Gpw.png" /><figcaption>Onboarding Screen of PrayerTimes App</figcaption></figure><h4>- Ana Sayfa (Home Screen)</h4><p>Ana sayfa, bir uygulamanın en önemli bir parçasıdır. Çünkü kullanıcıların en fazla vakit geçirdiği sayfadır. Genellikle ana sayfada, kullanıcı diğer sayfalara yapacağı yolculukların başlangıç noktası olduğundan gezinme bileşenleri (components) içerir. Materyal tasarımda bu bileşenin ismi Bottom Navigation Bar olarak adlandırılmaktır.</p><blockquote><a href="https://material.io/components/bottom-navigation">Material.io Bottom Navigation</a></blockquote><p>Daha öncesinde çizdiğimiz mockup’ta neler olacağını belirtmiştik. Materyal tasarım prensiplerine göre tasarladığımız zaman ortaya bu şekilde bir sonuç çıkmaktadır:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/393/1*jRwc7SiiAvcBhQbLQg5JgA.png" /><figcaption>Bottom Navigation Bar of PrayerTimes App</figcaption></figure><blockquote><a href="https://material.io/develop/android/components/top-app-bars/">App Bar</a> geçerli ekranla ilgili bilgileri ve eylemleri görüntüler.</blockquote><p>App Bar bileşenimizde bilgi olarak, uygulamanın ismini ve logosunu ekleyebiliriz. Materyal tasarım prensiplerine göre tasarladığımız zaman ortaya bu şekilde bir sonuç çıkmaktadır:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/393/1*oe_QeV5ZsPdfWD0UT4rXUw.png" /><figcaption>App Bar of PrayerTimes App</figcaption></figure><p>Uygulamanın <em>Body </em>içerisinde sırasıyla bilgiler bulunduracağız. Bu bilgiler, bulunduğu günün tarihi miladi ve hicri takvime göre olabilir. Ramazan ayında bulunduğumuz için iftara kalan süreyi gösterebilir. En önemlisi ise kullanıcının seçimini yaptığı şehire göre namaz vakitlerinin bulunduğu bir alan olabilir. Bu bilgileri ayrı ayrı kutucuklar halinde hazırladığımız zaman ortaya bu şekilde bir sonuç çıkmaktadır:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/892/1*bkKpEam_sUC2aNVpZ-Etnw.png" /><figcaption>Home Screen of PrayerTimes App</figcaption></figure><p>En altta bulunan gezinme bileşenimiz (Bottom Navigation Bar) içerisinde bulunan eylem butonlarının işlevlerini tasarlarken, farklı bir sayfaya yönlendirme ihtiyacımız olmadığını ve aynı sayfada daha verimli olacağını düşünüyorum. Burda kullanılabilecek en doğru bileşen (component) “<a href="https://material.io/components/dialogs">Dialog</a>” olduğuna hepimizin hemfikir olduğumuzu düşünüyorum. Çünkü bu bileşen kullanıcı deneyimi açısından bakıldığında, kullanıcının dikkatini odaklamaktadır. Böylelikle seçimimiz bu şekilde olacaktır:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*f-Qsh70YjOzuvEN5s2sdSA.png" /><figcaption>Dialogs of PrayerTimes App</figcaption></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FY3e3gnofVUd4RnXKDz%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FY3e3gnofVUd4RnXKDz%2Fsource.gif&amp;image=https%3A%2F%2Fi.giphy.com%2Fmedia%2FY3e3gnofVUd4RnXKDz%2Fgiphy-downsized-large.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/6fc7121baf8586b0da99557ba1473670/href">https://medium.com/media/6fc7121baf8586b0da99557ba1473670/href</a></iframe><p><strong><em>Veee böylelikle tasarımımızı tamamlamış olduk. Şimdi kodlamaya başlayabiliriz.</em></strong></p><figure><a href="https://twitter.com/Flutter_Turkiye"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qAJ2sdQiVuCCvrDqI1MhVA.png" /></a></figure><h3>Uygulama Kodlama💻💙</h3><p>Tasarımımız hazır olduğuna göre kodlamaya başlayabiliriz.</p><blockquote>Uygulamanın kodlandığı Flutter sürümü “<strong>Flutter: 1.18.0–11.1pre” </strong>ve kanalı<strong> “beta”</strong>dır.</blockquote><blockquote>Beta kanalına, “<strong>Terminal”</strong>den <strong>flutter channel beta</strong> komutunu yazarak geçeebilirsiniz. <strong>flutter upgrade</strong> komutunu girmeyi unutmayın. [<a href="https://flutter.dev/docs/development/tools/sdk/upgrading">Upgrading Flutter</a>]</blockquote><h4>- Projeyi Oluşturalım🆕</h4><p>Eğer Flutter kurulumunu gerçekleştirdiyseniz, bu aşamada hızlı ve basit bir şekilde proje oluşturabilirsiniz. Proje oluşturmayı bilmiyorsanız <a href="https://flutter.dev/docs/get-started/test-drive?tab=androidstudio">buraya tıklayarak</a> öğrenebilirsiniz.</p><p>Projeyi oluşturmak istediğimiz klasörü açtık ve <strong>Shift+Mouse Sağ Tık </strong>yaptıktan sonra <strong>Terminal</strong>i açıyoruz. <strong>flutter create prayertimes</strong> komutunu giriyoruz. Projemiz oluşturuluyor. Ardından cd prayertimes komutu ile klasör içine giriyoruz ve code . komutu ile <strong>Visual Studio Code </strong>kod<strong> </strong>editöründe projeyi açıyoruz.</p><h4>- Klasör Hiyerarşisini Düzenleyelim 📁</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/285/1*5ewUCguAmAf_XrUdb-kqUQ.png" /><figcaption>Project Folder Structure of PrayerTimes</figcaption></figure><p>Bir önceki <a href="https://medium.com/flutter-t%C3%BCrkiye/flutter-clean-code-c52ff8759c0e">Flutter: Clean Code</a> yazımda daha detaylı bahsetmiştim. Bu projemizde şimdilik bu klasörleri oluşturmamız yeterlidir.</p><h4>- Arayüzdeki Ögeleri Ekleyelim🖌️📝</h4><p>Tasarımda kullandığımız renkleri, yazıları, ikonları ve kütüphaneleri ekliyoruz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9dbdae5a1c106db6776150c40bc9799a/href">https://medium.com/media/9dbdae5a1c106db6776150c40bc9799a/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bb0d4b6fbb8a15455c2075ee39ffbfa9/href">https://medium.com/media/bb0d4b6fbb8a15455c2075ee39ffbfa9/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5cce9e58dfe065dc2f113ef321efaaaa/href">https://medium.com/media/5cce9e58dfe065dc2f113ef321efaaaa/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/920/1*vL2DDOW0U8dcW4SscjQK_A.png" /><figcaption>libraries</figcaption></figure><h4>- Logoyu Ekleyelim 🕌</h4><p>Projemizde logonun temaya uygun renk seçilebilmesi ve boyutunun istenildiği şekilde düzenlebilmesi için svg olarak kaydetmiştik. Logomuzu custom widget hale getirerek bu özellikleri verebiliriz. Projemizde bulunan <strong>lib &gt; ui &gt; widgets </strong>klasörüne<strong> </strong><strong>appLogo.dart </strong>dosyasını oluşturalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bbNeSZPc5qmKlj6QtS8Lvw.png" /><figcaption>appLogo.dart</figcaption></figure><h4>- Temayı Düzenleyelim🎨</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/270/1*IQkMfsUJnsw274w5Ak3I2w.png" /></figure><p>Koyu ve açık mod temalarımızı oluşturmak için öncelikle yandaki görselde görüldüğü gibi <strong>lib &gt; UI &gt; Theme</strong> klasörümüze dosyalarımızı oluşturuyoruz.</p><p>Örnek olarak<strong> koyu mod</strong> temamızı oluşturmayı göstereceğim. Açık moddan tek farkı renkler olacaktır.</p><p>final themeDarkData <strong>=</strong> <em>ThemeData</em>(); isimli bir ThemeData değişkeni oluşturuyoruz. Ardından property olarak brightness<strong>:</strong> <em>Brightness</em>.dark ekliyoruz. <em>Açık mod olsaydı </em><em>Brightness.light olarak eklememiz yeterli olacaktır. </em>Yazılar için tema eklerken, tasarımda kullandığımız <a href="https://fonts.google.com/specimen/Open+Sans"><strong>Google Open Sans</strong></a><strong> </strong>fontunu kullanabilmemiz için <a href="https://pub.dev/packages/google_fonts"><strong>google_fonts</strong></a><strong> </strong>paketini kurmamız gerekiyor ve geriye sadece renkleri ve yazı temalarını eklemek kalıyor.</p><blockquote>Projemizdeki pubspec.yaml dosyası içerisinden dependencies: alanına google_fonts: ^1.1.0eklememiz gerekmektedir. (Sürüm değişkenlik gösterebilir.)</blockquote><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/25d3668cfb6cc812c11f55e91768226d/href">https://medium.com/media/25d3668cfb6cc812c11f55e91768226d/href</a></iframe><p>Oluşturduğumuz temaları uygulamamıza şimdilik sadece tanımlıyoruz. Projemizdeki main.dart dosyası içerisindeki MaterialApp widget’ımızın theme ve darkTheme property’lerine ekliyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/852/1*zRPbD-s8K8EWn226qRjnlg.png" /><figcaption>main.dart of PrayerTimes App</figcaption></figure><h4>- Splash Ekranı Düzenleyelim⏰</h4><p>Splash ekranın amacından daha önce bahsetmiştik. Bu ekranı native bir şekilde düzenlemek için Android ve iOS tarafına da ayrı ayrı müdahale etmemiz gerekiyor.</p><p>Android için:</p><p>Projemizde bulunan <strong>android &gt; app &gt; src &gt; main &gt; res &gt; values </strong>klasörüne<strong> colors.xml </strong>dosyasını oluşturalım. Ardından aşağıda bulunan kodu yapıştıralım. <em>(Dilerseniz hex kodu ile yazılı olan rengi değiştirebilirsiniz.)</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/765eba58d346d5d06fa3829c1d1057df/href">https://medium.com/media/765eba58d346d5d06fa3829c1d1057df/href</a></iframe><p><strong>Adım 2) </strong>Projemizde bulunan <strong>android &gt; app &gt; src &gt; main &gt; res &gt; drawable &gt; launch_background.xml </strong>dosyasını açalım.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/946/1*lZTVtT3lOZJCevhj--Yp1Q.png" /><figcaption>launch_background.xml of PrayerTimes App</figcaption></figure><p>Dosyayı açtıktan sonra &lt;layer-list&gt; içerisinde bulunan &lt;item android:drawable=&quot;@android:color/white&quot; /&gt; satırı &lt;item android:drawable=”@color/splash_color” /&gt; ile değiştirelim. Bunu yapma amacımız, uygulama açılırken gösterilen beyaz sayfa yerine, dilediğimiz rengi gösterebilmemizdir.</p><p>Dilersek görselde ekleyebiliriz. Görsel eklemek istemiyorsanız, <strong>adım 4&#39;</strong>e geçiniz.</p><p><strong>Adım 3) </strong>Projemizde bulunan <strong>android &gt; app &gt; src &gt; main &gt; res &gt; drawable </strong>klasörüne logo.png dosyamızı ekleyelim. Ardından <strong>launch_background.xml </strong>dosyamızı açalım. <strong>Adım 2</strong>&#39;de eklediğimiz &lt;item&gt; elementinin altına, aşağıda bulunan kodu ekleyelim. <em>(Dikkat! </em><em>drawable/logo yazma sebebimiz dosyanın isminin </em><strong><em>logo </em></strong><em>olmasından dolayıdır.)</em></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/75b09aad41b1d0bb882efb766f4353f2/href">https://medium.com/media/75b09aad41b1d0bb882efb766f4353f2/href</a></iframe><p>Vee böylelikle Android native splash ekranımızı oluşturmuş olduk.</p><blockquote>iOS için şimdilik bu kısmı ne yazık ki gösteremiyorum. Maddi durumlardan dolayı henüz kendime Mac cihaz satın alamadım.</blockquote><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fb26xrSmDzn5fO%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fgiphy.com%2Fgifs%2Ftom-hardy-flowers-reggie-kray-b26xrSmDzn5fO&amp;image=https%3A%2F%2Fmedia1.giphy.com%2Fmedia%2Fb26xrSmDzn5fO%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="281" frameborder="0" scrolling="no"><a href="https://medium.com/media/32d0f7e41e956a20c7cda8904fd78918/href">https://medium.com/media/32d0f7e41e956a20c7cda8904fd78918/href</a></iframe><h4>- Onboarding Ekranı Hazırlayalım</h4><p><strong>Adım 1) </strong>Projemizde bulunan <strong>lib &gt; screens </strong>klasörüne, kodu yazacağımız <strong>onboarding_page.dart </strong>isimli dosyayı oluşturalım.</p><p><strong>Adım 2) <em>StatefulWidget </em></strong><em>oluşturalım.</em></p><p><strong>Adım 3) </strong><strong>main.dart </strong>dosyamıza geri dönelim ve <em>şimdilik </em>Onboarding Page<em> </em>dosyamıza yönlendirelim.</p><p><strong>Adım 4) </strong><strong>onboarding_page.dart </strong>dosyamıza geri dönelim. Tasarımda bulunan arkaplan gölgelendirmesini oluşturalım. Sayfanın tamamını kaplayacağından dolayı Container içerisindeheight ve width özelliklerinedouble.infinity değerini verelim. Ardından decoration özelliği içerisine gradient ekleyelim. Bu gölgelendirme dairesel olmasından dolayı bizim için <a href="https://api.flutter.dev/flutter/painting/RadialGradient-class.html"><em>RadialGradient</em></a><em> </em>en verimli sonucu verecektir. Değerlerimizi girdikten sonra sonuç bu şekilde olacaktır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/987/1*u4YQmgPLU-Qa9vB3nInnjQ.png" /><figcaption>gradient of onboarding page</figcaption></figure><p><strong>Adım 5) </strong>Tasarımımıza baktığımız zaman sırasıyla container, indicator ve buton görmekteyiz. Düşündüğümüz zaman bunları Columnwidget içerisine alarak sıralayabiliriz. Öncelikle bilgilendirme kutumuzu oluşturalım. Container içerisinde <a href="https://api.flutter.dev/flutter/widgets/PageView-class.html">PageView</a> ekleyelim. Bunu eklememizde en önemli faktör hem parmaklarımız ile kutucukları kaydırabilmemiz hem de aynı boyutta bir yapı oluşturmamıza olanak sağlamasıdır. PageView içerisinde özellik olarak physics<strong>:</strong> <a href="https://api.flutter.dev/flutter/widgets/ClampingScrollPhysics-class.html"><em>ClampingScrollPhysics</em></a><a href="https://api.flutter.dev/flutter/widgets/ClampingScrollPhysics-class.html">()</a> eklemeliyiz. Bu aynı zamanda belirlediğimiz sınırın dışına çıkmasını engellemektedir. PageView içerisine controller veonPageChanged özelliklerini de ekledikten sonra kutu içerisinde gerekli olan bilgilerimizi tutacağımız model sınıfımızı oluşturabiliriz.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/387421a63dac3226cddf3eb2925852d4/href">https://medium.com/media/387421a63dac3226cddf3eb2925852d4/href</a></iframe><blockquote>PageController ve anlık sayfayı gösterecek olan değişkeni eklemeyi unutmayın.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1xCAYCO__UMUrYN6d6xQZw.png" /></figure><p><strong>Adım 6) </strong>Projemizde bulunan <strong>lib &gt; models </strong>klasörüne, model sınıfımızı yazacağımız onboarding_model<strong>.dart </strong>isimli dosyayı oluşturalım.</p><p><strong>Adım 7) </strong>Tasarımımızdan gördüğümüz kadarıyla bilgilendirme kutucuklarımız; başlık, açıklama ve ikon barındırmaktadır ve geriye kalan her şey aynı olduğu için bu bilgilerden sınıf oluşturmamız yeterli olacaktır.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/888/1*y3wCPQqu2KMYRX1Ljx2How.png" /></figure><p><strong>Adım 8) </strong>Bilgilerimizin bulunduğu nesneleri tutacağımız listemizi oluşturalım.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ec913f9f3dbf7e41300db581f45c9cb8/href">https://medium.com/media/ec913f9f3dbf7e41300db581f45c9cb8/href</a></iframe><p><strong>Adım 9) </strong>Oluşturduğumuz modeli sayfa içerisine implemente ediyoruz.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u-mN3rILFtHbOU60wHb0GQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/372/1*dEL1Eyzhj3rYYvCxMJ0GHg.png" /><figcaption>onboarding screen of PrayerTimes App</figcaption></figure><p><strong>Adım 10) </strong>Tasarımda bulunan componentlere baktığımızda öncelikli olarak iki adet ana componentimiz var. Kırmızı renk ile işaretli olan componente baktığımızda Container içerisinde PageView ve onun içerisinde Column ardından Custom Widget , Text ve Text görmekteyiz. Bu tasarım yapısını oluşturduktan sonra onboarding ekranımızı tamamlamış oluyoruz.</p><p>Onboarding ekranına ait kodlara <a href="https://github.com/flutterturkey/prayer-times/blob/master/lib/screens/onboarding_page.dart">buradan</a> ulaşabilirsiniz.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FSEQf45Lg1mGbe%2Ftwitter%2Fiframe&amp;display_name=Giphy&amp;url=https%3A%2F%2Fgiphy.com%2Fgifs%2Fgravity-film-space-SEQf45Lg1mGbe&amp;image=https%3A%2F%2Fmedia2.giphy.com%2Fmedia%2FSEQf45Lg1mGbe%2Fgiphy.gif&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="217" frameborder="0" scrolling="no"><a href="https://medium.com/media/c726a6f5f6c4955ebc5bef0bbb2dcf85/href">https://medium.com/media/c726a6f5f6c4955ebc5bef0bbb2dcf85/href</a></iframe><p>Biraz uzun olmasından dolayı ve okunaklılığı artırmak amacıyla, izninizle yazıyı burada <strong>“Part 1”</strong> olarak tamamlamak istiyorum. Çok yakında <strong>“Part 2” </strong>de görüşmek üzere.</p><p>Yazıyı okuyarak zaman ayırdığınız ve sabırla sonuna kadar geldiğiniz için teşekkür ederim, umarım faydalı olmuştur.</p><p>Ve ayrıca teşekkür ederim:</p><p><a href="https://medium.com/flutter-t%C3%BCrkiye">Flutter Türkiye</a></p><p><a href="https://medium.com/u/69de64cd6243">Adem</a> ile birlikte geliştirdiğimiz açık kaynak projeye buradan ulaşabilir ve bize destek verebilirsiniz :</p><blockquote>Not: Proje; sınav, yoğun çalışma temposu ve benzeri nedenlerden dolayı henüz tamamlanamamıştır.</blockquote><p><a href="https://github.com/flutterturkey/prayer-times/">flutterturkey/prayer-times</a></p><p>Bu yazımı gözden geçirip geri bildirim verenlere özel teşekkür etmek istiyorum.</p><ul><li><a href="https://medium.com/u/914cc3056d24">Muhammed Salih Guler</a></li><li><a href="https://medium.com/u/e97a349e25ee">Beyza Sunay Güler</a></li><li><a href="https://medium.com/u/a8f607c08460">Zeynep Inkaya</a></li></ul><p>Bana aşağıdaki adreslerden ulaşabilirsiniz:</p><ul><li><em>Flutter Türkiye </em><a href="http://bit.ly/flutterturkiye"><em>Slack</em></a><em> Kanalı</em></li><li><a href="https://twitter.com/mukireuss"><em>Twitter</em></a><em> hesabımdan</em></li><li><a href="https://www.linkedin.com/in/muhammetomer/">LinkedIn</a> hesabımdan</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e03fc991d4c7" width="1" height="1" alt=""><hr><p><a href="https://medium.com/flutter-t%C3%BCrkiye/ba%C5%9Ftan-sona-flutter-projesi-ezan-vakti-part-1-e03fc991d4c7">Baştan Sona Flutter Projesi: Ezan Vakti (Part 1)</a> was originally published in <a href="https://medium.com/flutter-t%C3%BCrkiye">Flutter Türkiye</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>