<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alpha</title>
    <description>The latest articles on DEV Community by Alpha (@hassanteslim007).</description>
    <link>https://dev.to/hassanteslim007</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1121367%2F93bec5cb-102e-41c2-b196-01f128e18ef5.jpeg</url>
      <title>DEV Community: Alpha</title>
      <link>https://dev.to/hassanteslim007</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hassanteslim007"/>
    <language>en</language>
    <item>
      <title>I'm Building an App That Connects You with Strangers from Anywhere in the World</title>
      <dc:creator>Alpha</dc:creator>
      <pubDate>Mon, 02 Feb 2026 10:51:19 +0000</pubDate>
      <link>https://dev.to/hassanteslim007/im-building-an-app-that-connects-you-with-strangers-from-anywhere-in-the-world-published-4clm</link>
      <guid>https://dev.to/hassanteslim007/im-building-an-app-that-connects-you-with-strangers-from-anywhere-in-the-world-published-4clm</guid>
      <description>&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;Most people will never visit most places on Earth.&lt;br&gt;
But everyone can have a conversation.&lt;/p&gt;

&lt;p&gt;That thought sparked Meridian – an app that connects you with random people from any country, in any language. Think Omegle meets Duolingo meets a digital passport.&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;Pick a place – Tap anywhere on the map&lt;br&gt;
Get matched – Connect with someone who actually lives there&lt;br&gt;
Chat in any language – Real-time translation handles the rest&lt;br&gt;
Collect stamps – Build your digital passport with every conversation&lt;/p&gt;
&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;I just shipped the waitlist landing page and wanted to share the stack:&lt;/p&gt;

&lt;p&gt;Backend API&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET 8 Minimal APIs&lt;/li&gt;
&lt;li&gt;PostgreSQL on Render&lt;/li&gt;
&lt;li&gt;Entity Framework Core for data access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frontend&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vanilla HTML/CSS/JS (no framework needed for a landing page)&lt;/li&gt;
&lt;li&gt;CSS custom properties for theming&lt;/li&gt;
&lt;li&gt;Intersection Observer for scroll animations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Infrastructure&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Render for hosting (API + static site + database)&lt;/li&gt;
&lt;li&gt;Auto-deploy from GitHub&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Some Code Highlights
&lt;/h2&gt;

