mirror of
https://github.com/Iconica-Development/flutter_carousel.git
synced 2025-05-19 12:13:46 +02:00
Compare commits
23 commits
Author | SHA1 | Date | |
---|---|---|---|
|
eef26a375b | ||
|
cb432b548f | ||
|
6f9e7c863d | ||
|
4d1edb208e | ||
|
537870d922 | ||
|
f382ec7e59 | ||
|
3a6b8e0232 | ||
|
6a130302cf | ||
|
9f1fff083c | ||
|
7459954bed | ||
|
34f9b4143b | ||
|
7644eafa30 | ||
|
c4d82a1667 | ||
|
19d008c411 | ||
|
6a2161ca03 | ||
|
782361b846 | ||
|
7992d71076 | ||
|
6a55bc823b | ||
|
07964e5e96 | ||
|
a6254addd4 | ||
b16bcf548f | |||
43528119d5 | |||
7d514ef5dc |
24 changed files with 377 additions and 148 deletions
10
.github/dependabot.yaml
vendored
Normal file
10
.github/dependabot.yaml
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
- package-ecosystem: "pub"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
14
.github/workflows/component-ci.yml
vendored
Normal file
14
.github/workflows/component-ci.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: Iconica Standard Component CI Workflow
|
||||||
|
# Workflow Caller version: 2.0.0
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-global-iconica-workflow:
|
||||||
|
uses: Iconica-Development/.github/.github/workflows/component-ci.yml@master
|
||||||
|
secrets: inherit
|
||||||
|
permissions: write-all
|
||||||
|
with:
|
||||||
|
subfolder: "." # add optional subfolder to run workflow in
|
14
.github/workflows/component-documentation.yml
vendored
Normal file
14
.github/workflows/component-documentation.yml
vendored
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
name: Iconica Standard Component Documentation Workflow
|
||||||
|
# Workflow Caller version: 1.0.0
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
call-iconica-component-documentation-workflow:
|
||||||
|
uses: Iconica-Development/.github/.github/workflows/component-documentation.yml@master
|
||||||
|
secrets: inherit
|
||||||
|
permissions: write-all
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -21,3 +21,7 @@ doc/api/
|
||||||
*.js.map
|
*.js.map
|
||||||
|
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
# FVM Version Cache
|
||||||
|
.fvm/
|
||||||
|
.fvmrc
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
## 0.3.1
|
||||||
|
|
||||||
|
* Added Iconica CI and Iconica Linter
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
* Added option for backwards infinite scrolling and intial page
|
||||||
|
|
||||||
## 0.1.0
|
## 0.1.0
|
||||||
|
|
||||||
* add opacity as an option to the card transform
|
* add opacity as an option to the card transform
|
||||||
|
|
7
FEATURES.md
Normal file
7
FEATURES.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
* Every sort of widget can be animated as a card.
|
||||||
|
* For the animation the following properties can be set between animation frames:
|
||||||
|
this.x = 0,
|
||||||
|
this.y = 0,
|
||||||
|
this.angle = 0,
|
||||||
|
this.scale = 1,
|
||||||
|
this.opacity = 1.0,
|
10
LICENSE
10
LICENSE
|
@ -1 +1,9 @@
|
||||||
TODO: Add your license here.
|
Copyright (c) 2022 Iconica, All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
15
README.md
15
README.md
|
@ -1,18 +1,21 @@
|
||||||
|
[](https://github.com/Iconica-Development) [](https://github.com/Iconica-Development/flutter_carousel/actions/new) [](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.
|

|
||||||
|
|
||||||
|
Figma Design that defines this component (only accessible for Iconica developers): https://www.figma.com/file/4WkjwynOz5wFeFBRqTHPeP/Iconica-Design-System?type=design&node-id=357%3A3335&mode=design&t=XulkAJNPQ32ARxWh-1
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 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 +27,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>
|
|
@ -1 +1,9 @@
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_iconica_analysis/analysis_options.yaml
|
||||||
|
|
||||||
|
# Possible to overwrite the rules from the package
|
||||||
|
|
||||||
|
analyzer:
|
||||||
|
exclude:
|
||||||
|
|
||||||
|
linter:
|
||||||
|
rules:
|
BIN
carousel.gif
Normal file
BIN
carousel.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.2 MiB |
BIN
demo.gif
BIN
demo.gif
Binary file not shown.
Before Width: | Height: | Size: 8.3 MiB |
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
4
example/lib/extensions/string.dart
Normal file
4
example/lib/extensions/string.dart
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
extension CapitalizeExtension on String {
|
||||||
|
String capitalize() =>
|
||||||
|
isNotEmpty ? "${this[0].toUpperCase()}${substring(1)}" : this;
|
||||||
|
}
|
|
@ -1,7 +1,12 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:carousel/carousel.dart';
|
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;
|
||||||
|
@ -21,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) {
|
||||||
|
@ -50,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),
|
||||||
|
@ -121,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}'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// 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,
|
||||||
|
@ -6,5 +12,5 @@ class Pokemon {
|
||||||
});
|
});
|
||||||
String name;
|
String name;
|
||||||
int nr;
|
int nr;
|
||||||
List<String> types = const [];
|
List<PokemonType> types = const [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// 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 {
|
||||||
|
@ -16,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),
|
||||||
),
|
),
|
||||||
|
@ -36,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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -68,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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
20
example/lib/pokemon_types.dart
Normal file
20
example/lib/pokemon_types.dart
Normal 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,
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
/// A Flutter package for creating a carousel widget.
|
||||||
library carousel;
|
library carousel;
|
||||||
|
|
||||||
export 'package:carousel/src/carousel.dart';
|
export 'package:carousel/src/carousel.dart';
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:carousel/src/models/card_transform.dart';
|
import 'package:carousel/src/models/card_transform.dart';
|
||||||
import 'package:carousel/src/widgets/carousel_card.dart';
|
import 'package:carousel/src/widgets/carousel_card.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.dart';
|
||||||
|
@ -7,7 +11,8 @@ typedef CarouselCardBuilder = Widget Function(BuildContext context, int index);
|
||||||
|
|
||||||
class Carousel extends StatefulWidget {
|
class Carousel extends StatefulWidget {
|
||||||
/// Animated cards by swiping.
|
/// Animated cards by swiping.
|
||||||
/// 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.
|
||||||
/// Transform path can be privided using [transforms]
|
/// Transform path can be privided using [transforms]
|
||||||
const Carousel({
|
const Carousel({
|
||||||
required this.transforms,
|
required this.transforms,
|
||||||
|
@ -17,8 +22,10 @@ class Carousel extends StatefulWidget {
|
||||||
this.onPageChanged,
|
this.onPageChanged,
|
||||||
this.alignment = AlignmentDirectional.topStart,
|
this.alignment = AlignmentDirectional.topStart,
|
||||||
this.onCardClick,
|
this.onCardClick,
|
||||||
Key? key,
|
this.initialPage = 0,
|
||||||
}) : super(key: key);
|
this.allowInfiniteScrollingBackwards = false,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
/// A list of transforms to calculate the position of the card when swiping.
|
/// A list of transforms to calculate the position of the card when swiping.
|
||||||
/// Every item in the list is one of the possible card positions.
|
/// Every item in the list is one of the possible card positions.
|
||||||
|
@ -27,7 +34,8 @@ class Carousel extends StatefulWidget {
|
||||||
/// The index of the transform card which acts as the selected card.
|
/// The index of the transform card which acts as the selected card.
|
||||||
final int selectableCardId;
|
final int selectableCardId;
|
||||||
|
|
||||||
/// Builder for the card given a [context] and a [index] to identify the right card.
|
/// Builder for the card given a [context] and a [index] to
|
||||||
|
/// identify the right card.
|
||||||
final CarouselCardBuilder builder;
|
final CarouselCardBuilder builder;
|
||||||
|
|
||||||
/// Called when selected card is changed to the next one.
|
/// Called when selected card is changed to the next one.
|
||||||
|
@ -42,16 +50,31 @@ class Carousel extends StatefulWidget {
|
||||||
/// Size of the pageview used to capture swipe gestures.
|
/// Size of the pageview used to capture swipe gestures.
|
||||||
final double pageViewHeight;
|
final double pageViewHeight;
|
||||||
|
|
||||||
|
/// The page to show when first creating the [Carousel].
|
||||||
|
final int initialPage;
|
||||||
|
|
||||||
|
/// Whether to allow infinite scrolling backwards. Defaults to false. If true,
|
||||||
|
/// this works by using a very large number of pages (10000).
|
||||||
|
/// Works in conjunction with [initialPage].
|
||||||
|
final bool allowInfiniteScrollingBackwards;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<Carousel> createState() => _CarouselState();
|
State<Carousel> createState() => _CarouselState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CarouselState extends State<Carousel> {
|
class _CarouselState extends State<Carousel> {
|
||||||
final PageController _pageController = PageController(initialPage: 0);
|
late PageController _pageController;
|
||||||
double _currentPage = 0;
|
double _currentPage = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
_pageController = PageController(
|
||||||
|
initialPage: widget.allowInfiniteScrollingBackwards
|
||||||
|
? 10000 + widget.initialPage
|
||||||
|
: widget.initialPage,
|
||||||
|
);
|
||||||
|
_currentPage = _pageController.initialPage.toDouble();
|
||||||
|
|
||||||
_pageController.addListener(() {
|
_pageController.addListener(() {
|
||||||
_currentPage = _pageController.page!;
|
_currentPage = _pageController.page!;
|
||||||
});
|
});
|
||||||
|
@ -65,38 +88,36 @@ class _CarouselState extends State<Carousel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Stack(
|
||||||
return Stack(
|
alignment: widget.alignment,
|
||||||
alignment: widget.alignment,
|
children: [
|
||||||
children: [
|
AnimatedBuilder(
|
||||||
AnimatedBuilder(
|
animation: _pageController,
|
||||||
animation: _pageController,
|
builder: (context, _) {
|
||||||
builder: (context, _) {
|
var transitionPos = _currentPage % 1;
|
||||||
final transitionPos = _currentPage % 1;
|
var index = _currentPage.floor();
|
||||||
final index = _currentPage.floor();
|
var length = widget.transforms.length - 1;
|
||||||
final length = widget.transforms.length - 1;
|
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < length; i++) ...[
|
for (var i = 0; i < length; i++) ...[
|
||||||
CarouselCard(
|
CarouselCard(
|
||||||
cardTransform: widget.transforms[i]
|
cardTransform: widget.transforms[i]
|
||||||
.transform(widget.transforms[i + 1], transitionPos),
|
.transform(widget.transforms[i + 1], transitionPos),
|
||||||
child: widget.builder.call(context, index - i),
|
child: widget.builder.call(context, index - i),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
SizedBox(
|
||||||
SizedBox(
|
height: widget.pageViewHeight,
|
||||||
height: widget.pageViewHeight,
|
child: PageView.builder(
|
||||||
child: PageView.builder(
|
scrollBehavior: _MouseSwipeOnWeb(),
|
||||||
scrollBehavior: _MouseSwipeOnWeb(),
|
onPageChanged: widget.onPageChanged,
|
||||||
onPageChanged: widget.onPageChanged,
|
controller: _pageController,
|
||||||
controller: _pageController,
|
itemBuilder: (context, index) => Visibility(
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return Visibility(
|
|
||||||
visible: false,
|
visible: false,
|
||||||
maintainState: true,
|
maintainState: true,
|
||||||
maintainAnimation: true,
|
maintainAnimation: true,
|
||||||
|
@ -116,13 +137,11 @@ class _CarouselState extends State<Carousel> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MouseSwipeOnWeb extends MaterialScrollBehavior {
|
class _MouseSwipeOnWeb extends MaterialScrollBehavior {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
class CardTransform {
|
class CardTransform {
|
||||||
/// Used by [Carousel] to build cards on the correct position.
|
/// Used by [Carousel] to build cards on the correct position.
|
||||||
CardTransform({
|
CardTransform({
|
||||||
|
@ -24,15 +28,14 @@ class CardTransform {
|
||||||
/// [transitionPos] is a position value of a swipe for example.
|
/// [transitionPos] is a position value of a swipe for example.
|
||||||
/// [other] is the position, scale, rotation
|
/// [other] is the position, scale, rotation
|
||||||
/// which the current [CardTransform] need to be transformed to.
|
/// which the current [CardTransform] need to be transformed to.
|
||||||
CardTransform transform(CardTransform other, double transitionPos) {
|
CardTransform transform(CardTransform other, double transitionPos) =>
|
||||||
return CardTransform(
|
CardTransform(
|
||||||
x: _transformValue(x, other.x, transitionPos),
|
x: _transformValue(x, other.x, transitionPos),
|
||||||
y: _transformValue(y, other.y, transitionPos),
|
y: _transformValue(y, other.y, transitionPos),
|
||||||
angle: _transformValue(angle, other.angle, transitionPos),
|
angle: _transformValue(angle, other.angle, transitionPos),
|
||||||
scale: _transformValue(scale, other.scale, transitionPos),
|
scale: _transformValue(scale, other.scale, transitionPos),
|
||||||
opacity: _transformValue(opacity, other.opacity, transitionPos),
|
opacity: _transformValue(opacity, other.opacity, transitionPos),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
double _transformValue(double valueA, double valueB, double transformPos) =>
|
double _transformValue(double valueA, double valueB, double transformPos) =>
|
||||||
valueA - ((valueA - valueB) * transformPos);
|
valueA - ((valueA - valueB) * transformPos);
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'package:carousel/src/models/card_transform.dart';
|
import 'package:carousel/src/models/card_transform.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -6,26 +10,24 @@ class CarouselCard extends StatelessWidget {
|
||||||
const CarouselCard({
|
const CarouselCard({
|
||||||
required this.cardTransform,
|
required this.cardTransform,
|
||||||
required this.child,
|
required this.child,
|
||||||
Key? key,
|
super.key,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
final CardTransform cardTransform;
|
final CardTransform cardTransform;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Transform.translate(
|
||||||
return Transform.translate(
|
offset: Offset(cardTransform.x, cardTransform.y),
|
||||||
offset: Offset(cardTransform.x, cardTransform.y),
|
child: Transform.rotate(
|
||||||
child: Transform.rotate(
|
angle: cardTransform.angle,
|
||||||
angle: cardTransform.angle,
|
child: Transform.scale(
|
||||||
child: Transform.scale(
|
scale: cardTransform.scale,
|
||||||
scale: cardTransform.scale,
|
child: Opacity(
|
||||||
child: Opacity(
|
opacity: cardTransform.opacity,
|
||||||
opacity: cardTransform.opacity,
|
child: child,
|
||||||
child: child,
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
46
pubspec.yaml
46
pubspec.yaml
|
@ -1,9 +1,11 @@
|
||||||
name: carousel
|
name: carousel
|
||||||
description: card carousel
|
description: card carousel
|
||||||
version: 0.1.0
|
version: 0.3.1
|
||||||
|
|
||||||
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.6 <3.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
flutter: ">=1.17.0"
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13,41 +15,9 @@ dependencies:
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^2.0.0
|
flutter_iconica_analysis:
|
||||||
|
git:
|
||||||
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
|
ref: 6.0.0
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
|
||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
# To add assets to your package, add an assets section, like this:
|
|
||||||
# assets:
|
|
||||||
# - images/a_dot_burr.jpeg
|
|
||||||
# - images/a_dot_ham.jpeg
|
|
||||||
#
|
|
||||||
# For details regarding assets in packages, see
|
|
||||||
# https://flutter.dev/assets-and-images/#from-packages
|
|
||||||
#
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
|
||||||
|
|
||||||
# To add custom fonts to your package, add a fonts section here,
|
|
||||||
# in this "flutter" section. Each entry in this list should have a
|
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
|
||||||
# list giving the asset and other descriptors for the font. For
|
|
||||||
# example:
|
|
||||||
# fonts:
|
|
||||||
# - family: Schyler
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/Schyler-Regular.ttf
|
|
||||||
# - asset: fonts/Schyler-Italic.ttf
|
|
||||||
# style: italic
|
|
||||||
# - family: Trajan Pro
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/TrajanPro.ttf
|
|
||||||
# - asset: fonts/TrajanPro_Bold.ttf
|
|
||||||
# weight: 700
|
|
||||||
#
|
|
||||||
# For details regarding fonts in packages, see
|
|
||||||
# https://flutter.dev/custom-fonts/#from-packages
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// SPDX-FileCopyrightText: 2022 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:carousel/src/models/card_transform.dart';
|
import 'package:carousel/src/models/card_transform.dart';
|
||||||
|
|
Loading…
Reference in a new issue