ফ্লাটারে লিকুইড গ্লাস (গ্লাসমরফিজম) ডিজাইন

অ্যাপল তাদের সব গুলো অপারেটিং সিস্টেমকে ইউনিফাইড ভার্সন নেইমের পাশাপাশি ইউনিফাইড ডিজাইনে নিয়ে এসেছে। সব গুলোতেই এখন একই ডিজাইন (লিকুইড গ্লাস) দেখা যাবে। এই ডিজাইনের অরিজিনাল নাম হচ্ছে গ্লাসমরফিজম। যেটা অনেক আগে থেকেই বিভিন্ন অপারেটিং সিস্টেম, অ্যাপে ব্যবহৃত হয়ে আসছে।

ফ্লাটারে ন্যাটিভলি কন্টেইনারে অপাসিটি সেট করে গ্লাসমরফিজম ইউআই তৈরি করতে পারি। তবে glassmorphism নামে ফ্লাটারের সুন্দর একটা প্যাকেজ রয়েছে। যা ব্যবহার করে আমরা সহজে লিকুইড গ্লাস ইউআই তৈরি করতে পারব। প্যাকেজের পেইজে সুন্দর কিছু উদাহরণ রয়েছে। যেমনঃ

import 'package:flutter/material.dart';
import 'package:glassmorphism/glassmorphism.dart';
import 'dart:ui';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GlassmorphicContainer Example',
      home: GlassmorphicSample(),
    );
  }
}

class GlassmorphicSample extends StatefulWidget {
  @override
  State<GlassmorphicSample> createState() => GlassmorphicSampleState();
}

