half_circle_scroll 0.0.2 copy "half_circle_scroll: ^0.0.2" to clipboard
half_circle_scroll: ^0.0.2 copied to clipboard

A customizable half-circle scroll widget for Flutter.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Half Circle Scroll Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const DemoPage(),
    );
  }
}

class DemoPage extends StatefulWidget {
  const DemoPage({Key? key}) : super(key: key);

  @override
  State<DemoPage> createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  int selectedIndex = 0;
  HalfCircleOrientation currentOrientation = HalfCircleOrientation.vertical;
  HalfCircleItemShape currentShape = HalfCircleItemShape.roundedRectangle;
  
  final List<HalfCircleScrollItem> items = [
    const HalfCircleScrollItem(text: 'Home'),
    const HalfCircleScrollItem(text: 'Profile'),
    const HalfCircleScrollItem(text: 'Settings'),
    const HalfCircleScrollItem(text: 'Messages'),
    const HalfCircleScrollItem(text: 'Notifications'),
    const HalfCircleScrollItem(text: 'Search'),
    const HalfCircleScrollItem(text: 'Calendar'),
    const HalfCircleScrollItem(text: 'Tasks'),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Half Circle Scroll Demo'),
        backgroundColor: Colors.blue[600],
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // Selected item display
            Container(
              padding: const EdgeInsets.all(16),
              margin: const EdgeInsets.only(bottom: 20),
              decoration: BoxDecoration(
                color: Colors.blue[50],
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: Colors.blue[200]!),
              ),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.touch_app, color: Colors.blue[600]),
                  const SizedBox(width: 8),
                  Text(
                    'Selected: ${items[selectedIndex].text}',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.w600,
                      color: Colors.blue[800],
                    ),
                  ),
                ],
              ),
            ),

            // Half Circle Scroll Widget
            Container(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topLeft,
                  end: Alignment.bottomRight,
                  colors: [Colors.blue[50]!, Colors.purple[50]!],
                ),
                borderRadius: BorderRadius.circular(20),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.1),
                    blurRadius: 20,
                    offset: const Offset(0, 10),
                  ),
                ],
              ),
              padding: const EdgeInsets.all(20),
              child: HalfCircleScroll(
                items: items,
                config: HalfCircleScrollConfig(
                  radius: 150.0,
                  orientation: currentOrientation,
                  itemShape: currentShape,
                  selectedColor: Colors.orange,
                  unselectedColor: Colors.blue,
                  itemWidth: 100.0,
                  itemHeight: 80.0,
                  animationDuration: const Duration(milliseconds: 400),
                  animationCurve: Curves.easeOutCubic,
                  selectedTextStyle: const TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: 12,
                  ),
                  unselectedTextStyle: const TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.w500,
                    fontSize: 10,
                  ),
                ),
                onSelectionChanged: (index) {
                  setState(() {
                    selectedIndex = index;
                  });
                },
              ),
            ),

            const SizedBox(height: 30),

            // Controls
            Card(
              elevation: 4,
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Controls',
                      style: Theme.of(context).textTheme.headlineSmall,
                    ),
                    const SizedBox(height: 16),
                    
                    // Orientation Selector
                    const Text('Orientation:', style: TextStyle(fontWeight: FontWeight.w600)),
                    const SizedBox(height: 8),
                    Wrap(
                      spacing: 8,
                      children: HalfCircleOrientation.values.map((orientation) {
                        return ChoiceChip(
                          label: Text(_getOrientationName(orientation)),
                          selected: currentOrientation == orientation,
                          onSelected: (selected) {
                            if (selected) {
                              setState(() {
                                currentOrientation = orientation;
                              });
                            }
                          },
                        );
                      }).toList(),
                    ),
                    
                    const SizedBox(height: 16),
                    
                    // Shape Selector
                    const Text('Item Shape:', style: TextStyle(fontWeight: FontWeight.w600)),
                    const SizedBox(height: 8),
                    Wrap(
                      spacing: 8,
                      children: HalfCircleItemShape.values.map((shape) {
                        return ChoiceChip(
                          label: Text(_getShapeName(shape)),
                          selected: currentShape == shape,
                          onSelected: (selected) {
                            if (selected) {
                              setState(() {
                                currentShape = shape;
                              });
                            }
                          },
                        );
                      }).toList(),
                    ),
                  ],
                ),
              ),
            ),

            const SizedBox(height: 30),

            // Custom Builder Example
            Card(
              elevation: 4,
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Custom Builder Example',
                      style: Theme.of(context).textTheme.headlineSmall,
                    ),
                    const SizedBox(height: 16),
                    
                    Container(
                      height: 300,
                      decoration: BoxDecoration(
                        gradient: LinearGradient(
                          colors: [Colors.purple[100]!, Colors.pink[100]!],
                        ),
                        borderRadius: BorderRadius.circular(12),
                      ),
                      child: HalfCircleScroll(
                        items: List.generate(6, (index) => 
                          HalfCircleScrollItem(text: 'Custom ${index + 1}')
                        ),
                        config: const HalfCircleScrollConfig(
                          radius: 120.0,
                          orientation: HalfCircleOrientation.horizontal,
                          itemWidth: 80.0,
                          itemHeight: 80.0,
                        ),
                        itemBuilder: (context, index, item, isSelected, scale, opacity) {
                          return Container(
                            decoration: BoxDecoration(
                              gradient: LinearGradient(
                                begin: Alignment.topLeft,
                                end: Alignment.bottomRight,
                                colors: isSelected 
                                  ? [Colors.orange, Colors.deepOrange] 
                                  : [Colors.purple[300]!, Colors.purple[600]!],
                              ),
                              borderRadius: BorderRadius.circular(16),
                              boxShadow: [
                                BoxShadow(
                                  color: (isSelected ? Colors.orange : Colors.purple)
                                      .withOpacity(0.4),
                                  blurRadius: isSelected ? 12 : 6,
                                  offset: const Offset(0, 4),
                                ),
                              ],
                            ),
                            child: Center(
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(
                                    _getIconForIndex(index),
                                    color: Colors.white,
                                    size: 20 * scale,
                                  ),
                                  const SizedBox(height: 4),
                                  Text(
                                    item.text ?? '',
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 8 * scale,
                                      fontWeight: isSelected 
                                        ? FontWeight.bold 
                                        : FontWeight.normal,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          );
                        },
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  String _getOrientationName(HalfCircleOrientation orientation) {
    switch (orientation) {
      case HalfCircleOrientation.vertical:
        return 'Vertical';
      case HalfCircleOrientation.horizontal:
        return 'Horizontal';
      case HalfCircleOrientation.invertedVertical:
        return 'Inverted V';
      case HalfCircleOrientation.invertedHorizontal:
        return 'Inverted H';
    }
  }

  String _getShapeName(HalfCircleItemShape shape) {
    switch (shape) {
      case HalfCircleItemShape.rectangle:
        return 'Rectangle';
      case HalfCircleItemShape.circle:
        return 'Circle';
      case HalfCircleItemShape.roundedRectangle:
        return 'Rounded';
      case HalfCircleItemShape.custom:
        return 'Custom';
    }
  }

  IconData _getIconForIndex(int index) {
    final icons = [
      Icons.home,
      Icons.star,
      Icons.favorite,
      Icons.settings,
      Icons.person,
      Icons.message,
    ];
    return icons[index % icons.length];
  }
}
1
likes
160
points
29
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A customizable half-circle scroll widget for Flutter.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on half_circle_scroll