flutter_spinwheel 0.1.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 76

🎨 Flutter Spinwheel #

A widget that outputs items (text or image) along a pan-able circular wheel/spinner with customization options.

🍀 Features #

  • Auto-play (enable/disable)
  • Long-press to pause (enable/disable)
  • Size adjustments
  • Text/Image support
  • Image tweaking support
  • Clockwise and counter-clockwise pan to navigate
  • Touch to navigate in previously panned direction
  • Paint customization to alter the look
  • Callback function to notify selected item

📥 Install & Import #

Add:

dependencies:
  flutter_spinwheel: "^1.0.0"

among your other dependencies in pubspec.yaml and then import it in your required project:

import  'package:flutter_spinwheel/flutter_spinwheel.dart';

🔧 Usage #

List<String> items = ['🏘',  '🚓',  '🚛',  '🏍',  '🎉'];

List<NamedImage> imgPack = [
	NamedImage(
		path:  'assets/images/car.jpg',
		name:  'car',
	),
	NamedImage(
		path:  'assets/images/bike.jpg',
		name:  'bike',
	),
	NamedImage(
		path:  'assets/images/other.jpg',
		name:  'other',
	),
];
final spinwheelWithText = Spinwheel(
	items: items,
	onChanged: (val) {
	if (this.mounted)
		setState(() {
			currentText = val;
		});
	},
	size:  150.0,
	select:  2,
	autoPlay:  true,
);
final spinwheelWithImage = Spinwheel(
	size:  250.0,
	imageItems: imgPack,
	select:  1,
	onChanged: (val) {
		carousel.animateToPage(carouselNames.indexOf(val),
		duration:  Duration(seconds:  1), curve:  Curves.linear);
	},
	rotationDuration:  250,
	autoPlay:  true,
	longPressToPauseAutoplay:  true,
	hideOthers:  false,
	shouldDrawBorder:  false,
	shouldDrawCenterPiece:  false,
	wheelOrientation: pi /  4,
);

📁 Sample #

Text Demo Image Demo Simple Demo

🚀 Future Plans #

  • Tap on any item on the spinner to rotate to that item
  • More fluid animations

👨🏼‍💻 Support / Feature Request / Bug Report #

If you experience any issues or need help understanding some of the functionalities or you feel that it can be improved, feel free to open an issue on the repo (ofcourse, first look if there is already a similar open issue).

[0.1.0] - 02/04/2020 #

  • Fixed some sizing issues

[0.0.2] - 31/03/2020 #

  • Release to pub.dev and testing

[0.0.1] - 30/03/2020 #

  • Initial release for testing

example/lib/main.dart

import 'dart:math';

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

import 'package:flutter_spinwheel/flutter_spinwheel.dart';
import 'package:carousel_slider/carousel_slider.dart';

List<Widget> getAppBarActions(BuildContext context) {
  return [
    FlatButton(
      child: Icon(
        Icons.device_unknown,
        color: Colors.white,
      ),
      onPressed: () {
        Navigator.pushReplacementNamed(context, '/sample');
      },
    ),
    FlatButton(
      child: Icon(
        Icons.insert_emoticon,
        color: Colors.white,
      ),
      onPressed: () {
        Navigator.pushReplacementNamed(context, '/emoji');
      },
    ),
    FlatButton(
      child: Icon(
        Icons.image,
        color: Colors.white,
      ),
      onPressed: () {
        Navigator.pushReplacementNamed(context, '/image');
      },
    ),
  ];
}

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

class SpinwheelDemo extends StatefulWidget {
  @override
  _SpinwheelDemoState createState() => _SpinwheelDemoState();
}

class _SpinwheelDemoState extends State<SpinwheelDemo> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Spinwheel Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/emoji',
      routes: {
        '/sample': (context) => SpinwheelSampleApp(),
        '/emoji': (context) => SpinwheelEmojiDemo(),
        '/image': (context) => SpinwheelImageDemo()
      },
    );
  }
}

class SpinwheelSampleApp extends StatefulWidget {
  @override
  _SpinwheelSampleAppState createState() => _SpinwheelSampleAppState();
}

class _SpinwheelSampleAppState extends State<SpinwheelSampleApp> {
  List<String> questions;
  List<List<dynamic>> choices;
  List<String> answers;
  int select;
  String currentText;

