flipbook_pro 1.0.2 copy "flipbook_pro: ^1.0.2" to clipboard
flipbook_pro: ^1.0.2 copied to clipboard

A Flutter package that provides beautiful Flipboard-style vertical page flip animations with smooth 3D perspective transformations and spring physics.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flipboard Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.red),
        useMaterial3: true,
      ),
      home: const FlipboardDemo(),
    );
  }
}

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

  @override
  State<FlipboardDemo> createState() => _FlipboardDemoState();
}

class _FlipboardDemoState extends State<FlipboardDemo>
    with SingleTickerProviderStateMixin {
  bool _showSplash = true;
  late AnimationController _bounceController;
  late Animation<double> _bounceAnimation;

  @override
  void initState() {
    super.initState();

    // Bounce animasyonu
    _bounceController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 800),
    );

    _bounceAnimation = Tween<double>(begin: -15, end: 15).animate(
      CurvedAnimation(
        parent: _bounceController,
        curve: Curves.easeInOut,
      ),
    );

    // Sürekli yukarı-aşağı
    _bounceController.repeat(reverse: true);

    // 3 saniye sonra splash'ı kapat
    Future.delayed(const Duration(seconds: 3), () {
      if (mounted) {
        setState(() {
          _showSplash = false;
        });
        _bounceController.stop();
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        children: [
          // Ana içerik
          FlipboardView(
            itemCount: 3,
            initialPage: 0,
            itemBuilder: (context, index) {
              if (index == 0) {
                return const Page1FullImage();
              } else if (index == 1) {
                return const Page2NewsCards();
              } else {
                return const Page3BusinessArticle();
              }
            },
            loop: true,
            perspective: 0.001,
          ),
          // Splash overlay
          if (_showSplash)
            AnimatedOpacity(
              opacity: _showSplash ? 1.0 : 0.0,
              duration: const Duration(milliseconds: 300),
              child: Container(
                color: Colors.black.withValues(alpha: 0.9),
                child: Center(
                  child: AnimatedBuilder(
                    animation: _bounceAnimation,
                    builder: (context, child) {
                      return Transform.translate(
                        offset: Offset(0, _bounceAnimation.value),
                        child: child,
                      );
                    },
                    child: Image.asset(
                      'assets/images/scrolling.png',
                      width: 80,
                      height: 80,
                      color: Colors.white,
                    ),
                  ),
                ),
              ),
            ),
        ],
      ),
    );
  }
}

