Initial commit
This commit is contained in:
@@ -0,0 +1,418 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:holo_shiny/holo_shiny.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const ExampleApp());
|
||||
}
|
||||
|
||||
class ExampleApp extends StatelessWidget {
|
||||
const ExampleApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF24A6A8)),
|
||||
),
|
||||
home: const ExampleHome(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ExampleHome extends StatefulWidget {
|
||||
const ExampleHome({super.key});
|
||||
|
||||
@override
|
||||
State<ExampleHome> createState() => _ExampleHomeState();
|
||||
}
|
||||
|
||||
class _ExampleHomeState extends State<ExampleHome> {
|
||||
late final ShinyController _sensorController;
|
||||
late final StreamController<Offset> _externalTiltController;
|
||||
late final ShinyController _overrideController;
|
||||
|
||||
double _prismatic = 0.8;
|
||||
double _sparkle = 0.8;
|
||||
double _specular = 0.8;
|
||||
double _diffraction = 0.8;
|
||||
HolographStyle _style = HolographStyle.crackedIce;
|
||||
SparkleShapeSpec _sparkleShape = SparkleShapeSpec.eightPointStar;
|
||||
|
||||
static const Map<String, SparkleShapeSpec> _sparkleChoices =
|
||||
<String, SparkleShapeSpec>{
|
||||
'8-Point Star': SparkleShapeSpec.eightPointStar,
|
||||
'5-Point Star': SparkleShapeSpec.fivePointStar,
|
||||
'Rectangle': SparkleShapeSpec.rectangle,
|
||||
'Diamond': SparkleShapeSpec.diamond,
|
||||
'Hexagon': SparkleShapeSpec.hexagon,
|
||||
'Random Polygon': SparkleShapeSpec.randomPolygon,
|
||||
'Confetti': SparkleShapeSpec.confetti,
|
||||
};
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_sensorController = ShinyController(useSensor: true);
|
||||
_externalTiltController = StreamController<Offset>.broadcast();
|
||||
_overrideController =
|
||||
ShinyController(tiltStream: _externalTiltController.stream);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_sensorController.dispose();
|
||||
_overrideController.dispose();
|
||||
_externalTiltController.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFF0D121A),
|
||||
appBar: AppBar(
|
||||
title: const Text('holo_shiny example'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
const Text('Shiny on Any Widget'),
|
||||
const SizedBox(height: 8),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: 320,
|
||||
height: 120,
|
||||
child: Shiny(
|
||||
controller: _sensorController,
|
||||
style: _style,
|
||||
sparkleShape: _sparkleShape,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF18263E),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
),
|
||||
child: const Row(
|
||||
children: <Widget>[
|
||||
Icon(Icons.auto_awesome, color: Colors.white),
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'This can wrap any widget, including app chrome.',
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text('ShinyCard (shape + rotation + shine)'),
|
||||
const SizedBox(height: 8),
|
||||
Center(
|
||||
child: ShinyCard(
|
||||
controller: _sensorController,
|
||||
style: _style,
|
||||
sparkleShape: _sparkleShape,
|
||||
background: const _DemoCardBackground(),
|
||||
foreground: const _RareBadge(),
|
||||
prismatic: _prismatic,
|
||||
sparkle: _sparkle,
|
||||
specular: _specular,
|
||||
diffraction: _diffraction,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_StylePicker(
|
||||
selectedStyle: _style,
|
||||
onChanged: (HolographStyle style) {
|
||||
setState(() {
|
||||
_style = style;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_SparkleShapePicker(
|
||||
selectedShape: _sparkleShape,
|
||||
choices: _sparkleChoices,
|
||||
onChanged: (SparkleShapeSpec shape) {
|
||||
setState(() {
|
||||
_sparkleShape = shape;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_LabeledSlider('Prismatic', _prismatic, (double value) {
|
||||
setState(() {
|
||||
_prismatic = value;
|
||||
});
|
||||
}),
|
||||
_LabeledSlider('Sparkle', _sparkle, (double value) {
|
||||
setState(() {
|
||||
_sparkle = value;
|
||||
});
|
||||
}),
|
||||
_LabeledSlider('Specular', _specular, (double value) {
|
||||
setState(() {
|
||||
_specular = value;
|
||||
});
|
||||
}),
|
||||
_LabeledSlider('Diffraction', _diffraction, (double value) {
|
||||
setState(() {
|
||||
_diffraction = value;
|
||||
});
|
||||
}),
|
||||
const SizedBox(height: 24),
|
||||
const Text('External Tilt Stream + Custom Shape (card)'),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: () =>
|
||||
_externalTiltController.add(const Offset(0.7, 0.0)),
|
||||
child: const Text('Tilt Right'),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: () =>
|
||||
_externalTiltController.add(const Offset(-0.7, 0.0)),
|
||||
child: const Text('Tilt Left'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Center(
|
||||
child: ShinyCard(
|
||||
controller: _overrideController,
|
||||
style: _style,
|
||||
sparkleShape: _sparkleShape,
|
||||
shape: const StadiumBorder(),
|
||||
background: Container(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: <Color>[Color(0xFF1A2A44), Color(0xFF15263D)],
|
||||
),
|
||||
),
|
||||
),
|
||||
foreground: const Center(
|
||||
child: Text(
|
||||
'EXTERNAL STREAM',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LabeledSlider extends StatelessWidget {
|
||||
const _LabeledSlider(this.label, this.value, this.onChanged);
|
||||
|
||||
final String label;
|
||||
final double value;
|
||||
final ValueChanged<double> onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(label),
|
||||
Slider(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _StylePicker extends StatelessWidget {
|
||||
const _StylePicker({
|
||||
required this.selectedStyle,
|
||||
required this.onChanged,
|
||||
});
|
||||
|
||||
final HolographStyle selectedStyle;
|
||||
final ValueChanged<HolographStyle> onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const Text('Style'),
|
||||
const SizedBox(height: 6),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: HolographStyle.values.map((HolographStyle style) {
|
||||
return ChoiceChip(
|
||||
label: Text(_styleLabel(style)),
|
||||
selected: selectedStyle == style,
|
||||
onSelected: (bool selected) {
|
||||
if (!selected) {
|
||||
return;
|
||||
}
|
||||
onChanged(style);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
String _styleLabel(HolographStyle style) {
|
||||
switch (style) {
|
||||
case HolographStyle.holographicSilver:
|
||||
return 'Holographic Silver';
|
||||
case HolographStyle.crackedIce:
|
||||
return 'Cracked Ice';
|
||||
case HolographStyle.silverMosaic:
|
||||
return 'Silver Mosaic';
|
||||
case HolographStyle.superGoldVinyl:
|
||||
return 'Super Gold Vinyl';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _SparkleShapePicker extends StatelessWidget {
|
||||
const _SparkleShapePicker({
|
||||
required this.selectedShape,
|
||||
required this.choices,
|
||||
required this.onChanged,
|
||||
});
|
||||
|
||||
final SparkleShapeSpec selectedShape;
|
||||
final Map<String, SparkleShapeSpec> choices;
|
||||
final ValueChanged<SparkleShapeSpec> onChanged;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const Text('Sparkle Shape'),
|
||||
const SizedBox(height: 6),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children:
|
||||
choices.entries.map((MapEntry<String, SparkleShapeSpec> entry) {
|
||||
return ChoiceChip(
|
||||
label: Text(entry.key),
|
||||
selected: selectedShape == entry.value,
|
||||
onSelected: (bool selected) {
|
||||
if (!selected) {
|
||||
return;
|
||||
}
|
||||
onChanged(entry.value);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DemoCardBackground extends StatelessWidget {
|
||||
const _DemoCardBackground();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
'assets/pokemon.png',
|
||||
fit: BoxFit.cover,
|
||||
alignment: Alignment.topCenter,
|
||||
errorBuilder:
|
||||
(BuildContext context, Object error, StackTrace? stackTrace) {
|
||||
return Container(
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: <Color>[Color(0xFF2D1B1B), Color(0xFF120D18)],
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: const Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: Text(
|
||||
'Demo Card',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: <Color>[
|
||||
Colors.black.withValues(alpha: 0.10),
|
||||
Colors.black.withValues(alpha: 0.22),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RareBadge extends StatelessWidget {
|
||||
const _RareBadge();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(12),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(99),
|
||||
),
|
||||
child: const Text(
|
||||
'RARE',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w800,
|
||||
letterSpacing: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user