<?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: Ann Mary John</title>
    <description>The latest articles on DEV Community by Ann Mary John (@annmaryjohn).</description>
    <link>https://dev.to/annmaryjohn</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%2F3027446%2F25747042-98e0-4d75-85cf-cef1d2dfd358.png</url>
      <title>DEV Community: Ann Mary John</title>
      <link>https://dev.to/annmaryjohn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/annmaryjohn"/>
    <language>en</language>
    <item>
      <title>🎨 Building a Custom Circular Data Grid in Flutter Using CustomPainter</title>
      <dc:creator>Ann Mary John</dc:creator>
      <pubDate>Wed, 09 Apr 2025 09:31:16 +0000</pubDate>
      <link>https://dev.to/annmaryjohn/building-a-custom-circular-data-grid-in-flutter-using-custompainter-3ig4</link>
      <guid>https://dev.to/annmaryjohn/building-a-custom-circular-data-grid-in-flutter-using-custompainter-3ig4</guid>
      <description>&lt;p&gt;When you need pixel-perfect control over your UI, Flutter’s CustomPainter opens the door to beautiful and creative layouts. In this post, I'll show you how I built a circular data grid using CustomPainter, with color-coded values and a dynamic legend.&lt;br&gt;
Use cases for this kind of visualization include:&lt;/p&gt;

&lt;p&gt;1.Budget/performance heatmaps &lt;br&gt;
2.Status indicators&lt;br&gt;
3.Visual goal tracking&lt;/p&gt;

&lt;p&gt;Let’s jump in! 🚀&lt;/p&gt;
&lt;h3&gt;
  
  
  🧠 The Data Model
&lt;/h3&gt;

&lt;p&gt;We start by defining some basic models to structure our data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class DataGridModel {
  final GridLegendLevel value;
  final String? date;
  DataGridModel({required this.value, this.date});
}

class CircularDataGridModel {
  final List&amp;lt;DataGridModel&amp;gt; data;
  final int length;
  final GridContext context;

  CircularDataGridModel(
   {
    required this.data,
    required this.length,
    required this.context,
  });
}


enum GridContext {
  statusCrimson600IntensityLevels(3),
  statusGold500MutedPerLevels(5);

  final int nosOfColor; //for the different number of colors that can represent the data

  const GridContext(this.nosOfColor);
} // Defines the purpose of the grid

enum GridLegendLevel {
  // Intensity Levels
  high,
  moderate,
  none,

  // Performance Levels
  recommended,
  wellDone,
  stayUnder,
  overTheLimit,
}

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

&lt;/div&gt;



&lt;p&gt;This setup gives you a grid based on a list of values, with context-specific coloring.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎨 Color Mapping Logic
&lt;/h3&gt;