&lt;p&gt;Spam Protection&lt;br&gt;
Instead of adding reCAPTCHA (which hurts UX), I implemented invisible protection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Honeypot field - bots fill it, humans don't see it
if (!string.IsNullOrEmpty(request.Website))
{
    Console.WriteLine($"🤖 Bot detected: {ipAddress}");
    // Return fake success to not tip off the bot
    return Results.Ok(new WaitlistResponse(true, "Success", 999));
}
// Rate limiting - 3 signups per IP per hour
if (rateLimiter.IsRateLimited(ipAddress))
{
    return Results.BadRequest(new WaitlistResponse(false, "Too many requests"));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;UTM Tracking&lt;br&gt;
To see which platforms drive signups, I capture the source from the URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const urlParams = new URLSearchParams(window.location.search);
const utmSource = urlParams.get('utm_source') || 'landing-page';
// Later, in the fetch request:
body: JSON.stringify({
    email: email,
    source: utmSource
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I can share links like mysite.com?utm_source=devto and track conversions by platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Render's free tier works great for MVPs, but the cold start (50+ seconds) is rough&lt;/li&gt;
&lt;li&gt;Proxy IPs are tricky – I had to use X-Forwarded-For header for rate limiting&lt;/li&gt;
&lt;li&gt;Honeypot fields are surprisingly effective against basic bots&lt;/li&gt;
&lt;li&gt;Vanilla CSS with custom properties is all you need for a polished landing page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's Next&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building the core chat experience with SignalR for real-time messaging&lt;/li&gt;
&lt;li&gt;Integrating translation APIs&lt;/li&gt;
&lt;li&gt;Designing the passport/gamification system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try It Out&lt;br&gt;
I'd love early feedback! Join the waitlist:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://meridian-landing.onrender.com?utm_source=devto" rel="noopener noreferrer"&gt;https://meridian-landing.onrender.com?utm_source=devto&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And if you're curious about the code, drop a comment – happy to share more details.&lt;/p&gt;

&lt;p&gt;Building in public. One commit at a time.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>buildinpublic</category>
      <category>flutter</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Solving a Flutter iOS Crash: Service Protocol Failures &amp; Plugin Collisions</title>
      <dc:creator>Alpha</dc:creator>
      <pubDate>Mon, 07 Jul 2025 21:41:00 +0000</pubDate>
      <link>https://dev.to/hassanteslim007/solving-a-flutter-ios-crash-service-protocol-failures-plugin-collisions-15e5</link>
      <guid>https://dev.to/hassanteslim007/solving-a-flutter-ios-crash-service-protocol-failures-plugin-collisions-15e5</guid>
      <description>&lt;p&gt;While working on a Flutter app targeting iOS simulators, I ran into a frustrating error that appeared out of nowhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Error connecting to the service protocol: failed to connect to http://127.0.0.1:51062..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was immediately followed by a native macOS crash dialog:&lt;/p&gt;

&lt;p&gt;"Runner quit unexpectedly."&lt;/p&gt;

&lt;p&gt;Every time I clicked "Reopen," it just crashed again. The Flutter console eventually started spitting out this during hot restart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to Hot Restart: DebugAdapterException: app 'xxxx-xxxx' not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  First Aid: What to Try
&lt;/h2&gt;

&lt;p&gt;Every Flutter developer should run through these first-line recovery steps. These often fix transient or setup-related issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Clean Everything
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter clean
rm -rf ios/Pods ios/Podfile.lock pubspec.lock .dart_tool
flutter pub get
cd ios &amp;amp;&amp;amp; pod install &amp;amp;&amp;amp; cd ..
flutter run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? iOS builds cache native binaries and CocoaPods configs aggressively. Any inconsistency in plugin versions or native code will be left behind if not fully wiped.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Reboot Simulators
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;xcrun simctl shutdown all
xcrun simctl erase all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Simulators can become corrupted, especially after Xcode or iOS runtime updates. Resetting clears all app data and memory state.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Check connected Devices
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter devices
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it’s stuck on a simulator that no longer boots, pick another one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;open -a Simulator
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Run Flutter Doctor
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter doctor -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for anything red or yellow, especially issues with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Xcode Command Line Tools&lt;/li&gt;
&lt;li&gt;CocoaPods&lt;/li&gt;
&lt;li&gt;iOS Toolchain&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Restart Everything
&lt;/h3&gt;

&lt;p&gt;Sometimes macOS itself blocks port bindings or simulator-to-Dart VM communication. Restart your IDE, Terminal, Simulator, and if all else fails, your Mac.&lt;/p&gt;

&lt;p&gt;If you’ve tried all the above and still get:&lt;/p&gt;

&lt;p&gt;“Runner quit unexpectedly”&lt;br&gt;
"Service protocol connection failed"&lt;br&gt;
"Hot restart failed: app not found"&lt;/p&gt;

&lt;p&gt;...then you’re not dealing with a Dart error anymore. You’re likely hitting a native iOS crash. At this point:&lt;/p&gt;

&lt;p&gt;You need to investigate why the app crashes before the Dart VM boots.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Breakthrough: Reading the Crash
&lt;/h2&gt;

&lt;p&gt;In my case, none of the band aid worked and I was bleeding time and patience. There was insufficient message and errors to work with so I did the next best thing. &lt;br&gt;
Ran the code directly from Xcode. This gave me a goldmine of crash logs, and hiding in the crowd was this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Duplicate plugin key: VideoThumbnailPlugin'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A native plugin registration conflict.&lt;/p&gt;

&lt;h2&gt;
  
  
  Root Cause: Duplicate Plugin Registration
&lt;/h2&gt;

&lt;p&gt;Earlier I had thought about getting thumbnails from a video URL and I added "video thumbnail" package forgetting I already had a similar one from a different implementation but my pubspec.yaml looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;video_thumbnail: ^...
get_thumbnail_video: ^...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both plugins register the same iOS native plugin name: VideoThumbnailPlugin. Flutter on iOS does not allow two plugins to register with the same key, and this causes an Objective-C crash during app launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Option 1: Remove the Duplicate Plugin&lt;br&gt;
Keep only one of the conflicting plugins in your pubspec.yaml.&lt;br&gt;
Then rebuild:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter clean
flutter pub get
cd ios &amp;amp;&amp;amp; pod install &amp;amp;&amp;amp; cd ..
flutter run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Option 2: Rename the Plugin (If You Forked It)&lt;br&gt;
If you forked one of the plugins (e.g., get_thumbnail_video), you must:&lt;/p&gt;

&lt;p&gt;Rename the Objective-C class in ios/Classes/VideoThumbnailPlugin.m:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@implementation GetVideoThumbnailPlugin // ← renamed
Rename the registration function and key to avoid clashing with the original.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the conflict was removed, everything worked again:&lt;/p&gt;

&lt;p&gt;The Flutter app launched&lt;br&gt;
Service protocol connected&lt;br&gt;
Hot reload and devtools worked as expected&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Lessons
&lt;/h2&gt;

&lt;p&gt;Flutter’s native iOS plugins must have unique registration keys.&lt;/p&gt;

&lt;p&gt;A duplicate plugin crash happens before Dart is even loaded, so it won’t show in normal flutter run logs.&lt;/p&gt;

&lt;p&gt;Always try first aid steps before assuming your code is broken — but know when to dig into native logs.&lt;/p&gt;

&lt;p&gt;Use xcrun simctl or run the app from Xcode when things go wrong. It can save you hours.&lt;/p&gt;

&lt;p&gt;iOS crashes in Flutter can be deceptive. If your app dies before main() runs, always suspect:&lt;/p&gt;

&lt;p&gt;Plugin conflicts&lt;br&gt;
Info.plist issues&lt;br&gt;
Native code changes (especially after plugin updates)&lt;/p&gt;

&lt;p&gt;Debugging these crashes takes patience, but knowing what to check and in what order will save you a lot of frustration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Happy Coding&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ios</category>
      <category>flutter</category>
      <category>mobile</category>
      <category>programming</category>
    </item>
    <item>
      <title>Dart Extensions: Tips and Tricks</title>
      <dc:creator>Alpha</dc:creator>
      <pubDate>Fri, 03 Nov 2023 10:25:05 +0000</pubDate>
      <link>https://dev.to/hassanteslim007/dart-extensions-tips-and-tricks-3806</link>
      <guid>https://dev.to/hassanteslim007/dart-extensions-tips-and-tricks-3806</guid>
      <description>&lt;h2&gt;
  
  
  What are Dart Extensions?
&lt;/h2&gt;

&lt;p&gt;Dart Extensions are a way to add new methods, getters, or setters to existing classes. This feature enables developers to write cleaner and more organized code by avoiding the need to create separate utility classes or modify the original class. It also allows for better code reusability.&lt;/p&gt;

&lt;p&gt;The need for Dart Extensions arises from the desire to keep code modular and easy to maintain. When you want to add specific functionality to a class, it's better to use extensions instead of cluttering the class with unrelated methods. This approach enhances code readability and maintainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Define Dart Extensions
&lt;/h3&gt;

&lt;p&gt;Defining a Dart Extension is straightforward. You create an extension by using the extension keyword, followed by the extension name. Then, you specify the class you want to extend and add the new methods, getters, or setters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extension ExtensionName on ExtendedType {
  // Define extension methods and properties here
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ExtensionName&lt;/strong&gt;: This is the name you give to your extension. It can be any valid identifier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ExtendedType&lt;/strong&gt;: This is the type you want to extend with additional methods or properties. It can be a class, interface, or a built-in type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Dart Extensions
&lt;/h3&gt;

&lt;p&gt;To use Dart Extensions, import the necessary library and call the extension method on an instance of the class you want to extend. This allows you to access the new functionality provided by the extension.&lt;br&gt;
Extensions can also be used on custom classes as shown in an example below.&lt;/p&gt;
&lt;h3&gt;
  
  
  Examples
&lt;/h3&gt;

&lt;p&gt;Here's a simple example showing how to extend the dart String class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//defining the extension
extension StringExtension on String {
//getter
  int get wordCount {
    // Split the string by whitespace and count the words
    return split(' ').where((word) =&amp;gt; word.isNotEmpty).length;
  }
}

//using the extension
String foo = 'Hello';
print(foo.wordCount); //result: 1

String bar = "My name is Alpha";
print(bar.wordCount); // result: 4

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below is another example extending the integer built-in type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//defining the extension
extension IntExtension on int{
  //method
  bool isPrime(){
    bool prime = true;
    for(int i in List.generate(this, (index) =&amp;gt; index+1) ){
      if(i == this) break;
      if(i == 1) continue;
      if(this%i == 0){
        prime = false;
        break;
      } else {
        prime = true;
      }

    }
    return prime;
  }

//using the extension
int x = 2;
print(x.isPrime()); //result: true

print(6.isPrime()); //result: false
print(7.isPrime()); //result: true
print(1101.isPrime()); // result false
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we didn't include the brackets when calling the wordCount String extension because it's a getter but we included the brackets in the isPrime() int extension because it is a method(function).&lt;/p&gt;

&lt;p&gt;For custom classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//class creation
class Person {
  final String name;
  final DateTime birthdate;

  Person({required this.name, required this.birthdate});
}

//extending class
extension PersonAgeExtension on Person {
  int get age {
    final currentDate = DateTime.now();
    final age = currentDate.year - birthdate.year;

    if (birthdate.isAfter(currentDate.subtract(Duration(years: age))) {
      return age - 1;
    } else {
      return age;
    }
  }
}

//using extension
  final person = Person(name: 'John Doe', birthdate: DateTime(1990, 5, 15));

  final age = person.age;
  print('${person.name} is $age years old.');
//result: John doe is 33 years old
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dart Extensions vs. Inheritance
&lt;/h2&gt;

&lt;p&gt;Dart Extensions offers a different approach to extending class functionality compared to inheritance. While inheritance creates a new class hierarchy, extensions enhance existing classes, making them more suitable for certain scenarios.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatibility
&lt;/h2&gt;

&lt;p&gt;Dart Extensions are supported in Dart 2.7 and later versions. They work seamlessly with Dart and Flutter, making them an essential feature for developers working on these platforms.&lt;/p&gt;

&lt;p&gt;In the context of Flutter, Dart Extensions can be particularly useful for adding custom functionality to Flutter widgets or enhancing the functionality of existing packages. They contribute to creating a more expressive and efficient codebase for Flutter apps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Dart Extensions are a powerful feature in the Dart programming language, enabling developers to enhance existing classes with new methods and functionality. They improve code organization, reusability, and compatibility, making them a valuable tool in your development arsenal.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Exploring Simple Widgets II: Autocomplete</title>
      <dc:creator>Alpha</dc:creator>
      <pubDate>Thu, 31 Aug 2023 09:24:16 +0000</pubDate>
      <link>https://dev.to/hassanteslim007/exploring-simple-widgets-ii-autocomplete-279f</link>
      <guid>https://dev.to/hassanteslim007/exploring-simple-widgets-ii-autocomplete-279f</guid>
      <description>&lt;p&gt;Making user-friendly and effective interfaces is crucial in today's quickly changing world of app development. The Flutter autocomplete widget is one of the widgets that have the potential to substantially improve the user experience. This dynamic feature makes entering and retrieving data easier while enhancing user involvement. This post will explore Flutter's autocomplete widget and show how it can improve how users experience your apps.&lt;/p&gt;

&lt;p&gt;The Autocomplete widget is a powerful widget provided by the Flutter library that enables users to efficiently input data by offering predictive suggestions. This functionality significantly reduces user effort and enhances their experience. There are use cases for this widget in E-commerce apps where users can get real-time suggestion when searching for a product, travel and booking apps to suggest places to users and much more.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the Autocomplete Widget
&lt;/h2&gt;

&lt;p&gt;In your scaffold body, we create the Autocomplete widget and provide the required &lt;em&gt;optionsBuilder&lt;/em&gt; parameter which is used to provide the list of suggestions that should be displayed when the field is focused. The autocomplete widget infers a type T that extends Object and as such should be created with the type which could be int, String or even custom Objects.&lt;br&gt;
The stripped down code of the autocomplete widget would look like so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Autocomplete'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(18.0),
        child: Center(
          child: Autocomplete&amp;lt;int&amp;gt;(
            optionsBuilder: (val){
              return [1,2,3,4,5];
            },
          )
        ),
      )
       );
       }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdoonk90rg63i6hy75e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqdoonk90rg63i6hy75e6.png" alt="Automplete&amp;lt;int&amp;gt;" width="800" height="1188"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Autocomplete'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(18.0),
        child: Center(
          child: Autocomplete&amp;lt;String&amp;gt;(
            optionsBuilder: (val){
              return ['Cat', 'Dog', 'Fish', 'Goat', 'Sheep'];
            },
          )
        ),
      )
       );
       }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrxtb3vr3s8gfrpm6r06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrxtb3vr3s8gfrpm6r06.png" alt="Autocomplete&amp;lt;String&amp;gt;" width="800" height="1188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above implementation shows the suggestions as soon as the textfield is in focus but that isn't what we aim to achieve. There are other parameters that gives us customization and allow us to tweak the widget to our need.&lt;br&gt;