class GlassmorphicSampleState extends State<GlassmorphicSample> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Container(
        height: double.infinity,
        width: double.infinity,
        child: Stack(
          children: [
            Image.network(
              "https://github.com/RitickSaha/glassmophism/blob/master/example/assets/bg.png?raw=true",
              fit: BoxFit.cover,
              height: double.infinity,
              width: double.infinity,
              scale: 1,
            ),
            SafeArea(
              child: Center(
                child: GlassmorphicContainer(
                    width: 350,
                    height: 750,
                    borderRadius: 20,
                    blur: 20,
                    alignment: Alignment.bottomCenter,
                    border: 2,
                    linearGradient: LinearGradient(
                        begin: Alignment.topLeft,
                        end: Alignment.bottomRight,
                        colors: [
                          Color(0xFFffffff).withOpacity(0.1),
                          Color(0xFFFFFFFF).withOpacity(0.05),
                        ],
                        stops: [
                          0.1,
                          1,
                        ]),
                    borderGradient: LinearGradient(
                      begin: Alignment.topLeft,
                      end: Alignment.bottomRight,
                      colors: [
                        Color(0xFFffffff).withOpacity(0.5),
                        Color((0xFFFFFFFF)).withOpacity(0.5),
                      ],
                    ),
                    child: null),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

যার আউটপুট পাবো এমনঃ

রিয়েল লাইফে গ্লাস যেমন কাজ করে, এখানেও তেমনি কাজ করবে। গ্লাসের পেছনে যেমন ব্যাকগ্রাউন্ড থাকবে, গ্লাসের ভেতর দিয়ে ঐ ব্যাকগ্রাউন্ড দেখা যাবে। আর এর জন্য ফ্লাটারে স্ট্যাক উইজেট ব্যবহার করতে হবে। গ্লাসের উপর আবার নতুন আইটেম যোগ করতে পারব। তা যোগ করতে পারব GlassmorphicContainer এর মধ্যে চাইল্ড যোগ করে। যেমন

GlassmorphicContainer(
                  width: 350,
                  height: 750,
                  borderRadius: 20,
                  blur: 20,
                  alignment: Alignment.bottomCenter,
                  border: 2,
                  linearGradient: LinearGradient(
                    begin: Alignment.topLeft,
                    end: Alignment.bottomRight,
                    colors: [
                      Color(0xFFffffff).withOpacity(0.1),
                      Color(0xFFFFFFFF).withOpacity(0.05),
                    ],
                    stops: [0.1, 1],
                  ),
                  borderGradient: LinearGradient(
                    begin: Alignment.topLeft,
                    end: Alignment.bottomRight,
                    colors: [
                      Color(0xFFffffff).withOpacity(0.5),
                      Color((0xFFFFFFFF)).withOpacity(0.5),
                    ],
                  ),
                  // You can place any child widget here, e.g., Text, Column, etc.
                  child: Center(
                    child: Text(
                      'Hello, World!',
                      style: TextStyle(
                        fontSize: 30,
                        fontWeight: FontWeight.bold,
                        color: Colors.white,
                        shadows: [
                          Shadow(
                            blurRadius: 10.0,
                            color: Colors.black54,
                            offset: Offset(2.0, 2.0),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),

এখানে গ্লাস কন্টেইনারের মধ্যে Hello, World লেখা দেখাবে।

এবার একটা অনবোর্ডিং স্ক্রিন তৈরি করতে পারি।

import 'package:flutter/material.dart';
import 'package:glassmorphism/glassmorphism.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';

void main() {
  runApp(const MeditationApp());
}

class MeditationApp extends StatelessWidget {
  const MeditationApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: OnboardingScreen(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class OnboardingScreen extends StatefulWidget {
  const OnboardingScreen({super.key});

  @override
  State&lt;OnboardingScreen> createState() => _OnboardingScreenState();
}

class _OnboardingScreenState extends State&lt;OnboardingScreen> {
  final PageController _controller = PageController();

  final List&lt;Map&lt;String, String>> onboardingTexts = [
    {
      'title': '30 days\nMeditation\nChallenge',
      'description':
          '100+ guided meditations covering anxiety, focus, stress, gratitude and more.',
    },
    {
      'title': 'Mindfulness\nMatters',
      'description':
          'Learn the art of being present and living fully in each moment.',
    },
    {
      'title': 'Relax.\nBreathe.\nReflect.',
      'description':
          'Daily calming practices to help you unwind and reset your mind.',
    },
  ];

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;

    return Scaffold(
      body: Stack(
        children: [
               Image.network(
              "https://github.com/RitickSaha/glassmophism/blob/master/example/assets/bg.png?raw=true",
              fit: BoxFit.cover,
              height: double.infinity,
              width: double.infinity,
              scale: 1,
            ),
          GlassmorphicContainer(
            width: size.width,
            height: size.height,
            borderRadius: 0,
            blur: 20,
            alignment: Alignment.center,
            border: 0,
            linearGradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
              colors: [
                Color(0xFFffffff).withValues(alpha: 0.2),
                Color(0xFFFFFFFF).withValues(alpha: 0.1),
              ],
              stops: [0.1, 1],
            ),
            borderGradient: LinearGradient(
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
              colors: [
                Colors.white24.withValues(alpha: 0.5),
                Colors.white24.withValues(alpha: 0.2),
              ],
            ),
          ),
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment:
                  CrossAxisAlignment.center, 

              children: [
                ClipOval(
                  child: Image.asset(
                    'assets/run.jpg',
                    width: 250,
                    height: 250,
                    fit: BoxFit.cover,
                  ),
                ),

                SizedBox(height: 40),

                Padding(
                  padding: const EdgeInsets.only(bottom: 40),
                  child: GlassmorphicContainer(
                    width: size.width * 0.9,
                    height: size.height * 0.35,
                    borderRadius: 30,
                    blur: 20,
                    alignment: Alignment.bottomCenter,
                    border: 2,
                    linearGradient: LinearGradient(
                      colors: [
                        Colors.white.withValues(alpha:  0.1),
                        Colors.white38.withValues(alpha:  0.1),
                      ],
                    ),
                    borderGradient: LinearGradient(
                      colors: [Colors.white24, Colors.white10],
                    ),
                    child: Padding(
                      padding: const EdgeInsets.all(24),
                      child: PageView.builder(
                        controller: _controller,
                        itemCount: onboardingTexts.length,
                        itemBuilder: (context, index) {
                          final item = onboardingTexts[index];
                          return Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                item['title']!,
                                style: const TextStyle(
                                  fontSize: 28,
                                  fontWeight: FontWeight.bold,
                                  color: Colors.white,
                                ),
                              ),
                              const SizedBox(height: 16),
                              Text(
                                item['description']!,
                                style: const TextStyle(
                                  fontSize: 14,
                                  color: Colors.white70,
                                ),
                              ),
                              const Spacer(),
                              Row(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceBetween,
                                children: [
                                  TextButton(
                                    onPressed: () {
                                      _controller.jumpToPage(
                                        onboardingTexts.length - 1,
                                      );
                                    },
                                    child: const Text(
                                      'Skip',
                                      style: TextStyle(color: Colors.white60),
                                    ),
                                  ),
                                  Row(
                                    children: [
                                      SmoothPageIndicator(
                                        controller: _controller,
                                        count: onboardingTexts.length,
                                        effect: const ExpandingDotsEffect(
                                          dotColor: Colors.white24,
                                          activeDotColor: Colors.white,
                                          dotHeight: 8,
                                          dotWidth: 8,
                                        ),
                                      ),
                                      const SizedBox(width: 16),
                                      ElevatedButton(
                                        onPressed: () {
                                          if (index &lt;
                                              onboardingTexts.length - 1) {
                                            _controller.nextPage(
                                              duration: const Duration(
                                                milliseconds: 300,
                                              ),
                                              curve: Curves.easeInOut,
                                            );
                                          } else {
                                            // Navigate or finish
                                          }
                                        },
                                        style: ElevatedButton.styleFrom(
                                          foregroundColor: Colors.black,
                                          backgroundColor: Colors.white,
                                          shape: RoundedRectangleBorder(
                                            borderRadius: BorderRadius.circular(
                                              20,
                                            ),
                                          ),
                                          padding: const EdgeInsets.symmetric(
                                            horizontal: 24,
                                            vertical: 12,
                                          ),
                                        ),
                                        child: Text(
                                          index &lt; onboardingTexts.length - 1
                                              ? 'Next'
                                              : 'Done',
                                        ),
                                      ),
                                    ],
                                  ),
                                ],
                              ),
                            ],
                          );
                        },
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

যার আউটপুট পাবো এমনঃ

Leave a Comment