Skip to main content

liquid_glass_ios_widgets 0.1.0 copy "liquid_glass_ios_widgets: ^0.1.0" to clipboard
liquid_glass_ios_widgets: ^0.1.0 copied to clipboard

Native iOS 26 Liquid Glass components (buttons, switch, slider, segmented control, glass container, tab bar) as Flutter widgets via platform views.

example/lib/main.dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:liquid_glass_ios_widgets/liquid_glass_ios_widgets.dart';

void main() => runApp(const ExampleApp());

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

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

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

  @override
  State<GalleryPage> createState() => _GalleryPageState();
}

class _GalleryPageState extends State<GalleryPage> {
  int _tab = 0;
  bool? _supported;

  @override
  void initState() {
    super.initState();
    LiquidGlass.isSupported().then((value) {
      if (mounted) setState(() => _supported = value);
    });
  }

  @override
  Widget build(BuildContext context) {
    final bottomInset = MediaQuery.paddingOf(context).bottom;
    return Scaffold(
      body: Stack(
        children: [
          const Positioned.fill(child: _ColorfulBackground()),
          Positioned.fill(
            child: IndexedStack(
              index: _tab,
              children: [
                _ControlsTab(supported: _supported),
                const _GlassTab(),
              ],
            ),
          ),
          Positioned(
            left: 0,
            right: 0,
            bottom: bottomInset,
            child: LiquidGlassTabBar(
              currentIndex: _tab,
              onTap: (index) => setState(() => _tab = index),
              items: const [
                LiquidGlassTabItem(
                  label: 'Controls',
                  systemImage: 'slider.horizontal.3',
                ),
                LiquidGlassTabItem(
                  label: 'Glass',
                  systemImage: 'drop',
                  selectedSystemImage: 'drop.fill',
                  badge: 'new',
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _ControlsTab extends StatefulWidget {
  const _ControlsTab({required this.supported});

  final bool? supported;

  @override
  State<_ControlsTab> createState() => _ControlsTabState();
}

class _ControlsTabState extends State<_ControlsTab> {
  bool _switch = true;
  double _slider = 0.4;
  int _segment = 0;
  int _taps = 0;

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.fromLTRB(
        20,
        MediaQuery.paddingOf(context).top + 16,
        20,
        140,
      ),
      children: [
        const Text(
          'Liquid Glass',
          style: TextStyle(
            fontSize: 34,
            fontWeight: FontWeight.bold,
            color: Colors.white,
          ),
        ),
        Text(switch (widget.supported) {
          null => 'Checking…',
          true => 'iOS 26 — real Liquid Glass',
          false => 'Liquid Glass unavailable, using fallbacks',
        }, style: const TextStyle(color: Colors.white70)),
        const SizedBox(height: 24),
        _Section(
          title: 'Buttons — tapped $_taps times',
          child: Wrap(
            spacing: 12,
            runSpacing: 12,
            crossAxisAlignment: WrapCrossAlignment.center,
            children: [
              LiquidGlassButton(
                label: 'Glass',
                onPressed: () => setState(() => _taps++),
              ),
              LiquidGlassButton(
                label: 'Prominent',
                style: LiquidGlassButtonStyle.prominent,
                onPressed: () => setState(() => _taps++),
              ),
              LiquidGlassButton(
                label: 'Share',
                systemImage: 'square.and.arrow.up',
                size: LiquidGlassControlSize.large,
                onPressed: () => setState(() => _taps++),
              ),
              LiquidGlassButton.icon(
                systemImage: 'heart.fill',
                foregroundColor: Colors.pink,
                onPressed: () => setState(() => _taps++),
              ),
              LiquidGlassButton.icon(
                systemImage: 'plus',
                style: LiquidGlassButtonStyle.prominent,
                tint: Colors.orange,
                onPressed: () => setState(() => _taps++),
              ),
              const LiquidGlassButton(label: 'Disabled', onPressed: null),
            ],
          ),
        ),
        _Section(
          title: 'Full width',
          child: LiquidGlassButton(
            label: 'Continue',
            style: LiquidGlassButtonStyle.prominent,
            tint: Colors.indigo,
            size: LiquidGlassControlSize.large,
            width: double.infinity,
            height: 52,
            onPressed: () => setState(() => _taps++),
          ),
        ),
        _Section(
          title: 'Switch — ${_switch ? 'on' : 'off'}',
          child: Row(
            children: [
              LiquidGlassSwitch(
                value: _switch,
                onChanged: (value) => setState(() => _switch = value),
              ),
              const SizedBox(width: 16),
              LiquidGlassSwitch(
                value: !_switch,
                activeColor: Colors.orange,
                onChanged: (value) => setState(() => _switch = !value),
              ),
            ],
          ),
        ),
        _Section(
          title: 'Slider — ${(_slider * 100).round()}%',
          child: LiquidGlassSlider(
            value: _slider,
            onChanged: (value) => setState(() => _slider = value),
          ),
        ),
        _Section(
          title: 'Segmented control — #$_segment',
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              LiquidGlassSegmentedControl(
                selectedIndex: _segment,
                onChanged: (index) => setState(() => _segment = index),
                segments: const [
                  LiquidGlassSegment(label: 'Day'),
                  LiquidGlassSegment(label: 'Week'),
                  LiquidGlassSegment(label: 'Month'),
                ],
              ),
              const SizedBox(height: 12),
              LiquidGlassSegmentedControl(
                expand: true,
                selectedIndex: _segment,
                onChanged: (index) => setState(() => _segment = index),
                segments: const [
                  LiquidGlassSegment(systemImage: 'list.bullet'),
                  LiquidGlassSegment(systemImage: 'square.grid.2x2'),
                  LiquidGlassSegment(systemImage: 'map'),
                ],
              ),
            ],
          ),
        ),
      ],
    );
  }
}

class _GlassTab extends StatelessWidget {
  const _GlassTab();

  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.fromLTRB(
        20,
        MediaQuery.paddingOf(context).top + 16,
        20,
        140,
      ),
      children: [
        LiquidGlassContainer(
          padding: const EdgeInsets.all(20),
          shape: const LiquidGlassShape.rect(cornerRadius: 28),
          child: const Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'Glass card',
                style: TextStyle(fontSize: 22, fontWeight: FontWeight.w600),
              ),
              SizedBox(height: 8),
              Text(
                'A native .glassEffect() surface with Flutter content on top. '
                'Scroll to see the background refract through it.',
              ),
            ],
          ),
        ),
        const SizedBox(height: 20),
        Row(
          children: [
            Expanded(
              child: LiquidGlassContainer(
                height: 120,
                tint: Colors.blue.withValues(alpha: 0.4),
                shape: const LiquidGlassShape.rect(cornerRadius: 24),
                onTap: () {},
                child: const Center(child: Text('Tinted + interactive')),
              ),
            ),
            const SizedBox(width: 16),
            Expanded(
              child: LiquidGlassContainer(
                height: 120,
                variant: LiquidGlassVariant.clear,
                shape: const LiquidGlassShape.rect(cornerRadius: 24),
                child: const Center(
                  child: Text(
                    'Clear variant',
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
            ),
          ],
        ),
        const SizedBox(height: 20),
        Center(
          child: LiquidGlassContainer(
            shape: const LiquidGlassShape.capsule(),
            padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14),
            child: const Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(CupertinoIcons.music_note_2),
                SizedBox(width: 8),
                Text('Now playing — capsule'),
              ],
            ),
          ),
        ),
        const SizedBox(height: 20),
        for (final color in Colors.primaries)
          Container(
            height: 72,
            margin: const EdgeInsets.only(bottom: 12),
            decoration: BoxDecoration(
              color: color,
              borderRadius: BorderRadius.circular(20),
            ),
          ),
      ],
    );
  }
}

class _Section extends StatelessWidget {
  const _Section({required this.title, required this.child});

  final String title;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 28),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            title,
            style: const TextStyle(
              color: Colors.white,
              fontWeight: FontWeight.w600,
            ),
          ),
          const SizedBox(height: 12),
          child,
        ],
      ),
    );
  }
}

class _ColorfulBackground extends StatelessWidget {
  const _ColorfulBackground();

  @override
  Widget build(BuildContext context) {
    return const DecoratedBox(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          colors: [Color(0xFF1E3C72), Color(0xFF8E2DE2), Color(0xFFFF6A00)],
        ),
      ),
    );
  }
}
2
likes
0
points
598
downloads

Publisher

unverified uploader

Weekly Downloads

Native iOS 26 Liquid Glass components (buttons, switch, slider, segmented control, glass container, tab bar) as Flutter widgets via platform views.

Repository (GitHub)
View/report issues

Topics

#ios #liquid-glass #widget #cupertino #platform-views

License

unknown (license)

Dependencies

collection, flutter

More

Packages that depend on liquid_glass_ios_widgets

Packages that implement liquid_glass_ios_widgets