To begin, we can customize the widget to only show the options as soon as the user starts typing and show only relevant options based on user input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Home extends StatelessWidget {
  List&amp;lt;String&amp;gt; animals = ['Cat', 'Dog', 'Fish', 'Goat', 'Sheep'];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Autocomplete'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(18.0),
        child: Center(
          child: Autocomplete&amp;lt;String&amp;gt;(
            optionsBuilder: (val){
              if(val.text.isEmpty){
                return [];
              }
              return animals.where((animal){
                return animal.toLowerCase().contains(val.text);
              });
            },
          )
        ),
      )
       );
       }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot0h7l4vnjtg6dhp0we8.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot0h7l4vnjtg6dhp0we8.gif" alt="Autocomplete gif" width="600" height="1050"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing Options
&lt;/h2&gt;

&lt;p&gt;Using the &lt;em&gt;optionsViewBuilder&lt;/em&gt; parameter, we can customize the way our suggestions are presented to fit our app's design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Autocomplete&amp;lt;String&amp;gt;(
            optionsBuilder: (val){
              if(val.text.isEmpty){
                return [];
              }
              return animals.where((animal){
                return animal.toLowerCase().contains(val.text.toLowerCase());
              });
            },
            optionsViewBuilder: (context,onSelected, options){
             return ListView.builder(
                    itemCount: options.length,
                    itemBuilder: (context,index){
                            String x = options.elementAt(index);
                      return Card(child: ListTile(
                        onTap: () =&amp;gt; onSelected(x),
                        title: Text(x, style: TextStyle(color: Colors.blue))));
                    },
                  );
            },
          )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivege81yuf4rxfaq40yr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivege81yuf4rxfaq40yr.png" alt="Customized options" width="800" height="1276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The autocomplete widget can be populated with various customized list and even data fetched asynchronously opening  various possibilities to the usage. There are also various packages that have been made for even more customization and flexibility to save you a ton of stress. Find them on &lt;a href="https://pub.dev/packages?q=autocomplete" rel="noopener noreferrer"&gt;Pub.dev&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Autocomplete widgets shine as tools that not only enhance efficiency but also contribute to the overall satisfaction of users. From their seamless implementation to their potential across various industries, autocomplete widgets empower developers to create highly interactive, top-tier applications.&lt;br&gt;
