Updated README, updated GIF, improved example, added dependabot

This commit is contained in:
Thomas Klein Langenhorst 2022-12-13 16:26:31 +01:00
parent b16bcf548f
commit a6254addd4
12 changed files with 193 additions and 58 deletions

10
.github/dependabot.yaml vendored Normal file
View file

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "pub"
directory: "/"
schedule:
interval: "daily"

View file

@ -30,18 +30,3 @@ jobs:
run: flutter format -o none --set-exit-if-changed . run: flutter format -o none --set-exit-if-changed .
- name: Flutter analyze - name: Flutter analyze
run: flutter analyze run: flutter analyze
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.gradle/wrapper
/opt/hostedtoolcache/flutter
key: ${{ runner.OS }}-flutter-install-cache
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
- name: Run tests
run: flutter test --coverage

View file

@ -1,18 +1,18 @@
[![pub package](https://img.shields.io/pub/v/flutter_carousel.svg)](https://github.com/Iconica-Development) [![Build status](https://img.shields.io/github/workflow/status/Iconica-Development/flutter_carousel/CI)](https://github.com/Iconica-Development/flutter_carousel/actions/new) [![style: effective dart](https://img.shields.io/badge/style-effective_dart-40c4ff.svg)](https://github.com/tenhobi/effective_dart)
# Carousel # Carousel
Carousel widget. Makes it easier to create card carousels using a list of transforms. Carousel widget. Makes it easier to create card carousels using a list of transforms.
Each card can change its rotation, position and scale when swiping the cards. Each card can change its rotation, position and scale when swiping the cards.
Supports all platforms. ![Carousel GIF](carousel.gif)
![Demo video](demo.gif)
## Usage ## Usage
To use this package, add `carousel` as a [dependency in your pubspec.yaml file](https://flutter.dev/docs/development/platform-integration/platform-channels). To use this package, add `carousel` as a dependency in your pubspec.yaml file.
### Example ## How to use
See [Example Code](example/lib/main.dart) for more info. See the [Example Code](example/lib/main.dart) for an example on how to use this package.
## Issues ## Issues
@ -24,4 +24,4 @@ If you would like to contribute to the plugin (e.g. by improving the documentati
## Author ## Author
This carousel for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl> This `carousel` for Flutter is developed by [Iconica](https://iconica.nl). You can contact us at <support@iconica.nl>

BIN
carousel.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

BIN
demo.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 MiB

View file

@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>9.0</string> <string>11.0</string>
</dict> </dict>
</plist> </plist>

View file

@ -272,7 +272,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -350,7 +350,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -399,7 +399,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0; IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;

View file

@ -0,0 +1,4 @@
extension CapitalizeExtension on String {
String capitalize() =>
isNotEmpty ? "${this[0].toUpperCase()}${substring(1)}" : this;
}

View file

@ -6,6 +6,7 @@ import 'package:carousel/carousel.dart';
import 'package:carousel_example/pokemon.dart'; import 'package:carousel_example/pokemon.dart';
import 'package:carousel_example/pokemon_card.dart'; import 'package:carousel_example/pokemon_card.dart';
import 'package:carousel_example/pokemon_types.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'dart:math' as math; import 'dart:math' as math;
@ -25,14 +26,65 @@ class _CarouselExampleAppState extends State<CarouselExampleApp> {
Pokemon? selected; Pokemon? selected;
final List<Pokemon> pokemons = [ final List<Pokemon> pokemons = [
Pokemon(name: 'Bulbasaur', nr: 1, types: ['grass', 'poison']), Pokemon(
Pokemon(name: 'Charmander', nr: 4, types: ['fire']), name: 'Bulbasaur',
Pokemon(name: 'Squirtle', nr: 7, types: ['water']), nr: 1,
Pokemon(name: 'Caterpie', nr: 10, types: ['bug']), types: [
Pokemon(name: 'Pidgey', nr: 16, types: ['normal', 'flying']), PokemonType.grass,
Pokemon(name: 'Pikachu', nr: 25, types: ['electric']), PokemonType.poison,
Pokemon(name: 'Machop', nr: 66, types: ['fighting']), ],
Pokemon(name: 'Geodude', nr: 74, types: ['rock', 'ground']), ),
Pokemon(
name: 'Charmander',
nr: 4,
types: [
PokemonType.fire,
],
),
Pokemon(
name: 'Squirtle',
nr: 7,
types: [
PokemonType.water,
],
),
Pokemon(
name: 'Caterpie',
nr: 10,
types: [
PokemonType.bug,
],
),
Pokemon(
name: 'Pidgey',
nr: 16,
types: [
PokemonType.normal,
PokemonType.flying,
],
),
Pokemon(
name: 'Pikachu',
nr: 25,
types: [
PokemonType.electric,
],
),
Pokemon(
name: 'Machop',
nr: 66,
types: [
PokemonType.fighting,
],
),
Pokemon(
name: 'Geodude',
nr: 74,
types: [
PokemonType.rock,
PokemonType.ground,
],
),
]; ];
Widget _buildCard(BuildContext context, int index) { Widget _buildCard(BuildContext context, int index) {
@ -54,7 +106,8 @@ class _CarouselExampleAppState extends State<CarouselExampleApp> {
body: Stack( body: Stack(
alignment: Alignment.bottomCenter, alignment: Alignment.bottomCenter,
children: [ children: [
SafeArea( Padding(
padding: const EdgeInsets.all(16.0),
child: ListView( child: ListView(
children: [ children: [
const SizedBox(height: 50), const SizedBox(height: 50),
@ -125,7 +178,7 @@ class _CarouselExampleAppState extends State<CarouselExampleApp> {
), ),
if (selected != null) if (selected != null)
Padding( Padding(
padding: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.only(bottom: 20),
child: Text('Clicked: ${selected!.name}'), child: Text('Clicked: ${selected!.name}'),
), ),
], ],

View file

@ -2,6 +2,8 @@
// //
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
import 'package:carousel_example/pokemon_types.dart';
class Pokemon { class Pokemon {
Pokemon({ Pokemon({
required this.name, required this.name,
@ -10,5 +12,5 @@ class Pokemon {
}); });
String name; String name;
int nr; int nr;
List<String> types = const []; List<PokemonType> types = const [];
} }

View file

@ -2,7 +2,9 @@
// //
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
import 'package:carousel_example/extensions/string.dart';
import 'package:carousel_example/pokemon.dart'; import 'package:carousel_example/pokemon.dart';
import 'package:carousel_example/pokemon_types.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class PokemonCard extends StatelessWidget { class PokemonCard extends StatelessWidget {
@ -20,9 +22,11 @@ class PokemonCard extends StatelessWidget {
width: MediaQuery.of(context).size.width / 2.2, width: MediaQuery.of(context).size.width / 2.2,
height: 220, height: 220,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blue.shade700, color: Colors.white,
boxShadow: const [ boxShadow: const [
BoxShadow(blurRadius: 4), BoxShadow(
blurRadius: 8,
),
], ],
borderRadius: BorderRadius.circular(15), borderRadius: BorderRadius.circular(15),
), ),
@ -40,29 +44,12 @@ class PokemonCard extends StatelessWidget {
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 20, bottom: 8), padding: const EdgeInsets.only(top: 20, bottom: 8),
child: Text('Types', style: textStyle), child: Text('Type', style: textStyle),
), ),
Row( Row(
children: [ children: [
for (var type in pokemon.types) ...[ for (var type in pokemon.types) ...[
Container( TypeBadge(type: type),
height: 25,
width: 60,
margin: const EdgeInsets.only(right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Color(type.hashCode).withAlpha(255),
),
child: Center(
child: Text(
type,
style: const TextStyle(
color: Colors.white,
),
textAlign: TextAlign.center,
),
),
)
], ],
], ],
), ),
@ -72,3 +59,77 @@ class PokemonCard extends StatelessWidget {
); );
} }
} }
class TypeBadge extends StatelessWidget {
const TypeBadge({
super.key,
required this.type,
});
final PokemonType type;
@override
Widget build(BuildContext context) {
return Container(
height: 25,
width: 60,
margin: const EdgeInsets.only(right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: getTypeColor(type),
),
child: Center(
child: Text(
type.name.capitalize(),
style: const TextStyle(
color: Colors.white,
),
textAlign: TextAlign.center,
),
),
);
}
Color getTypeColor(PokemonType type) {
switch (type) {
case PokemonType.fire:
return const Color(0xFFF08030);
case PokemonType.water:
return const Color(0xFF6890F0);
case PokemonType.grass:
return const Color(0xFF78C850);
case PokemonType.normal:
return const Color(0xFFA8A878);
case PokemonType.electric:
return const Color(0xFFF8D030);
case PokemonType.ice:
return const Color(0xFF98D8D8);
case PokemonType.fighting:
return const Color(0xFFC03028);
case PokemonType.poison:
return const Color(0xFFA040A0);
case PokemonType.ground:
return const Color(0xFFE0C068);
case PokemonType.flying:
return const Color(0xFFA890F0);
case PokemonType.psychic:
return const Color(0xFFF85888);
case PokemonType.bug:
return const Color(0xFFA8B820);
case PokemonType.rock:
return const Color(0xFFB8A038);
case PokemonType.ghost:
return const Color(0xFF705898);
case PokemonType.dark:
return const Color(0xFF705848);
case PokemonType.dragon:
return const Color(0xFF7038F8);
case PokemonType.steel:
return const Color(0xFFB8B8D0);
case PokemonType.fairy:
return const Color(0xFFEE99AC);
default:
return const Color(0xFF68A090);
}
}
}

View file

@ -0,0 +1,20 @@
enum PokemonType {
fire,
water,
grass,
normal,
electric,
ice,
fighting,
poison,
ground,
flying,
psychic,
bug,
rock,
ghost,
dark,
dragon,
steel,
fairy,
}