How to Create A Simple Splash Screen UI design in flutter

Intro screen

simple UI screen with minimum configurations – How to Create A Simple Splash Screen UI design in flutter

  • dynamic pages length
  • configurable

Get Full Example:  here

<img decoding=
flutter splash screen

IntroDurations.dart

import 'package:extra_alignments/extra_alignments.dart';
import 'package:flutter/material.dart';
import 'package:flutter_animate/animate.dart';
import 'package:flutter_animate/effects/effects.dart';
import 'package:flutter_animate/num_duration_extensions.dart';
import 'package:gap/gap.dart';
import 'package:flutter_intro_screen/default_text_color.dart';
import 'package:flutter_intro_screen/indicator.dart';

class IntroDurations {
  final Duration fast;
  final Duration med;
  final Duration slow;
  final Duration pageTransition;

  const IntroDurations({
    this.fast = const Duration(milliseconds: 300),
    this.med = const Duration(milliseconds: 600),
    this.slow = const Duration(milliseconds: 900),
    this.pageTransition = const Duration(milliseconds: 200),
  });
}

class IntroMessages {
  final String swap;
  final String navigate;

  const IntroMessages({
    this.swap = "Swap left to continue",
    this.navigate = "Navigate",
  });
}

class IntroText {
  final TextStyle body;
  final TextStyle bodySmall;

  const IntroText({
    this.body = const TextStyle(),
    this.bodySmall = const TextStyle(),
  });
}

class IntroColors {
  final Color text;
  final Color button;
  final Color background;

  const IntroColors({
    this.background = Colors.black,
    this.text = Colors.white,
    this.button = Colors.white,
  });
}

class IntroInsets {
  final double xxs;
  final double xs;
  final double sm;
  final double md;
  final double lg;
  final double xl;
  final double xxl;

  const IntroInsets({
    this.xxs = 4,
    this.xs = 8,
    this.sm = 16,
    this.md = 24,
    this.lg = 32,
    this.xl = 48,
    this.xxl = 56,
  });
}

class FlutterIntroScreen extends StatefulWidget {
  final List<IntroPageData> pageData;
  final IntroMessages messages;
  final IntroText texts;
  final IntroInsets insets;
  final IntroDurations durations;
  final IntroColors colors;
  final VoidCallback onCompletePressed;

  final Widget appLogo;
  final Widget centerWidget;

  const FlutterIntroScreen({
    Key? key,
    required this.appLogo,
    required this.centerWidget,
    required this.pageData,
    required this.onCompletePressed,
    this.messages = const IntroMessages(),
    this.insets = const IntroInsets(),
    this.durations = const IntroDurations(),
    this.colors = const IntroColors(),
    this.texts = const IntroText(),
  }) : super(key: key);

  @override
  State<FlutterIntroScreen> createState() => _FlutterIntroScreenState();
}

class _FlutterIntroScreenState extends State<FlutterIntroScreen> {
  static const double _imageSize = 264;
  static const double _logoHeight = 126;
  static const double _textHeight = 155;
  static const double _pageIndicatorHeight = 55;

  late final PageController _pageController = PageController()
    ..addListener(_handlePageChanged);
  final ValueNotifier<int> _currentPage = ValueNotifier(0);

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  void _handlePageChanged() {
    int newPage = _pageController.page?.round() ?? 0;
    _currentPage.value = newPage;
  }

  void _handleSemanticSwipe(int dir) {
    _pageController.animateToPage((_pageController.page ?? 0).round() + dir,
        duration: widget.durations.fast, curve: Curves.easeOut);
  }

  @override
  Widget build(BuildContext context) {
    // This view uses a full screen PageView to enable swipe navigation.
    // However, we only want the title / description to actually swipe,
    // so we stack a PageView with that content over top of all the other
    // content, and line up their layouts.

    final List<Widget> pages =
        widget.pageData.map((e) => _Page(data: e)).toList();

    final Widget content = Stack(children: [
      // page view with title & description:
      MergeSemantics(
        child: Semantics(
          onIncrease: () => _handleSemanticSwipe(1),
          onDecrease: () => _handleSemanticSwipe(-1),
          child: PageView(
            physics: const BouncingScrollPhysics(),
            controller: _pageController,
            children: pages,
            onPageChanged: (_) {},
          ),
        ),
      ),

      IgnorePointer(
        ignoringSemantics: false,
        child: Column(children: [
          const Spacer(),

          // logo:
          Semantics(
            header: true,
            child: Container(
              height: _logoHeight,
              alignment: Alignment.center,
              child: widget.appLogo,
            ),
          ),

          // masked image:
          SizedBox(
            height: _imageSize,
            width: _imageSize,
            child: ValueListenableBuilder<int>(
              valueListenable: _currentPage,
              builder: (_, value, __) {
                return AnimatedSwitcher(
                  duration: widget.durations.slow,
                  child: KeyedSubtree(
                    key: ValueKey(
                        value), // so AnimatedSwitcher sees it as a different child.
                    child: IntroPageImage(data: widget.pageData[value]),
                  ),
                );
              },
            ),
          ),

          // placeholder gap for text:
          const Gap(_FlutterIntroScreenState._textHeight),

          // page indicator:
          Container(
            height: _pageIndicatorHeight,
            alignment: const Alignment(0.0, -0.75),
            child: AppPageIndicator(
              count: widget.pageData.length,
              controller: _pageController,
              color: widget.colors.background,
            ),
          ),

          const Spacer(flex: 2),
        ]),
      ),

      // finish button:
      Positioned(
        right: widget.insets.lg,
        bottom: widget.insets.lg,
        child: _buildFinishBtn(context),
      ),

      // nav help text:
      BottomCenter(
        child: Padding(
          padding: EdgeInsets.only(bottom: widget.insets.lg),
          child: _buildNavText(context),
        ),
      ),
    ]);

    return DefaultTextColor(
      color: widget.colors.text,
      child: Container(
        color: widget.colors.background,
        child: SafeArea(child: content.animate().fadeIn(delay: 500.ms)),
      ),
    );
  }