For more information, check out the &lt;a href="https://api.flutter.dev/flutter/material/Autocomplete-class.html" rel="noopener noreferrer"&gt;Flutter docs for the autocomplete class&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>android</category>
      <category>widget</category>
    </item>
    <item>
      <title>Exploring Simple Widgets I: The Expansion Tile</title>
      <dc:creator>Alpha</dc:creator>
      <pubDate>Sun, 06 Aug 2023 22:18:07 +0000</pubDate>
      <link>https://dev.to/hassanteslim007/exploring-simple-widgets-i-the-expansion-tile-2amh</link>
      <guid>https://dev.to/hassanteslim007/exploring-simple-widgets-i-the-expansion-tile-2amh</guid>
      <description>&lt;h2&gt;
  
  
  What is the Expansion Tile Widget?
&lt;/h2&gt;

&lt;p&gt;The Expansion Tile Widget is a part of the Flutter material library that allows developers to create a collapsible tile with two states: &lt;strong&gt;expanded&lt;/strong&gt; and &lt;strong&gt;collapsed&lt;/strong&gt;. It is widely used to create lists with items that can expand or collapse to reveal more content. This widget is particularly useful when dealing with limited screen space and the need to display additional information when required. &lt;/p&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;The Expansion Tile Widget consists of a header and a body. When the user taps on the header, the widget expands, revealing the content inside the body. Subsequently, another tap collapses the widget, hiding the content. Think of things like FAQ section where the answer to a question is revealed when  the question tile is clicked on or a Post that reveals more info (or a comment section) when clicked.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use the Expansion Tile
&lt;/h2&gt;