// ============ SAYFA 1: Tam Sayfa Manzara Resmi ============
class Page1FullImage extends StatelessWidget {
  const Page1FullImage({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
      child: Column(
        children: [
          // Header
          const FlipboardHeader(),
          // Tam sayfa resim
          Expanded(
            child: Stack(
              fit: StackFit.expand,
              children: [
                Image.asset('assets/images/image.jpg', fit: BoxFit.cover),
                // Alt gradient
                Positioned(
                  bottom: 0,
                  left: 0,
                  right: 0,
                  height: 120,
                  child: Container(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [
                          Colors.transparent,
                          Colors.black.withValues(alpha: 0.9),
                        ],
                      ),
                    ),
                  ),
                ),
                // Watermark (sağ alt)
                Positioned(
                  bottom: 16,
                  right: 16,
                  child: Text(
                    '© Peter König',
                    style: TextStyle(
                      color: Colors.white.withValues(alpha: 0.6),
                      fontSize: 12,
                      fontStyle: FontStyle.italic,
                    ),
                  ),
                ),
                // Alt bilgi
                Positioned(
                  bottom: 12,
                  left: 16,
                  right: 80,
                  child: Text(
                    'Tübingen at blue hour  ·  500px.com  ·  500px.com',
                    style: TextStyle(
                      color: Colors.white.withValues(alpha: 0.85),
                      fontSize: 14,
                    ),
                  ),
                ),
              ],
            ),
          ),
          // Author satırı
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
            child: Row(
              children: [
                // Profil resmi
                Container(
                  width: 40,
                  height: 40,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    border: Border.all(color: Colors.grey[700]!, width: 1),
                  ),
                  child: ClipOval(
                    child: Icon(
                      Icons.person,
                      color: Colors.grey[500],
                      size: 24,
                    ),
                  ),
                ),
                const SizedBox(width: 12),
                const Text(
                  'Peter König',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 15,
                    fontWeight: FontWeight.w500,
                  ),
                ),
                const Spacer(),
                Icon(Icons.more_vert, color: Colors.grey[600], size: 24),
              ],
            ),
          ),
          // Action bar
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
            child: Row(
              children: [
                Icon(Icons.favorite_border, color: Colors.grey[500], size: 26),
                const SizedBox(width: 6),
                Text(
                  '1',
                  style: TextStyle(color: Colors.grey[500], fontSize: 14),
                ),
                const SizedBox(width: 24),
                Icon(
                  Icons.chat_bubble_outline,
                  color: Colors.grey[500],
                  size: 24,
                ),
                const SizedBox(width: 24),
                Icon(Icons.add, color: Colors.grey[500], size: 26),
                const Spacer(),
                Icon(Icons.share_outlined, color: Colors.grey[500], size: 24),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

// ============ SAYFA 2: Haber Kartları ============
class Page2NewsCards extends StatefulWidget {
  const Page2NewsCards({super.key});

  @override
  State<Page2NewsCards> createState() => _Page2NewsCardsState();
}

class _Page2NewsCardsState extends State<Page2NewsCards> {
  // Like durumları
  final Map<int, bool> _likedNews = {};
  final Map<int, int> _likeCounts = {0: 12, 1: 5};

  void _toggleLike(int index) {
    setState(() {
      _likedNews[index] = !(_likedNews[index] ?? false);
      if (_likedNews[index]!) {
        _likeCounts[index] = (_likeCounts[index] ?? 0) + 1;
      } else {
        _likeCounts[index] = (_likeCounts[index] ?? 1) - 1;
      }
    });
  }

  void _openNews(
    BuildContext context,
    String title,
    String source,
    String description,
    String imagePath,
  ) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => NewsDetailPage(
          title: title,
          source: source,
          description: description,
          imagePath: imagePath,
        ),
      ),
    );
  }

  void _showSnackBar(BuildContext context, String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        duration: const Duration(seconds: 1),
        backgroundColor: Colors.grey[800],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
      child: Column(
        children: [
          const FlipboardHeader(),
          Expanded(
            child: ListView(
              physics: const NeverScrollableScrollPhysics(),
              padding: EdgeInsets.zero,
              children: [
                // Haber 1
                _buildNewsCard(
                  index: 0,
                  title:
                      "İmamoğlu: 'Kreş bağışları rüşvet sayıldı, bu yalanlar yüzünden tutsağız'",
                  source: 'cumhuriyet.com.tr',
                  time: '3s',
                  description:
                      'Ekrem İmamoğlu, hakkında yürütülen soruşturmaya ilişkin açıklamalarda bulundu. İmamoğlu, Cumhurbaşkanlığı Aday Ofisi\'nin sosyal medya hesabından paylaşılan mesajında şu ifadeleri ...',
                  imagePath: 'assets/images/thumb1.webp',
                  publisher: 'Cumhuriyet',
                  publisherColor: Colors.red,
                  flipTo: 'Cumhuriyet Türkiye',
                ),
                Container(height: 0.5, color: Colors.grey[800]),
                // Haber 2
                _buildNewsCard(
                  index: 1,
                  title:
                      "Cumhurbaşkanlığı Başdanışmanlığı'na yeni isim: Üst düzey atamalar Resmî Gazete'de",
                  source: 'Halktv.com.tr',
                  time: '2s',
                  subtitle: 'Hab...',
                  description:
                      'Resmi Gazete\'de yayımlanan Cumhurbaşkanlığı atama kararlarıyla, kamu yönetiminde geniş kapsamlı bir görev ...',
                  imagePath: 'assets/images/thumb2.webp',
                  publisher: 'Halktv.com.tr',
                  publisherColor: Colors.red,
                  flipTo: 'Halk Tv Haber Portalı',
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildNewsCard({
    required int index,
    required String title,
    required String source,
    required String time,
    String? subtitle,
    required String description,
    required String imagePath,
    required String publisher,
    required Color publisherColor,
    required String flipTo,
  }) {
    final isLiked = _likedNews[index] ?? false;
    final likeCount = _likeCounts[index] ?? 0;

    return Material(
      color: Colors.transparent,
      child: InkWell(
        onTap: () => _openNews(context, title, source, description, imagePath),
        splashColor: Colors.white.withValues(alpha: 0.1),
        highlightColor: Colors.white.withValues(alpha: 0.05),
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // Başlık
              Text(
                title,
                style: const TextStyle(
                  color: Colors.white,
                  fontSize: 22,
                  fontWeight: FontWeight.bold,
                  height: 1.25,
                ),
              ),
              const SizedBox(height: 12),
              // İçerik + resim
              Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          '$source  ·  $time  ·  ${subtitle ?? '...'}',
                          style: TextStyle(
                            color: Colors.grey[500],
                            fontSize: 12,
                          ),
                        ),
                        const SizedBox(height: 8),
                        Text(
                          description,
                          style: TextStyle(
                            color: Colors.grey[400],
                            fontSize: 14,
                            height: 1.5,
                          ),
                          maxLines: 4,
                          overflow: TextOverflow.ellipsis,
                        ),
                      ],
                    ),
                  ),
                  const SizedBox(width: 12),
                  ClipRRect(
                    borderRadius: BorderRadius.circular(8),
                    child: Image.asset(
                      imagePath,
                      width: 110,
                      height: 85,
                      fit: BoxFit.cover,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 16),
              // Publisher
              Row(
                children: [
                  // Publisher avatar
                  GestureDetector(
                    onTap: () =>
                        _showSnackBar(context, '$publisher takip edildi'),
                    child: Stack(
                      children: [
                        CircleAvatar(
                          radius: 18,
                          backgroundColor: publisherColor,
                          child: Text(
                            publisher.substring(0, 1),
                            style: const TextStyle(
                              color: Colors.white,
                              fontWeight: FontWeight.bold,
                              fontSize: 14,
                            ),
                          ),
                        ),
                        Positioned(
                          bottom: 0,
                          right: 0,
                          child: Container(
                            width: 16,
                            height: 16,
                            decoration: BoxDecoration(
                              color: Colors.red,
                              shape: BoxShape.circle,
                              border: Border.all(color: Colors.black, width: 2),
                            ),
                            child: const Icon(
                              Icons.add,
                              color: Colors.white,
                              size: 10,
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  const SizedBox(width: 10),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          publisher,
                          style: const TextStyle(
                            color: Colors.white,
                            fontSize: 14,
                          ),
                        ),
                        Text(
                          'şuraya flipledi: $flipTo',
                          style: TextStyle(
                            color: Colors.grey[600],
                            fontSize: 12,
                          ),
                        ),
                      ],
                    ),
                  ),
                  GestureDetector(
                    onTap: () => _showSnackBar(context, 'Daha fazla seçenek'),
                    child: Icon(
                      Icons.more_vert,
                      color: Colors.grey[700],
                      size: 22,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 12),
              // Action bar
              Row(
                children: [
                  GestureDetector(
                    onTap: () => _toggleLike(index),
                    child: Row(
                      children: [
                        Icon(
                          isLiked ? Icons.favorite : Icons.favorite_border,
                          color: isLiked ? Colors.red : Colors.grey[600],
                          size: 24,
                        ),
                        if (likeCount > 0) ...[
                          const SizedBox(width: 4),
                          Text(
                            '$likeCount',
                            style: TextStyle(
                              color: isLiked ? Colors.red : Colors.grey[600],
                              fontSize: 14,
                            ),
                          ),
                        ],
                      ],
                    ),
                  ),
                  const SizedBox(width: 24),
                  GestureDetector(
                    onTap: () => _showSnackBar(context, 'Yorumlar'),
                    child: Icon(
                      Icons.chat_bubble_outline,
                      color: Colors.grey[600],
                      size: 22,
                    ),
                  ),
                  const SizedBox(width: 24),
                  GestureDetector(
                    onTap: () => _showSnackBar(context, 'Koleksiyona eklendi'),
                    child: Icon(Icons.add, color: Colors.grey[600], size: 26),
                  ),
                  const Spacer(),
                  GestureDetector(
                    onTap: () => _showSnackBar(context, 'Paylaş'),
                    child: Icon(
                      Icons.share_outlined,
                      color: Colors.grey[600],
                      size: 22,
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// ============ SAYFA 3: Business Article ============
class Page3BusinessArticle extends StatelessWidget {
  const Page3BusinessArticle({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black,
      child: Column(
        children: [
          const FlipboardHeader(),
          Expanded(
            child: SingleChildScrollView(
              physics: const NeverScrollableScrollPhysics(),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Hero resim
                  Stack(
                    children: [
                      Image.asset(
                        'assets/images/newsimage.jpg',
                        width: double.infinity,
                        height: 300,
                        fit: BoxFit.cover,
                      ),
                      // Category tag
                      Positioned(
                        bottom: 16,
                        left: 16,
                        child: Container(
                          padding: const EdgeInsets.symmetric(
                            horizontal: 12,
                            vertical: 6,
                          ),
                          decoration: BoxDecoration(
                            color: Colors.red,
                            borderRadius: BorderRadius.circular(4),
                          ),
                          child: const Text(
                            '# BUSİNESS',
                            style: TextStyle(
                              color: Colors.white,
                              fontSize: 11,
                              fontWeight: FontWeight.bold,
                              letterSpacing: 0.5,
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                  // İçerik
                  Padding(
                    padding: const EdgeInsets.all(16),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        // Subscription badge
                        Container(
                          padding: const EdgeInsets.symmetric(
                            horizontal: 10,
                            vertical: 6,
                          ),
                          decoration: BoxDecoration(
                            color: Colors.grey[900],
                            borderRadius: BorderRadius.circular(4),
                          ),
                          child: Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              Icon(
                                Icons.lock_outline,
                                color: Colors.grey[500],
                                size: 14,
                              ),
                              const SizedBox(width: 6),
                              Text(
                                'Abonelik gerekli olabilir',
                                style: TextStyle(
                                  color: Colors.grey[500],
                                  fontSize: 12,
                                ),
                              ),
                            ],
                          ),
                        ),
                        const SizedBox(height: 16),
                        // Başlık
                        const Text(
                          '4 AI Tools to Help You Start a Profitable Solo Business in 2026',
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 26,
                            fontWeight: FontWeight.bold,
                            height: 1.2,
                          ),
                        ),
                        const SizedBox(height: 14),
                        // Source
                        Row(
                          children: [
                            Icon(
                              Icons.bolt,
                              color: Colors.amber[600],
                              size: 16,
                            ),
                            const SizedBox(width: 4),
                            Text(
                              'entrepreneur.com  ·  1s  ·  Ben Angel',
                              style: TextStyle(
                                color: Colors.grey[500],
                                fontSize: 13,
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 16),
                        // Description
                        Text(
                          "Most AI advice optimizes tasks. This setup replaces leverage. In this video, I break down the four AI tools I use to run a profitable solo business in 2026 — without hiring, without coding and without duct-taping random workflows together. These are not hacks. They're systems you can actually run. Instead of chasing productivity, this stack is built around one idea: Let AI handle the coordination, so you focus on decisions that move revenue. What you'll get: Market ...",
                          style: TextStyle(
                            color: Colors.grey[400],
                            fontSize: 15,
                            height: 1.6,
                          ),
                        ),
                        const SizedBox(height: 20),
                        // Publisher
                        Row(
                          children: [
                            Stack(
                              children: [
                                CircleAvatar(
                                  radius: 20,
                                  backgroundColor: Colors.grey[850],
                                  child: const Text(
                                    'E',
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontWeight: FontWeight.bold,
                                      fontSize: 18,
                                    ),
                                  ),
                                ),
                                Positioned(
                                  bottom: 0,
                                  right: 0,
                                  child: Container(
                                    width: 16,
                                    height: 16,
                                    decoration: BoxDecoration(
                                      color: Colors.red,
                                      shape: BoxShape.circle,
                                      border: Border.all(
                                        color: Colors.black,
                                        width: 2,
                                      ),
                                    ),
                                    child: const Icon(
                                      Icons.add,
                                      color: Colors.white,
                                      size: 10,
                                    ),
                                  ),
                                ),
                              ],
                            ),
                            const SizedBox(width: 12),
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  const Text(
                                    'Entrepreneur',
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 15,
                                    ),
                                  ),
                                  Text(
                                    'şuraya flipledi: Science & Technology',
                                    style: TextStyle(
                                      color: Colors.grey[600],
                                      fontSize: 12,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                            Icon(
                              Icons.more_vert,
                              color: Colors.grey[700],
                              size: 22,
                            ),
                          ],
                        ),
                        const SizedBox(height: 16),
                        // Action bar
                        Row(
                          children: [
                            Icon(
                              Icons.favorite_border,
                              color: Colors.grey[600],
                              size: 24,
                            ),
                            const SizedBox(width: 6),
                            Text(
                              '1',
                              style: TextStyle(
                                color: Colors.grey[600],
                                fontSize: 14,
                              ),
                            ),
                            const SizedBox(width: 24),
                            Icon(
                              Icons.chat_bubble_outline,
                              color: Colors.grey[600],
                              size: 22,
                            ),
                            const SizedBox(width: 24),
                            Icon(Icons.add, color: Colors.grey[600], size: 26),
                            const SizedBox(width: 6),
                            Text(
                              '5',
                              style: TextStyle(
                                color: Colors.grey[600],
                                fontSize: 14,
                              ),
                            ),
                            const Spacer(),
                            Icon(
                              Icons.share_outlined,
                              color: Colors.grey[600],
                              size: 22,
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// ============ ORTAK BİLEŞENLER ============
class FlipboardHeader extends StatelessWidget {
  const FlipboardHeader({super.key});

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      bottom: false,
      child: Container(
        height: 50,
        padding: const EdgeInsets.symmetric(horizontal: 16),
        child: Row(
          children: [
            const Icon(Icons.arrow_back, color: Colors.white, size: 24),
            const Spacer(),
            const Text(
              'SANA ÖZEL',
              style: TextStyle(
                color: Colors.white,
                fontSize: 15,
                fontWeight: FontWeight.bold,
                letterSpacing: 0.5,
              ),
            ),
            const Spacer(),
            Icon(
              Icons.more_vert,
              color: Colors.white.withValues(alpha: 0.9),
              size: 24,
            ),
          ],
        ),
      ),
    );
  }
}

// ============ HABER DETAY SAYFASI ============
class NewsDetailPage extends StatelessWidget {
  final String title;
  final String source;
  final String description;
  final String imagePath;

  const NewsDetailPage({
    super.key,
    required this.title,
    required this.source,
    required this.description,
    required this.imagePath,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: CustomScrollView(
        slivers: [
          // App Bar with image
          SliverAppBar(
            expandedHeight: 250,
            pinned: true,
            backgroundColor: Colors.black,
            leading: IconButton(
              icon: Container(
                padding: const EdgeInsets.all(8),
                decoration: BoxDecoration(
                  color: Colors.black.withValues(alpha: 0.5),
                  shape: BoxShape.circle,
                ),
                child: const Icon(
                  Icons.arrow_back,
                  color: Colors.white,
                  size: 20,
                ),
              ),
              onPressed: () => Navigator.pop(context),
            ),
            actions: [
              IconButton(
                icon: Container(
                  padding: const EdgeInsets.all(8),
                  decoration: BoxDecoration(
                    color: Colors.black.withValues(alpha: 0.5),
                    shape: BoxShape.circle,
                  ),
                  child: const Icon(Icons.share, color: Colors.white, size: 20),
                ),
                onPressed: () {},
              ),
            ],
            flexibleSpace: FlexibleSpaceBar(
              background: Stack(
                fit: StackFit.expand,
                children: [
                  Image.asset(imagePath, fit: BoxFit.cover),
                  Container(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        begin: Alignment.topCenter,
                        end: Alignment.bottomCenter,
                        colors: [
                          Colors.transparent,
                          Colors.black.withValues(alpha: 0.8),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
          // Content
          SliverToBoxAdapter(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Source
                  Row(
                    children: [
                      Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 8,
                          vertical: 4,
                        ),
                        decoration: BoxDecoration(
                          color: Colors.red,
                          borderRadius: BorderRadius.circular(4),
                        ),
                        child: Text(
                          source.toUpperCase(),
                          style: const TextStyle(
                            color: Colors.white,
                            fontSize: 10,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                      ),
                      const SizedBox(width: 8),
                      Text(
                        '5 dakika önce',
                        style: TextStyle(color: Colors.grey[500], fontSize: 12),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  // Title
                  Text(
                    title,
                    style: const TextStyle(
                      color: Colors.white,
                      fontSize: 26,
                      fontWeight: FontWeight.bold,
                      height: 1.3,
                    ),
                  ),
                  const SizedBox(height: 24),
                  // Description
                  Text(
                    description,
                    style: TextStyle(
                      color: Colors.grey[300],
                      fontSize: 16,
                      height: 1.7,
                    ),
                  ),
                  const SizedBox(height: 16),
                  // Full article text
                  Text(
                    'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\n'
                    'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n'
                    'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.',
                    style: TextStyle(
                      color: Colors.grey[400],
                      fontSize: 16,
                      height: 1.7,
                    ),
                  ),
                  const SizedBox(height: 32),
                  // Action buttons
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      _buildActionButton(Icons.favorite_border, 'Beğen'),
                      _buildActionButton(Icons.chat_bubble_outline, 'Yorum'),
                      _buildActionButton(Icons.bookmark_border, 'Kaydet'),
                      _buildActionButton(Icons.share_outlined, 'Paylaş'),
                    ],
                  ),
                  const SizedBox(height: 32),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildActionButton(IconData icon, String label) {
    return Column(
      children: [
        Icon(icon, color: Colors.grey[500], size: 26),
        const SizedBox(height: 4),
        Text(label, style: TextStyle(color: Colors.grey[500], fontSize: 12)),
      ],
    );
  }
}
3
likes
160
points
29
downloads

Documentation

API reference

Publisher

verified publisherahmetbalkan.online

Weekly Downloads

A Flutter package that provides beautiful Flipboard-style vertical page flip animations with smooth 3D perspective transformations and spring physics.

Repository (GitHub)
View/report issues

Topics

#animation #flip #page-view #flipboard #widget

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flipbook_pro