&lt;p&gt;Depending on the context, we assign different color palettes to our cells:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ColorPalleteMapper {
  static Color getColor(GridContext context, GridLegendLevel value) {
    switch (context) {
      case GridContext.statusCrimson600IntensityLevels:
        return _getStatusCrimson600Muted(value);
      }
  }

  static Color _getStatusCrimson600Muted(GridLegendLevel value) {
    //return color based on the legend level
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  🧩 The Widget Setup
&lt;/h3&gt;

&lt;p&gt;We start by defining a CircularGridPainter that uses Canvas to draw each grid cell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CircularGridPainter extends CustomPainter {
  final CircularDataGridModel gridData;

  CircularGridPainter({super.repaint, required this.gridData});

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔢 Calculate Rows, Columns, and Cell Size
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int totalCells = gridData.data.length;
  int rows = gridData.length + 1;
  int columns = gridData.length;
  double cellWidth = 30.h;
  double cellHeight = 30.h;

  Paint borderPaint = Paint()
    ..color = Colors.transparent
    ..style = PaintingStyle.stroke
    ..strokeWidth = 2;

  int cellCount = 0;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  🔵 Drawing the Circular Cells
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (int row = 0; row &amp;lt; rows; row++) {
    for (int col = 0; col &amp;lt; columns; col++) {
      if (cellCount &amp;gt;= totalCells) break;

      // Optional: draw transparent border rectangle
      Rect cellRect = Rect.fromLTWH(
        col * cellWidth,
        row * cellHeight,
        cellWidth,
        cellHeight,
      );
      canvas.drawRect(cellRect, borderPaint);

      // Center point for the circle
      Offset center = Offset(
        col * cellWidth + cellWidth / 2,
        row * cellHeight + cellHeight / 2,
      );

      // Circle color based on the value
      Paint circlePaint = Paint()
        ..color = ColorPalleteMapper.getColor(
          gridData.context,
          gridData.data[cellCount].value,
        )
        ..style = PaintingStyle.fill;

      double radius = (cellWidth &amp;lt; cellHeight ? cellWidth : cellHeight) / 3;

      canvas.drawCircle(center, radius, circlePaint);
      cellCount++;
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This loop handles the drawing logic for every circular cell in the grid.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧾 Add a Legend for Clarity
&lt;/h3&gt;

&lt;p&gt;To help users understand what each color means, we add a dynamic legend widget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class LegendItem {
  final String name;
  final Color color;
  LegendItem({required this.name, required this.color});
}

class LegendWidget extends StatelessWidget {
  final GridContext gridContext;
  const LegendWidget({super.key, required this.gridContext});

  @override
  Widget build(BuildContext context) {
    final List&amp;lt;LegendItem&amp;gt; legends = LegendMapper.getLegendData(gridContext);
    return Wrap(
      spacing: 16.0,
      runSpacing: 8.0,
      children: legends.map((legend) {
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            CircleAvatar(radius: 5, backgroundColor: legend.color),
            SizedBox(width: 6),
            Text(
              legend.name,
              style: TextStyle(color: legend.color),
            ),
          ],
        );
      }).toList(),
    );
  }
}


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

&lt;/div&gt;



&lt;h3&gt;
  
  
  ✅ Wrapping Up
&lt;/h3&gt;

&lt;p&gt;And that's it! This is a powerful technique for anyone looking to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build custom UI components&lt;/li&gt;
&lt;li&gt;Create pixel-precise layouts&lt;/li&gt;
&lt;li&gt;Visualize data in creative ways&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you'd like to see a full working example, let me know in the comments! I’d be happy to publish a follow-up with demo integration or share the GitHub repo.&lt;br&gt;
Until next time, happy painting! 🖌️&lt;/p&gt;

&lt;p&gt;Follow me on dev.to for more Flutter tips and UI tricks.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
    </item>
    <item>
      <title>Comparative Analysis of Flutter and React Native for Application Development</title>
      <dc:creator>Ann Mary John</dc:creator>
      <pubDate>Mon, 07 Apr 2025 20:47:56 +0000</pubDate>
      <link>https://dev.to/annmaryjohn/comparative-analysis-of-flutter-and-react-native-for-application-development-4m96</link>
      <guid>https://dev.to/annmaryjohn/comparative-analysis-of-flutter-and-react-native-for-application-development-4m96</guid>
      <description>&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I have developed a sample app with both &lt;strong&gt;Flutter&lt;/strong&gt; and &lt;strong&gt;React Native&lt;/strong&gt; using three screens — Login, Home (with a chart), and Profile — to analyze both frameworks from a hands-on perspective. The focus was on performance, architecture, UI development, ecosystem, and developer experience to find the better fit for your project needs.&lt;/p&gt;




&lt;h3&gt;
  
  
  💻 &lt;strong&gt;Development Experience&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flutter&lt;/strong&gt; uses Dart and a widget-tree architecture. It had smoother setup and better UI control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native&lt;/strong&gt; uses JavaScript/TypeScript and a component-based structure. It had easier project structuring but faced setup and dependency challenges.&lt;/li&gt;
&lt;li&gt;Hot reload and live updates were supported by both, with &lt;strong&gt;React Native's Fast Refresh&lt;/strong&gt; standing out.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;: Flutter was better for UI development and setup; React Native made structuring simpler.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🚀 &lt;strong&gt;Performance&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flutter&lt;/strong&gt; uses the Skia engine and compiles to native code, offering better runtime performance and smaller app sizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native&lt;/strong&gt; relies on a JavaScript bridge, which adds latency and makes performance depend on third-party libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;: Flutter performed better, especially for graphics-intensive apps.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🎨 &lt;strong&gt;UI/UX Capabilities&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flutter&lt;/strong&gt; provides consistent UI across platforms using custom widgets, with strong built-in animation and UI tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native&lt;/strong&gt; uses native components, which gives a native look but relies heavily on third-party libraries for customization and animations.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;: Flutter is better for consistent cross-platform UIs with rich visuals and less external dependency.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  📱 &lt;strong&gt;Platform Support &amp;amp; Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flutter&lt;/strong&gt; supports iOS, Android, Web, and Desktop out-of-the-box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native&lt;/strong&gt; is primarily focused on mobile platforms but has a vast ecosystem for native integrations.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;: Flutter offers broader platform coverage; React Native is better supported in the mobile-native plugin ecosystem.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  🔧 &lt;strong&gt;Scalability &amp;amp; Maintainability&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flutter&lt;/strong&gt; has a more structured system, fewer dependencies, and easier maintenance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React Native&lt;/strong&gt; is flexible but requires careful version control and dependency management.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Verdict&lt;/strong&gt;: Flutter wins on maintainability, but React Native offers more integration flexibility.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ✅ &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Flutter excelled in UI consistency, built-in features, animation handling, and maintenance. Though asset configuration was manual, the experience was smoother overall.&lt;br&gt;&lt;br&gt;
React Native offered a simpler file structure and better native integration support but came with performance trade-offs and heavier dependency management.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