&lt;p&gt;To use the Expansion Tile Widget, simply add it to the body of your scaffold. It has a single required &lt;em&gt;title&lt;/em&gt; parameter which takes a widget (so it could be literally any widget). It shows the title of the Expansion tile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expansion Tile'),
      ),
      body: Center(
        // our Expansion Tile here
        child: ExpansionTile(
          title: Text('Hey, I can Expand'),

        ),
      ) );
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq37gqhaoepcvsnkewbv1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq37gqhaoepcvsnkewbv1.png" alt="Collapsed State" width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2az5graopoydplns8h8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2az5graopoydplns8h8e.png" alt="Expanded State but Empty" width="800" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Although we can see the change when we click on the tile, it doesn't exactly expand. That's because we haven't added the hidden items.&lt;/p&gt;

&lt;p&gt;To add the hidden items to be revealed, we have a &lt;em&gt;children&lt;/em&gt; property that takes in a List of widgets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ExpansionTile(
          title: Text('Hey, I Expand'),
          //adding the hidden items
          children: [
            ListTile(
              title: Text('Can you see me? I am a ListTile'),
              trailing: Icon(Icons.waving_hand)
            ),
             SizedBox(height: 10,),
            Text('I am a boring Text'),
            SizedBox(height: 10,),
            CircleAvatar(
              radius: 25,
              child: CircleAvatar(
                radius: 20,
                backgroundColor: Colors.white,
                child: FlutterLogo()),
            )
          ],
        ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pfmi5nfihzz5ao2bwo7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pfmi5nfihzz5ao2bwo7.png" alt="Expanded state with Children" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well, that's basically all you need to do to use the ExpansionTile widget. But there are other fun stuff to play around with.&lt;br&gt;
As you can see, there's a default expand more(arrow down) and expand less(arrow down) icon when we expand and collapse the tile, we can use our preferred Icon(or widget) using the &lt;em&gt;trailing&lt;/em&gt; parameter or nothing at all by just setting the value to a SizedBox. &lt;br&gt;
There's also an &lt;em&gt;onExpansionChanged&lt;/em&gt; parameter which takes a function with a boolean param that basically tells us the state of the tile and we can do something in this function when we change the state of the tile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Home extends StatefulWidget {
  @override
  State&amp;lt;Home&amp;gt; createState() =&amp;gt; _HomeState();
}

class _HomeState extends State&amp;lt;Home&amp;gt; {
  bool isExpanded = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expansion Tile'),
      ),
      body: Center(
        child: ExpansionTile(
          title: Text('Hey, I Expand'),
          trailing: Text(isExpanded ? 'close' : 'open'),
          //adding the hidden items
          onExpansionChanged: (val){
            setState((){
              isExpanded = val;
            });
          },
          children: [
            ListTile(
              title: Text('Can you see me? I am a ListTile'),
              trailing: Icon(Icons.waving_hand)
            ),
             SizedBox(height: 10,),
            Text('I am a boring Text'),
            SizedBox(height: 10,),
            CircleAvatar(
              radius: 25,
              child: CircleAvatar(
                radius: 20,
                backgroundColor: Colors.white,
                child: FlutterLogo()),
            )
          ],
        ),
      ) );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen7tpg7x7j8wa9rax0jh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fen7tpg7x7j8wa9rax0jh.png" alt="Collapsed tile with custom trailing" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcg5vn7qpvvu2d7zdaob5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcg5vn7qpvvu2d7zdaob5.png" alt="Expanded tile with custom trailing" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the snippet above, we changed our &lt;em&gt;Home&lt;/em&gt; to a stateful widget so we could update our trailer from open to closed using setState((){}) when the tile changes.&lt;/p&gt;

&lt;p&gt;There are other interesting attributes in the Expansion tile which includes boolean values &lt;em&gt;intiallyExpanded&lt;/em&gt; for specifying the initial state of the tile and &lt;em&gt;maintainState&lt;/em&gt; to specify whether the children widget be kept in the widget tree or recreated each time the tile is Expanded.&lt;br&gt;
There is also the &lt;em&gt;tilePadding&lt;/em&gt; for specifying the padding of the Expansion tile and &lt;em&gt;childrenPadding&lt;/em&gt; for the children's padding.&lt;br&gt;
Other values are provided are for styling our ExpansionTile includes such as the colors and shapes.&lt;/p&gt;

