<?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: Erick Murai</title>
    <description>The latest articles on DEV Community by Erick Murai (@raicodesokwe).</description>
    <link>https://dev.to/raicodesokwe</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%2F855288%2Ff1b46058-d735-4e72-bc29-dfb91107b5f0.jpeg</url>
      <title>DEV Community: Erick Murai</title>
      <link>https://dev.to/raicodesokwe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raicodesokwe"/>
    <language>en</language>
    <item>
      <title>Implementing Neumorphic design in flutter without a package</title>
      <dc:creator>Erick Murai</dc:creator>
      <pubDate>Sat, 30 Apr 2022 17:56:43 +0000</pubDate>
      <link>https://dev.to/raicodesokwe/implementing-neumorphic-design-in-flutter-without-a-package-2jbl</link>
      <guid>https://dev.to/raicodesokwe/implementing-neumorphic-design-in-flutter-without-a-package-2jbl</guid>
      <description>&lt;p&gt;In recent times, few concepts have rocked the UI/UX design world in a fashion similar to the neumorphic design craze. &lt;a href="https://dribbble.com/" rel="noopener noreferrer"&gt;Dribbble&lt;/a&gt; and &lt;a href="https://www.behance.net/" rel="noopener noreferrer"&gt;behance&lt;/a&gt; are littered with designs illustrating the use of this design pattern in web or mobile apps. It's a minimal design thus very appealing to the eye due to its softness and uniqueness in a design landscape where popping, shouting colors are all the rave.&lt;br&gt;