  Widget _buildFinishBtn(BuildContext context) {
    return ValueListenableBuilder<int>(
      valueListenable: _currentPage,
      builder: (_, pageIndex, __) {
        return AnimatedOpacity(
          opacity: pageIndex == widget.pageData.length - 1 ? 1 : 0,
          duration: widget.durations.fast,
          child: FloatingActionButton.small(
            elevation: 0,
            onPressed: widget.onCompletePressed,
            tooltip: widget.messages.swap,
            backgroundColor: widget.colors.button,
            child: const Icon(Icons.arrow_forward_ios_rounded),
          ),
        );
      },
    );
  }

  Widget _buildNavText(BuildContext context) {
    return ValueListenableBuilder(
      valueListenable: _currentPage,
      builder: (_, pageIndex, __) {
        return AnimatedOpacity(
          opacity: pageIndex == widget.pageData.length - 1 ? 0 : 1,
          duration: widget.durations.fast,
          child: Semantics(
            onTapHint: widget.messages.swap,
            onTap: () {
              final int current = _pageController.page!.round();
              _pageController.animateToPage(
                current + 1,
                duration: 250.ms,
                curve: Curves.easeIn,
              );
            },
            child: widget.centerWidget,
          ),
        );
      },
    );
  }
}

@immutable
class IntroPageData {
  const IntroPageData({
    required this.title,
    required this.description,
    required this.image,
    this.mask,
  });

  final Widget title;
  final Widget description;
  final Widget image;
  final Widget? mask;
}

class _Page extends StatelessWidget {
  const _Page({Key? key, required this.data}) : super(key: key);

  final IntroPageData data;

  @override
  Widget build(BuildContext context) {
    return Semantics(
      liveRegion: true,
      child: Column(
        children: [
          const Spacer(),
          const Gap(_FlutterIntroScreenState._imageSize +
              _FlutterIntroScreenState._logoHeight),
          SizedBox(
            height: _FlutterIntroScreenState._textHeight,
            width: _FlutterIntroScreenState._imageSize,
            child: IntroStaticTextScale(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  data.title,
                  const Gap(12),
                  data.description,
                ],
              ),
            ),
          ),
          const Gap(_FlutterIntroScreenState._pageIndicatorHeight),
          const Spacer(flex: 2),
        ],
      ),
    );
  }
}

class IntroPageImage extends StatelessWidget {
  const IntroPageImage({
    Key? key,
    required this.data,
  }) : super(key: key);

  final IntroPageData data;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        SizedBox.expand(
          child: data.image,
        ),
        if (data.mask != null)
          Positioned.fill(
            child: data.mask!,
          ),
      ],
    );
  }
}

class IntroStaticTextScale extends StatelessWidget {
  const IntroStaticTextScale({
    Key? key,
    required this.child,
    this.scale = 1,
  }) : super(key: key);
  final Widget child;
  final double scale;

  @override
  Widget build(BuildContext context) {
    return MediaQuery(
      data: MediaQuery.of(context).copyWith(textScaleFactor: scale),
      child: child,
    );
  }
}

Get Full Source Code


Do like & share my Facebook page. if you find this post helpful. Thank you!!

Related Articles:

How to Install Flutter in windows 10

How to Setup Space Between Elements In Flutter 

Flutter Card Widget with Example

Integrating an API into a Flutter – Working with REST APIs

Create a simple splash screen in Flutter

Android Projects with Source Code

Flutter Interview Questions

School Database Management System Project 

Create Login Page UI Design in flutter

Make Navigation Drawer in Flutter Source Code

READ MORE

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top