&lt;p&gt;Here's a full list of all its Attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(new) ExpansionTile ExpansionTile({
  Key? key,
  Widget? leading,
  required Widget title,
  Widget? subtitle,
  void Function(bool)? onExpansionChanged,
  List&amp;lt;Widget&amp;gt; children = const &amp;lt;Widget&amp;gt;[],
  Widget? trailing,
  bool initiallyExpanded = false,
  bool maintainState = false,
  EdgeInsetsGeometry? tilePadding,
  CrossAxisAlignment? expandedCrossAxisAlignment,
  Alignment? expandedAlignment,
  EdgeInsetsGeometry? childrenPadding,
  Color? backgroundColor,
  Color? collapsedBackgroundColor,
  Color? textColor,
  Color? collapsedTextColor,
  Color? iconColor,
  Color? collapsedIconColor,
  ShapeBorder? shape,
  ShapeBorder? collapsedShape,
  Clip? clipBehavior,
  ListTileControlAffinity? controlAffinity,
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Nesting Expansion Tiles
&lt;/h2&gt;

&lt;p&gt;A common question that comes to mind is whether we can nest multiple expansion tiles in each other.Yes we can! However, while this is possible, it is advisable to limit the depth of the nesting to avoid overwhelming the user and to maintain a clear interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Home extends StatefulWidget {
  @override
  State&amp;lt;Home&amp;gt; createState() =&amp;gt; _HomeState();
}

class _HomeState extends State&amp;lt;Home&amp;gt; {
  bool isExpanded = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Expansion Tile'),
      ),
      body: Center(
        child: Column(
          children: [
            ExpansionTile(
              controlAffinity: ListTileControlAffinity.trailing,
              title: Text('Hey, I Expand'),
              initiallyExpanded: true,
              maintainState: true,
              subtitle: Text('Click me'),
              trailing: Text(isExpanded ? 'close' : 'open'),
              //adding the hidden items
              onExpansionChanged: (val){
                setState((){
                  isExpanded = val;
                });
              },
              children: [
                ListTile(
                  title: Text('Can you see me? I am a ListTile'),
                  trailing: Icon(Icons.waving_hand)
                ),
                 SizedBox(height: 10,),
                Text('I am a boring Text'),
                SizedBox(height: 10,),
                CircleAvatar(
                  radius: 25,
                  child: CircleAvatar(
                    radius: 20,
                    backgroundColor: Colors.white,
                    child: FlutterLogo()),
                )
              ],
            ),
            ExpansionTile(
  title: Text('Parent Tile'),
  children: [
    ExpansionTile(
      title: Text('Child Tile 1'),
      children: [
        ListTile(
          title: Text('Content 1'),
        ),
      ],
    ),
    ExpansionTile(
      title: Text('Child Tile 2'),
      children: [
        ListTile(
          title: Text('Content 2'),
        ),
      ],
    ),
  ],
)
          ],
        ),
      ) );
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyu85efl39ek3zikxu2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyu85efl39ek3zikxu2b.png" alt="Multiple Expansion Tiles" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz8td7fr5h0e0hqdypv9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flz8td7fr5h0e0hqdypv9.png" alt="Nested Expansion Tile depth 1" width="800" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xhatbozqboivo990tzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xhatbozqboivo990tzz.png" alt="Nested Expansion Tile depth 2" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Expansion Tile Widget in Flutter provides developers with a powerful tool to create collapsible and expandable content areas, enhancing user experience and improving UI design. By customizing the widget's appearance and behaviour, developers can create intuitive and engaging interfaces for their Flutter applications.&lt;/p&gt;

&lt;p&gt;Checkout an interesting use of Expansion Tile in the GitHub gist below: &lt;br&gt;
&lt;a href="https://gist.github.com/HassanTeslim007/f5add1d59c55d1bb5159dc8e591c399d" rel="noopener noreferrer"&gt;Github Gist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please suggest in the comment what Widget I should look into next. Thank you &lt;/p&gt;

</description>
      <category>flutter</category>
      <category>mobile</category>
      <category>coding</category>
      <category>dart</category>
    </item>
    <item>
      <title>Unleashing the Power of Flutter Slivers: Dive into a Scrollable Wonderland!</title>
      <dc:creator>Alpha</dc:creator>
      <pubDate>Fri, 28 Jul 2023 20:23:57 +0000</pubDate>
      <link>https://dev.to/hassanteslim007/unleashing-the-power-of-flutter-slivers-dive-into-a-scrollable-wonderland-38ed</link>
      <guid>https://dev.to/hassanteslim007/unleashing-the-power-of-flutter-slivers-dive-into-a-scrollable-wonderland-38ed</guid>
      <description>&lt;p&gt;Are you ready to take your Flutter app's user interface to the next level? Buckle up as we embark on an exhilarating journey into the captivating world of Flutter Slivers. Get ready to wield the magical abilities of slivers to create dynamic, responsive, and awe-inspiring scrollable areas like never before!&lt;/p&gt;