Luckily, we can implement these great designs in our flutter apps and make them stand out from the crowd(of apps*). I shall implement both a dark and light neumorphic design. For this demonstration, I shall use a simple fintech app UI sample I created. &lt;br&gt;
Here is the &lt;a href="https://github.com/Raicodesokwe/kudidemo" rel="noopener noreferrer"&gt;source code&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Firstly&lt;/strong&gt;,we shall begin with the light version. We shall implement a base theme widget that shall hold all global theme properties that shall apply throughout the app. We shall use a scaffold background color of Color.grey[300] to enable use apply neumorphic shadows that pop effectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ThemeData lightThemeData(BuildContext context) {
  return ThemeData.light().copyWith(
      scaffoldBackgroundColor: Colors.grey[300],
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we shall create a box decoration variable that we shall use throughout the app to create a light box-shadow that shall create the popping effect present in neumorphic designs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final BoxDecoration decorator = BoxDecoration(
      [
              BoxShadow(
                  color: Colors.grey.shade500,
                  offset: Offset(4, 4),
                  blurRadius: 15,
                  spreadRadius: 1),
              BoxShadow(
                spreadRadius: 1,
                color: Colors.white,
                offset: Offset(-4, -4),
                blurRadius: 15,
              )
            ]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to add the neumorphic shadow to any widget that we use for example, container, we'll just add the decorator variable to the decoration property.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Container(
              height: size.height * 0.07,
              width: size.width * 0.4,
              decoration: decorator.copyWith(
                  borderRadius: BorderRadius.circular(30.0),
                  color: Colors.greenAccent),)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In certain instances, we might want to add a depression effect in our neumorphic design language so as to create an illusion of a depression on the screen as illustrated in the image below. This can also be created with flutter &lt;a href="https://media.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%2Fal44vo665g6q6wy0v98v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fal44vo665g6q6wy0v98v.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
We shall create a decoration and box painter widget and add the colors we shall use to create the concave decoration effect&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class SecondDecoration extends Decoration {
  final ShapeBorder? shape;
  final double? depression;
  final List&amp;lt;Color&amp;gt;? colors;

  SecondDecoration({
    @required this.shape,
    @required this.depression,
    this.colors,
  })  : assert(shape != null),
        assert(depression! &amp;gt;= 0),
        assert(colors == null || colors.length == 2);

  @override
  BoxPainter createBoxPainter([void onChanged]) =&amp;gt;
      _SecondDecorationPainter(shape!, depression!, colors!);

  @override
  EdgeInsetsGeometry get padding =&amp;gt; shape!.dimensions;
}

class _SecondDecorationPainter extends BoxPainter {
  ShapeBorder shape;
  double depression;
  List&amp;lt;Color&amp;gt; colors;

  _SecondDecorationPainter(this.shape, this.depression, this.colors) {
    colors = [
      // Colors.black,
      // Colors.grey.shade800,
        Colors.black87,
       Colors.white
    ];
  }

  @override
  void paint(
      ui.Canvas canvas, ui.Offset offset, ImageConfiguration configuration) {
    final rect = offset &amp;amp; configuration.size!;
    final shapePath = shape.getOuterPath(rect);

    final delta = 16 / rect.longestSide;
    final stops = [0.5 - delta, 0.5 + delta];

    final path = Path()
      ..fillType = PathFillType.evenOdd
      ..addRect(rect.inflate(depression * 2))
      ..addPath(shapePath, Offset.zero);
    canvas.save();
    canvas.clipPath(shapePath);

    final paint = Paint()
      ..maskFilter = MaskFilter.blur(BlurStyle.normal, depression);
    final clipSize = rect.size.aspectRatio &amp;gt; 1
        ? Size(rect.width, rect.height / 2)
        : Size(rect.width / 2, rect.height);
    for (final alignment in [Alignment.topLeft, Alignment.bottomRight]) {
      final shaderRect =
          alignment.inscribe(Size.square(rect.longestSide), rect);
      paint.shader = ui.Gradient.linear(
          shaderRect.topLeft, shaderRect.bottomRight, colors, stops);

      canvas.save();
      canvas.clipRect(alignment.inscribe(clipSize, rect));
      canvas.drawPath(path, paint);
      canvas.restore();
    }
    canvas.restore();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We shall then pass this Decoration widget as an argument to the decoration property of a container widget.We shall then pass a pair of colors that shall give us a concave depression decoration effect in our container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Container(
                height: 60,
                decoration: SecondDecoration(
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(10)),
                        depression: 10,
                        colors: [
                            Color.fromRGBO(216, 213, 208, 1),
                            Colors.white
                          ]))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila. We can now create a light neumorphic shadow and depression effect in our flutter apps.&lt;br&gt;
Next up, we shall replicate the same in dark mode.&lt;br&gt;
&lt;strong&gt;Firstly&lt;/strong&gt;,we shall add a global dark theme with a dark scaffold color that shall enable us to create a dark neumorphic design.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ThemeData darkThemeData(BuildContext context) {
  return ThemeData.dark().copyWith(
      scaffoldBackgroundColor:Colors.grey[900],
      );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We shall then create a dark neumorphic shadow that shall create a popping effect. This shall be done by creating a decorator variable that shall hold the BoxDecoration object with the necessary box-shadow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final BoxDecoration decorator = BoxDecoration(
      [
              BoxShadow(
                  color: Colors.black,
                  offset: Offset(5, 5),
                  blurRadius: 15,
                  spreadRadius: 5),
              BoxShadow(
                spreadRadius: 1,
                color: Colors.grey.shade800,
                offset: Offset(-4, -4),
                blurRadius: 15,
              )
            ]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now use this variable within the container widget down the widget tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Container(
              height: size.height * 0.07,
              width: size.width * 0.4,
              decoration: decorator.copyWith(
                  borderRadius: BorderRadius.circular(30.0),
                  color: Colors.greenAccent),)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We shall then create a dark concave depression neumorphic effect with Decoration and box painter widgets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class ConcaveDecoration extends Decoration {
  final ShapeBorder? shape;
  final double? depression;
  final List&amp;lt;Color&amp;gt;? colors;

  ConcaveDecoration({
    @required this.shape,
    @required this.depression,
    this.colors,
  })  : assert(shape != null),
        assert(depression! &amp;gt;= 0),
        assert(colors == null || colors.length == 2);

  @override
  BoxPainter createBoxPainter([void onChanged]) =&amp;gt;
      _ConcaveDecorationPainter(shape!, depression!, colors!);

  @override
  EdgeInsetsGeometry get padding =&amp;gt; shape!.dimensions;
}

class _ConcaveDecorationPainter extends BoxPainter {
  ShapeBorder shape;
  double depression;
  List&amp;lt;Color&amp;gt; colors;

  _ConcaveDecorationPainter(this.shape, this.depression, this.colors) {
    colors = [
      Colors.black,
      Colors.grey.shade800,
      //   Colors.black87,
      //  Colors.white
    ];
  }

  @override
  void paint(
      ui.Canvas canvas, ui.Offset offset, ImageConfiguration configuration) {
    final rect = offset &amp;amp; configuration.size!;
    final shapePath = shape.getOuterPath(rect);

    final delta = 16 / rect.longestSide;
    final stops = [0.5 - delta, 0.5 + delta];

    final path = Path()
      ..fillType = PathFillType.evenOdd
      ..addRect(rect.inflate(depression * 2))
      ..addPath(shapePath, Offset.zero);
    canvas.save();
    canvas.clipPath(shapePath);

    final paint = Paint()
      ..maskFilter = MaskFilter.blur(BlurStyle.normal, depression);
    final clipSize = rect.size.aspectRatio &amp;gt; 1
        ? Size(rect.width, rect.height / 2)
        : Size(rect.width / 2, rect.height);
    for (final alignment in [Alignment.topLeft, Alignment.bottomRight]) {
      final shaderRect =
          alignment.inscribe(Size.square(rect.longestSide), rect);
      paint.shader = ui.Gradient.linear(
          shaderRect.topLeft, shaderRect.bottomRight, colors, stops);

      canvas.save();
      canvas.clipRect(alignment.inscribe(clipSize, rect));
      canvas.drawPath(path, paint);
      canvas.restore();
    }
    canvas.restore();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is how it appears &lt;a href="https://media.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%2F10d96fg2566bk2e8xf9x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F10d96fg2566bk2e8xf9x.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
We can now use this concave decoration effect in container widgets within our widget tree&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Container(
                height: 60,
                decoration:ConcaveDecoration(
                        colors: [Colors.black, Colors.grey.shade800],
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(10)),
                        depression: 10))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a great looking dark mode neumorphic design for our apps.&lt;br&gt;
Here is a &lt;a href="https://twitter.com/muraideveloper/status/1520449533083275265" rel="noopener noreferrer"&gt;video&lt;/a&gt; illustrating the feel and look of the sample app.&lt;br&gt;
In the app, I also implement functionality enabling toggling between light mode and dark mode. I offered an explanation on how to implement that functionality &lt;a href="https://dev.to/raicodesokwe/implementing-persistent-dark-mode-in-flutter-4854"&gt;here&lt;/a&gt;&lt;br&gt;
Thanks for reading until the end and stay tuned for more flutter tips in future.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Implementing biometric authentication in flutter</title>
      <dc:creator>Erick Murai</dc:creator>
      <pubDate>Fri, 29 Apr 2022 15:07:55 +0000</pubDate>
      <link>https://dev.to/raicodesokwe/implementing-biometric-authentication-in-flutter-4kl1</link>
      <guid>https://dev.to/raicodesokwe/implementing-biometric-authentication-in-flutter-4kl1</guid>
      <description>&lt;p&gt;With biometric authentication, we are able to verify users of our apps based on the biological characteristics of the users of our app. This can be done by checking if a user's fingerprint or face matches his/her fingerprint/face id in the phone. This method of authentication has gained popularity in the recent past especially with fintech apps that require a high level of security. They use it to verify that the user is indeed who they say they are. The uniqueness of our fingerprints and faces makes biometric authentication one of the most secure ways of verifying a user's identity.&lt;br&gt;
We shall create a simple project with three screens, a login screen, a signup screen and a homepage.&lt;br&gt;
The entire code for the project is available &lt;a href="https://github.com/Raicodesokwe/biometric"&gt;here&lt;/a&gt;&lt;br&gt;
We shall use &lt;a href="https://pub.dev/packages/firebase_auth"&gt;firebase&lt;/a&gt; for authentication and the &lt;a href="https://pub.dev/packages/lottie"&gt;Lottie package&lt;/a&gt; for some animations to spruce up our app. We shall then add these packages to our pubspec.yaml file at the root of our project folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  flutter:
    sdk: flutter
  firebase_auth:
  lottie:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now onto the main subject of discussion which is biometric authentication. For this, we shall need to use the &lt;a href="https://pub.dev/packages/flutter_secure_storage"&gt;flutter_secure_storage&lt;/a&gt; package that shall enable us store the login details which in our case shall be an email and password securely. This package uses the AES encryption standard that ensures the security of our data.&lt;br&gt;
Next up, the &lt;a href="https://pub.dev/packages/local_auth"&gt;local_auth&lt;/a&gt; package. We shall use this to access the local on-device authentication mechanisms for our users. On Android, this is the fingerprint biometric authentication method while on IOS, this is the touch code, Face ID or lock code authentication mechanism. We shall then add these to our pubspec.yaml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies:
  flutter:
    sdk: flutter
  local_auth:
  flutter_secure_storage:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that for the local_auth package to work in IOS, we need to add a user defaults permission allowing the use of Face ID in our app. This shall be added in our info.plist file which is located in &lt;code&gt;[project]/ios/Runner/info.plist&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;key&amp;gt;NSFaceIDUsageDescription&amp;lt;/key&amp;gt;
&amp;lt;string&amp;gt;Why is my app authenticating using face id?&amp;lt;/string&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, for the package to work in android, we need to add this piece of code to our MainActivity.java page which is located in &lt;code&gt;[project]/android/app/main/java/MainActivity.java&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import android.os.Bundle;
import io.flutter.app.FlutterFragmentActivity;
import io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin;
import io.flutter.plugins.localauth.LocalAuthPlugin;

public class MainActivity extends FlutterFragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FlutterAndroidLifecyclePlugin.registerWith(
                registrarFor(
                        "io.flutter.plugins.flutter_plugin_android_lifecycle.FlutterAndroidLifecyclePlugin"));
        LocalAuthPlugin.registerWith(registrarFor("io.flutter.plugins.localauth.LocalAuthPlugin"));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also have to add the USE_FINGERPRINT and USE_BIOMETRIC permissions in our AndroidManifest.xml file which is located in &lt;code&gt;[project]/android/app/src/main/AndroidManifest.xml&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app"&amp;gt;
  &amp;lt;uses-permission android:name="android.permission.USE_FINGERPRINT"/&amp;gt;
 &amp;lt;uses-permission android:name="android.permission.USE_BIOMETRIC"/&amp;gt;
&amp;lt;manifest&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, we should set the minSdkVersion in&lt;code&gt;[project]/android/app/build.gradle&lt;/code&gt; to  &amp;gt;= 18 so as to enable flutter_secure_storage to work&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;android {
    ...

    defaultConfig {
        ...
        minSdkVersion 18
        ...
    }

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Firstly&lt;/strong&gt;, we shall create a new user in our app with firebase auth in our signup screen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class AuthService{
 signUp(String email, String password, context) async {
    try {
      await FirebaseAuth.instance
          .createUserWithEmailAndPassword(email: email, password: password);
    } on FirebaseAuthException catch (e) {
      ScaffoldMessenger.of(context)
          .showSnackBar(SnackBar(content: Text(e.message.toString())));
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Next&lt;/strong&gt;, we shall create our login page where the bulk of our biometric authentication logic shall be contained. We shall create  localauth and storage variables that we shall use throughout the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final LocalAuthentication localAuth = LocalAuthentication();
final storage = const FlutterSecureStorage();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We should now go ahead and check if the device supports biometric authentication or not.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final canCheck = await localAuth.canCheckBiometrics;
final deviceIsSupported = await localAuth.isDeviceSupported();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Afterwards, we shall get the available biometrics on the device.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;BiometricType&amp;gt; availableBiometrics =
    await auth.getAvailableBiometrics();

if (Platform.isIOS) {
    if (availableBiometrics.contains(BiometricType.face)) {
        // Face ID.
    } else if (availableBiometrics.contains(BiometricType.fingerprint)) {
        // Touch ID.
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We shall use a boolean flag &lt;code&gt;bool _useTouchId = false;&lt;/code&gt; that shall check whether the user has checked to use biometric authentication upon first login and if so, we shall write the values of the user's email and password to flutter_secure_storage for storage and later retrieval if we use biometric authentication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  final authenticated = await localAuth.authenticate(
                localizedReason: 'Enable Face ID to sign in more easily',
                useErrorDialogs: true,
                stickyAuth: true);

            if (authenticated) {
              storage.write(key: 'email', value: email);
              storage.write(key: 'password', value: password);
              storage.write(key: 'usingBiometric', value: 'true');
            }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In subsequent logins, if we intend to use biometric authentication, we shall go ahead and read the email and password values from flutter_secure_storage for authentication.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; final authenticated = await localAuth.authenticate(
                localizedReason: 'Enable Face ID to sign in more easily');

            if (authenticated) {
              String? userStoredEmail = await storage.read(
                key: 'email',
              );
              String? userStoredPassword = await storage.read(
                key: 'password',
              );
              AuthService()
                  .signIn(userStoredEmail!, userStoredPassword!, context);
            }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it !!! All that's remaining is for us to create a simple homescreen with a logout button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';

import 'loginpage.dart';

class HomePage extends StatelessWidget {
   HomePage({Key? key}) : super(key: key);
final _auth=FirebaseAuth.instance;
Color greenColor = const Color(0xFF00AF19);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body:  Center(
        child: Text('Home screen',style: TextStyle(color: greenColor,fontWeight: FontWeight.w700,fontSize: 35),),
      ),
      floatingActionButton: FloatingActionButton(
        backgroundColor: greenColor,
        onPressed: ()async {
          await _auth.signOut();
          Navigator.pushReplacement(
          context, MaterialPageRoute(builder: (context) =&amp;gt; LoginPage()));
        },
        child:const  Icon(Icons.logout,),
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voila!!! Our app has a reliable and safe biometric authentication system.&lt;br&gt;
Here is the project's &lt;a href="https://github.com/Raicodesokwe/biometric"&gt;source code&lt;/a&gt; and here is a &lt;a href="https://twitter.com/muraideveloper/status/1484086852617396224"&gt;video demo&lt;/a&gt; of the end result&lt;br&gt;
Thanks for reading until the end (&lt;em&gt;long read, I know&lt;/em&gt;)*. Stay tuned for more flutter tips in future&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Implementing persistent dark mode in flutter</title>
      <dc:creator>Erick Murai</dc:creator>
      <pubDate>Fri, 29 Apr 2022 09:40:18 +0000</pubDate>
      <link>https://dev.to/raicodesokwe/implementing-persistent-dark-mode-in-flutter-4854</link>
      <guid>https://dev.to/raicodesokwe/implementing-persistent-dark-mode-in-flutter-4854</guid>
      <description>&lt;p&gt;A modern staple of present day UI/UX design is the implementation of functionality that enables switching between dark mode and light mode within apps. Luckily for us flutter developers, we can implement this too in DART. In our app, we shall use the toggle button and not rely on the phone's theme. We also want to persist our theme thus we shall use the &lt;a href="https://pub.dev/packages/provider"&gt;provider package&lt;/a&gt; for app-wide theming and &lt;a href="https://pub.dev/packages/shared_preferences/install"&gt;shared preferences&lt;/a&gt; to persist our theme.&lt;br&gt;
The source code for the project can be found &lt;a href="https://github.com/Raicodesokwe/flutterdarkmode.git"&gt;here&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Firstly&lt;/strong&gt;, we shall create a simple UI to demonstrate this. I've gone for a fintech sample app frontend for the purposes of demonstration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:darkmode/home/homepage.dart';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';


void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Flutter Demo',
            home: HomePage(),
          );

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Secondly&lt;/strong&gt;, we shall create a class in which we can define light theme and dark theme using ThemeData that enables us define the visual theme. We shall also pass various properties within the ThemeData such as iconTheme, appBarTheme and textTheme.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
ThemeData lightThemeData(BuildContext context) {
  return ThemeData.light().copyWith(
      visualDensity: VisualDensity.adaptivePlatformDensity,
      scaffoldBackgroundColor: Colors.white,
      appBarTheme: appBarTheme,
      iconTheme:const IconThemeData(color: Colors.black),

     textTheme: Theme.of(context).textTheme.apply(bodyColor: Colors.black));
}

ThemeData darkThemeData(BuildContext context) {
  return ThemeData.dark().copyWith(
      visualDensity: VisualDensity.adaptivePlatformDensity,
      scaffoldBackgroundColor:const Color(0xFF1D1D35),
      appBarTheme: appBarTheme,
      iconTheme:const IconThemeData(color: Colors.white),

      textTheme: Theme.of(context).textTheme.apply(bodyColor: Colors.white));
}

const appBarTheme = AppBarTheme(centerTitle: false, elevation: 0);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Thirdly&lt;/strong&gt;, we shall add the &lt;a href="https://pub.dev/packages/provider/install"&gt;Provider package&lt;/a&gt;  and  &lt;a href="https://pub.dev/packages/shared_preferences/install"&gt;shared preferences package&lt;/a&gt; .We shall use the provider package to enable the switching of the app-wide theme and the shared preferences package to store the persisted theme details thus when we exit the app and open it up again, the theme shall persist.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:shared_preferences/shared_preferences.dart';


class ThemeProvider extends ChangeNotifier {
 final String key = "theme";
 late SharedPreferences _prefs;
 late bool _darkTheme;

  bool get  darkTheme =&amp;gt; _darkTheme;

  ThemeProvider() {
    _darkTheme = true;
    _loadFromPrefs();
  }

  toggleTheme() {
    _darkTheme = !_darkTheme;
    _saveToPrefs();
    notifyListeners();
  }

  _initPrefs() async {
    // if(_prefs == null)
      _prefs = await SharedPreferences.getInstance();
  }

  _loadFromPrefs() async {
    await _initPrefs();
    _darkTheme = _prefs.getBool(key) ?? true;
    notifyListeners();
  }

  _saveToPrefs()async {
    await _initPrefs();
    _prefs.setBool(key, _darkTheme);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this done we shall go back to the Materialapp in main.dart and wrap the MaterialApp widget with a ChangeNotifierProvider widget that listens to the ChangeNotifier widget in its descendants and rebuilds dependents whenever ChangeNotifier.notifyListeners is called. We also wrap the MaterialApp widget with the Consumer widget that calls provider.of for us and listens to changes in our theme thus rebuilds it whenever necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:darkmode/home/homepage.dart';
import 'package:darkmode/provider/theme_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
        create: (_) =&amp;gt; ThemeProvider(),
        child: Consumer&amp;lt;ThemeProvider&amp;gt;(
            builder: (context, ThemeProvider notifier, child) {
          return MaterialApp(
            title: 'Flutter Demo',
            theme: notifier.darkTheme
                ? darkThemeData(context)
                : lightThemeData(context),
            debugShowCheckedModeBanner: false,
            home: HomePage(),
          );
        }));
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We shall now create a switch button that can toggle between light and dark mode. We shall listen to changes in the ThemeProvider by wrapping our Switch button with the consumer widget.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import 'package:darkmode/provider/theme_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';


class ChangeThemeButtonWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer&amp;lt;ThemeProvider&amp;gt;(
      builder: (context, notifier, child) =&amp;gt; Switch.adaptive(
        value: notifier.darkTheme,
        onChanged: (val) {
          notifier.toggleTheme();
          //bool value of switch which is true or false
        },
        activeTrackColor: Colors.green[100],
        inactiveTrackColor: Colors.green[300],
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created a fintech frontend as an easy way to demonstrate the switch between dark mode and light mode whose source code can be found  &lt;a href="https://github.com/Raicodesokwe/flutterdarkmode.git"&gt;here&lt;/a&gt; &lt;br&gt;
Here is the result:&lt;br&gt;
 &lt;a href="https://twitter.com/muraideveloper/status/1481697750878236680"&gt;Theme Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for the read up and stay tuned for more articles on flutter development.&lt;/p&gt;

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