  @override
  void initState() {
    super.initState();
    questions = [
      'Your first programming language?',
      'Did you own any pets?',
      'Choose any one vehicle you own from below',
    ];
    choices = [
      ['Dart', 'C', 'C++', 'Java', 'Python', 'JS', 'TS', '😠'],
      ['Yes', 'No'],
      [
        NamedImage(
          path: 'assets/images/car.jpg',
          name: 'car',
        ),
        NamedImage(
          path: 'assets/images/bike.jpg',
          name: 'bike',
        ),
        NamedImage(
          path: 'assets/images/other.jpg',
          name: 'other',
        ),
      ]
    ];
    select = 0;
    answers = ['', '', ''];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Center(
            child: Text('Sample'),
          ),
          actions: getAppBarActions(context)),
      body: Scrollbar(
        child: ListView.builder(
            itemCount: 3,
            itemBuilder: (context, index) => Container(
                  margin: EdgeInsets.all(20.0),
                  height: MediaQuery.of(context).size.height / 2,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    children: <Widget>[
                      Text(questions[index]),
                      Text(answers[index] == '😠'
                          ? '${answers[index]} None of these'
                          : answers[index]),
                      Spinwheel(
                        items: choices[index][0] is String
                            ? choices[index].cast<String>()
                            : null,
                        imageItems: choices[index][0] is NamedImage
                            ? choices[index].cast<NamedImage>()
                            : null,
                        select: select,
                        autoPlay: false,
                        hideOthers: false,
                        shouldDrawBorder: false,
                        onChanged: (val) {
                          if (this.mounted)
                            setState(() {
                              answers[index] = val;
                            });
                        },
                      )
                    ],
                  ),
                )),
      ),
    );
  }
}

class SpinwheelEmojiDemo extends StatefulWidget {
  @override
  _SpinwheelEmojiDemoState createState() => _SpinwheelEmojiDemoState();
}

class _SpinwheelEmojiDemoState extends State<SpinwheelEmojiDemo> {
  List<String> items;
  int select;
  String currentText;

  @override
  void initState() {
    super.initState();
    items = ['🏘', '🚓', '🚛', '🏍', '🎉'];
    select = 2;
    currentText = items[select];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Center(
            child: Text('Emoji'),
          ),
          actions: getAppBarActions(context)),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          Center(
            child: Text(
              currentText,
              style: TextStyle(fontSize: 100.0),
            ),
          ),
          Spinwheel(
            items: items,
            onChanged: (val) {
              if (this.mounted)
                setState(() {
                  currentText = val;
                });
            },
            shouldHighlight: false,
            size: 150.0,
            select: 2,
            rotationDuration: 250,
            autoPlay: true,
            shouldDrawDividers: true,
          ),
        ],
      ),
    );
  }
}

class SpinwheelImageDemo extends StatefulWidget {
  @override
  _SpinwheelImageDemoState createState() => _SpinwheelImageDemoState();
}

class _SpinwheelImageDemoState extends State<SpinwheelImageDemo> {
  List<String> carouselNames;
  List<NamedImage> imgPack;
  CarouselSlider carousel;

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

    carouselNames = ['dog', 'cat', 'budgie', 'goldfish'];

    imgPack = [
      NamedImage(
        path: 'assets/images/dog.jpg',
        name: carouselNames[0],
        offsetX: 1.2,
      ),
      NamedImage(
        path: 'assets/images/cat.jpg',
        name: carouselNames[1],
        offsetY: 1.7,
      ),
      NamedImage(
        path: 'assets/images/budgie.jpg',
        name: carouselNames[2],
      ),
      NamedImage(
          path: 'assets/images/goldfish.jpg',
          name: carouselNames[3],
          offsetX: 1.2),
    ];

    // For Image example
    carousel = CarouselSlider(
      items: imgPack.map((img) {
        return Container(
          padding: EdgeInsets.all(10.0),
          color: Colors.orange,
          child: Image.asset(img.path),
        );
      }).toList(),
      autoPlay: false,
      enlargeCenterPage: true,
      viewportFraction: 1.0,
      aspectRatio: 2.0,
      initialPage: 2,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(
          child: Text('Image'),
        ),
        actions: getAppBarActions(context),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          carousel,
          Center(
            child: Spinwheel(
              size: 250.0,
              imageItems: imgPack,
              select: 1,
              onChanged: (val) {
                carousel.animateToPage(carouselNames.indexOf(val),
                    duration: Duration(seconds: 1), curve: Curves.linear);
              },
              rotationDuration: 250,
              autoPlay: true,
              longPressToPauseAutoplay: true,
              hideOthers: false,
              shouldDrawDividers: true,
              shouldDrawBorder: false,
              shouldDrawCenterPiece: false,
              wheelOrientation: pi / 4,
            ),
          ),
        ],
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  flutter_spinwheel: ^0.1.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:flutter_spinwheel/flutter_spinwheel.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
53
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
76
Learn more about scoring.

We analyzed this package on Jul 9, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14
  • Flutter: 1.17.5

Analysis suggestions

Package not compatible with SDK dart

Because:

  • flutter_spinwheel that is a package requiring null.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12 1.14.13
meta 1.1.8 1.2.1
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
Dev dependencies
flutter_test