&lt;p&gt;Flutter, the beloved open-source UI software development kit by Google, brings to the table an enchanting concept known as Slivers. These spellbinding widgets empower developers to craft captivating scrollable areas within their apps, opening a realm of endless possibilities for creative layouts and engaging interactions.&lt;/p&gt;

&lt;p&gt;In this article, we'll be your trusty guide, unravelling the mysteries of Flutter Slivers and showing you how to harness their potential to create mesmerizing user experiences. The CustomScrollView acts as the gateway to the realm of Slivers. Through its harmonious orchestration of slivers, we shall wield the powers of dynamic app bars, smooth grids, and interactive lists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our Journey&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unravelling the Magic of SliverAppBar&lt;/li&gt;
&lt;li&gt;SliverGrid and SliverList: Where Data Unites with Artistry!&lt;/li&gt;
&lt;li&gt;Ascend to Great Heights: Unforgettable Headers with SliverPersistentHeader&lt;/li&gt;
&lt;li&gt;Harnessing Pure Magic: SliverToBoxAdapter and SliverFillRemaining&lt;/li&gt;
&lt;li&gt;Crafting Unique Tales: Delight with Animated Slivers &lt;/li&gt;
&lt;li&gt;Building Complex Layouts with Nested Slivers &lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Quest Begins: Dive into the First Few Slivers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unravelling the Magic of SliverAppBar
&lt;/h3&gt;

&lt;p&gt;Our expedition starts with the venerable SliverAppBar, a versatile hero that smoothly morphs its appearance as users scroll. It creates dynamic app bars that captivate your audience with their graceful animations and customizable elements. It automatically adjusts its size and appearance based on the scroll position. The SliverAppBar can include various magical attributes like titles, icons, buttons, and even flexible spaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; SliverAppBar(
  expandedHeight: 200.0,
  pinned: true,
  flexibleSpace: FlexibleSpaceBar(
  background: Image.network(
                'https://example.com/your_image.jpg',
                fit: BoxFit.cover,
              ),
  title: Text('Sage SliverAppBar'),
              centerTitle: true,
            ),
          ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SliverGrid and SliverList: Where Data Unites with Artistry!
&lt;/h3&gt;

&lt;p&gt;In this realm of creativity and precision, SliverGrid and SliverList come to life. Marvel at their combined power to organize your data into symmetrical harmony, dynamically adjusting to various screen sizes with grace. Rows and columns flow together like magic, presenting your information in a mesmerizing grid/list. Whether short or long, your lists will leave a lasting impression on those who dare to scroll through your enchanted creations.&lt;/p&gt;

&lt;p&gt;The SliverGrid widget provides a way to display items in a grid layout within a scrollable area. It is an excellent choice when you need to present data in a tabular or card-based format. SliverGrid offers flexibility in terms of item size, spacing, and responsiveness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SliverGrid(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              crossAxisSpacing: 8.0,
              mainAxisSpacing: 8.0,
            ),
  delegate: SliverChildBuilderDelegate(
              (context, index) {
                return Container(
                  color: Colors.blue,
                  alignment: Alignment.center,
                  child: Text(
                    'Grid Item $index',
                    style: TextStyle(color: Colors.white, fontSize: 16),
                  ),
                );
              },
              childCount: 10,
            ),
          ),

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SliverList widget is used to display a list of items in a scrollable area. It is particularly useful when dealing with a large number of items as it efficiently manages the memory by only rendering the items visible on the screen. SliverList allows for smooth scrolling and supports various customization options.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return ListTile(
                  leading: Icon(Icons.circle),
                  title: Text('List Item $index'),
                  subtitle: Text('Subtitle $index'),
                );
              },
              childCount: 20,
            ),
          ),

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ascend to Great Heights: Unforgettable Headers with SliverPersistentHeader
&lt;/h2&gt;

&lt;p&gt;As we climb higher, we encounter the majestic SliverPersistentHeader. Behold, a header that stands resolute, even as the content scrolls beneath. With its guidance, you'll craft breathtaking headers that keep users informed and connected, no matter where their journey leads.&lt;/p&gt;

&lt;p&gt;The SliverPersistentHeader widget enables developers to create headers that persist at the top of a scrollable area, even when the content is scrolled. This is useful for scenarios where you want to maintain a header with important information or navigation options visible to the user at all times.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
class MyPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      color: Colors.blue,
      alignment: Alignment.center,
      child: Text(
        'Persistent Header',
        style: TextStyle(color: Colors.white, fontSize: 20),
      ),
    );
  }

  @override
  double get maxExtent =&amp;gt; 100.0;

  @override
  double get minExtent =&amp;gt; 60.0;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To use the custom persistent header, we summon it into the delegate property of the SliverPersistentHeader and pin it!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; SliverPersistentHeader(
            pinned: true,
            delegate: MyPersistentHeaderDelegate(),
          ),

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Harnessing Pure Magic: SliverToBoxAdapter and SliverFillRemaining
&lt;/h2&gt;

&lt;p&gt;Amidst our adventure, we'll stumble upon the art of seamlessly integrating non-scrollable elements using SliverToBoxAdapter. Discover how to add static content that perfectly blends into your scrolling realm.&lt;br&gt;
The SliverToBoxAdapter widget allows you to insert a non-scrollable widget into a scrollable area. It is often used when you need to include static content or widgets that don't require scrolling within a larger scrollable layout. SliverToBoxAdapter provides a straightforward way to integrate non-scrollable elements seamlessly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; SliverToBoxAdapter(
            child: Container(
              color: Colors.blue,
              height: 100.0,
              alignment: Alignment.center,
              child: Text(
                'SliverToBoxAdapter Content',
                style: TextStyle(color: Colors.white, fontSize: 20),
              ),
            ),
          ),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you think you've seen it all, SliverFillRemaining takes center stage, ensuring no empty spaces tarnish your masterpiece. The true hero of responsive design, it dutifully occupies the remaining space, maintaining the perfect harmony of your scrollable kingdom. &lt;/p&gt;

&lt;p&gt;The SliverFillRemaining widget takes up the remaining space in a scrollable area, ensuring that no empty space is left at the end. It is particularly useful when you have a layout that requires some widgets to occupy a fixed amount of space, while others dynamically expand to fill the remaining area.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crafting Unique Tales: Delight with Animated Slivers
&lt;/h2&gt;

&lt;p&gt;But our journey doesn't end there! We unlock the secrets of animation with SliverChildBuilderDelegate and create enchanting scrollable animations with SliverAnimatedList. Immerse users in a realm of wonders as your lists come alive with captivating transitions. &lt;/p&gt;

&lt;h3&gt;
  
  
  A Symphony of Opacity: SliverAnimatedOpacity and SliverFadeTransition
&lt;/h3&gt;

&lt;p&gt;Just when you thought the wonders were over, we reveal the mesmerizing SliverAnimatedOpacity. Bring elements to life with graceful opacity animations that dance with the scroll, leaving your users spellbound. But the magic doesn't end there! SliverFadeTransition steps into the limelight, orchestrating smooth fade transitions on slivers. Embrace the power of subtlety and elevate the user experience of your scrollable landscapes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Somewhere in your state class
  bool _isVisible = true;
. 
.
.
SliverAnimatedOpacity(
            opacity: _isVisible ? 1.0 : 0.0,
            duration: Duration(milliseconds: 500),
            sliver: SliverFillRemaining(
              hasScrollBody: false,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _isVisible = !_isVisible;
                  });
                },
                child: Container(
                  color: Colors.blue,
                  alignment: Alignment.center,
                  child: Text(
                    'SliverAnimatedOpacity Content',
                    style: TextStyle(color: Colors.white, fontSize: 20),
                  ),
                ),
              ),
            ),
          ),
          SliverFadeTransition(
            opacity: _isVisible
                ? AlwaysStoppedAnimation(1.0)
                : Tween&amp;lt;double&amp;gt;(begin: 1.0, end: 0.0).animate(
                    CurvedAnimation(
                      parent: ModalRoute.of(context)!.animation!,
                      curve: Curves.fastOutSlowIn,
                    ),
                  ),
            sliver: SliverFillRemaining(
              hasScrollBody: false,
              child: GestureDetector(
                onTap: () {
                  setState(() {
                    _isVisible = !_isVisible;
                  });
                },
                child: Container(
                  color: Colors.blue,
                  alignment: Alignment.center,
                  child: Text(
                    'SliverFadeTransition Content',
                    style: TextStyle(color: Colors.white, fontSize: 20),
                  ),
                ),
              ),
            ),
          ),

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Final Puzzle: Building Complex Layouts with Nested Slivers
&lt;/h2&gt;

&lt;p&gt;As our adventure reaches its zenith, we unleash the ultimate power of nested slivers. With this grand finale, you'll craft complex and interactive layouts that defy expectations&lt;br&gt;
Nesting different types of slivers allows for building intricate UI designs with varying scrolling behaviours and interactive elements. Understanding how to structure and compose nested slivers is key to creating advanced Flutter layouts. Seamlessly combine slivers of different types to create a symphony of scrolling experiences that leave your users awe-inspired. &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion, Slivers offer various options for creating headers, lists, grids, and complex layouts. By leveraging the flexibility and customization provided by Slivers, you can create engaging and visually appealing user interfaces.&lt;/p&gt;

&lt;p&gt;In this article, we have explored the world of Flutter Slivers, understanding their purpose, and how to utilize them in your Flutter applications. Flutter Slivers provide a powerful mechanism for building dynamic and responsive scrollable areas in your Flutter applications. By taking advantage of the various types of slivers available, you can create highly dynamic and responsive user interfaces. Start experimenting with Flutter Slivers today and elevate your app's scrolling experience!&lt;/p&gt;

&lt;p&gt;Remember, Flutter's flexibility and the power of slivers enable you to design elegant and efficient user interfaces that engage your users and deliver an exceptional experience. Happy coding and enjoy creating stunning Flutter apps with Slivers!&lt;/p&gt;

&lt;p&gt;Here’s a gist showing the use of  our Sliver working together in perfect harmony&lt;br&gt;
&lt;a href="https://gist.github.com/HassanTeslim007/3ed141135db4f0bf3b43f2b839e810e2" rel="noopener noreferrer"&gt;See Github gist&lt;/a&gt;&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>android</category>
      <category>ios</category>
    </item>
  </channel>
</rss>
