Flutter炫酷卡片效果插件radiant_card的使用
Flutter炫酷卡片效果插件radiant_card的使用
radiant_card
本应用展示了Flutter自定义着色器功能。通过将Phong着色程序应用于GlossyCard小部件来模仿行为。
注意:着色器仅在Android/iOS以及可能的桌面操作系统上有效。
完整示例Demo
以下是一个完整的示例代码,展示了如何使用radiant_card
插件来创建炫酷的卡片效果。
import 'package:flutter/material.dart';
import 'package:marquee/marquee.dart';
import 'package:radiant_card/radiant_card.dart';
import 'package:vector_math/vector_math.dart' hide Colors;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const _widthInCards = 1;
static const _heightInCards = 1;
static const _viewportWidth = 1;
static const _gridViewPadding = 16.0;
static const _cardSpacing = 8.0;
static const _cardAspectRatio = 711.0 / 990.0;
final _controller = ScrollController();
double _scrollPosition = 0.0;
@override
void initState() {
super.initState();
_controller.addListener(() {
_scrollPosition = _controller.offset;
setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('卡片演示'),
),
body: ImageContextWidget(
imageFiles: const ["assets/images/pikachu.png", "assets/images/mask_1.png"], // todo 可能移除第一张图片
builder: (context, images) {
return LayoutBuilder(builder: (context, constraints) {
final containerWidth = constraints.maxWidth;
final containerHeight = constraints.maxHeight;
final cardWidth = (containerWidth - 2 * _gridViewPadding - (_widthInCards - 1) * _cardSpacing) / _widthInCards;
final cardHeight = cardWidth / _cardAspectRatio;
return GridView.count(
padding: const EdgeInsets.all(_gridViewPadding),
crossAxisCount: _widthInCards,
crossAxisSpacing: _cardSpacing,
mainAxisSpacing: _cardSpacing,
childAspectRatio: _cardAspectRatio,
controller: _controller,
children: List.generate(
_widthInCards * _heightInCards,
(index) {
final i = index % _widthInCards;
final j = index ~/ _widthInCards;
final cardCenterContainerXCoord = _gridViewPadding + i * (cardWidth + _cardSpacing) + cardWidth / 2 - containerWidth / 2;
final cardCenterContainerYCoord = _gridViewPadding + j * (cardHeight + _cardSpacing) + cardHeight / 2 - containerHeight / 2;
final cardCenterWorldXCoord = cardCenterContainerXCoord / containerWidth * _viewportWidth;
final cardCenterWorldYCoord = (cardCenterContainerYCoord - _scrollPosition) * _viewportWidth / containerWidth;
return WidgetToImageBuilder(
child: const AttaboyWidget(),
builder: (context, widgetImage) => widgetImage == null
? const SizedBox.shrink()
: RotatableShadedCard(
mainTexture: widgetImage,
mask: images[1],
centerPos: Vector3(cardCenterWorldXCoord, cardCenterWorldYCoord, 0),
worldSize: Size(cardWidth / containerWidth * _viewportWidth, cardHeight / containerWidth * _viewportWidth),
),
);
},
),
);
});
},
emptyBuilder: (context) => const SizedBox.shrink(),
),
backgroundColor: Colors.white,
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: () {
setState(() {});
},
),
);
}
}
class AttaboyWidget extends StatelessWidget {
const AttaboyWidget({
super.key,
});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue,
alignment: Alignment.center,
child: Stack(
fit: StackFit.expand,
children: [
Image.asset(
'assets/images/den.jpg', // TODO 确保此图像存在
fit: BoxFit.cover,
),
Positioned(
bottom: 80,
left: 0,
right: 0,
child: Container(
color: Colors.black,
height: 48,
child: Marquee(
text: "完美地保持住了",
crossAxisAlignment: CrossAxisAlignment.center,
style: const TextStyle(fontSize: 24, color: Colors.white, fontWeight: FontWeight.bold),
blankSpace: 32.0,
),
),
),
],
),
);
}
}
说明
-
导入必要的库:
import 'package:flutter/material.dart'; import 'package:marquee/marquee.dart'; import 'package:radiant_card/radiant_card.dart'; import 'package:vector_math/vector_math.dart' hide Colors;
-
初始化应用:
void main() { runApp(const MyApp()); }
-
主应用类:
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData(), home: const MyHomePage(), ); } }
-
主页状态类:
class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { static const _widthInCards = 1; static const _heightInCards = 1; static const _viewportWidth = 1; static const _gridViewPadding = 16.0; static const _cardSpacing = 8.0; static const _cardAspectRatio = 711.0 / 990.0; final _controller = ScrollController(); double _scrollPosition = 0.0; @override void initState() { super.initState(); _controller.addListener(() { _scrollPosition = _controller.offset; setState(() {}); }); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('卡片演示'), ), body: ImageContextWidget( imageFiles: const ["assets/images/pikachu.png", "assets/images/mask_1.png"], builder: (context, images) { return LayoutBuilder(builder: (context, constraints) { final containerWidth = constraints.maxWidth; final containerHeight = constraints.maxHeight; final cardWidth = (containerWidth - 2 * _gridViewPadding - (_widthInCards - 1) * _cardSpacing) / _widthInCards; final cardHeight = cardWidth / _cardAspectRatio; return GridView.count( padding: const EdgeInsets.all(_gridViewPadding), crossAxisCount: _widthInCards, crossAxisSpacing: _cardSpacing, mainAxisSpacing: _cardSpacing, childAspectRatio: _cardAspectRatio, controller: _controller, children: List.generate( _widthInCards * _heightInCards, (index) { final i = index % _widthInCards; final j = index ~/ _widthInCards; final cardCenterContainerXCoord = _gridViewPadding + i * (cardWidth + _cardSpacing) + cardWidth / 2 - containerWidth / 2; final cardCenterContainerYCoord = _gridViewPadding + j * (cardHeight + _cardSpacing) + cardHeight / 2 - containerHeight / 2; final cardCenterWorldXCoord = cardCenterContainerXCoord / containerWidth * _viewportWidth; final cardCenterWorldYCoord = (cardCenterContainerYCoord - _scrollPosition) * _viewportWidth / containerWidth; return WidgetToImageBuilder( child: const AttaboyWidget(), builder: (context, widgetImage) => widgetImage == null ? const SizedBox.shrink() : RotatableShadedCard( mainTexture: widgetImage, mask: images[1], centerPos: Vector3(cardCenterWorldXCoord, cardCenterWorldYCoord, 0), worldSize: Size(cardWidth / containerWidth * _viewportWidth, cardHeight / containerWidth * _viewportWidth), ), ); }, ), ); }); }, emptyBuilder: (context) => const SizedBox.shrink(), ), backgroundColor: Colors.white, floatingActionButton: FloatingActionButton( child: const Icon(Icons.refresh), onPressed: () { setState(() {}); }, ), ); } }
-
卡片内容组件:
class AttaboyWidget extends StatelessWidget { const AttaboyWidget({ super.key, }); @override Widget build(BuildContext context) { return Container( color: Colors.blue, alignment: Alignment.center, child: Stack( fit: StackFit.expand, children: [ Image.asset( 'assets/images/den.jpg', fit: BoxFit.cover, ), Positioned( bottom: 80, left: 0, right: 0, child: Container( color: Colors.black, height: 48, child: Marquee( text: "完美地保持住了", crossAxisAlignment: CrossAxisAlignment.center, style: const TextStyle(fontSize: 24, color: Colors.white, fontWeight: FontWeight.bold), blankSpace: 32.0, ), ), ), ], ), ); } }
更多关于Flutter炫酷卡片效果插件radiant_card的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter炫酷卡片效果插件radiant_card的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
radiant_card
是一个用于 Flutter 的插件,可以帮助开发者轻松实现炫酷的卡片效果。这个插件提供了多种卡片样式和动画效果,可以让你的应用界面更加吸引人。以下是如何使用 radiant_card
插件的基本步骤。
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 radiant_card
插件的依赖:
dependencies:
flutter:
sdk: flutter
radiant_card: ^1.0.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 导入插件
在你的 Dart 文件中导入 radiant_card
插件:
import 'package:radiant_card/radiant_card.dart';
3. 使用 RadiantCard
RadiantCard
是 radiant_card
插件提供的核心组件。你可以通过设置不同的属性来自定义卡片的外观和行为。
基本用法
RadiantCard(
width: 200,
height: 200,
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
child: Center(
child: Text(
'Hello, RadiantCard!',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
)
添加阴影效果
RadiantCard(
width: 200,
height: 200,
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
elevation: 10, // 阴影效果
child: Center(
child: Text(
'Hello, RadiantCard!',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
)
添加渐变背景
RadiantCard(
width: 200,
height: 200,
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(10),
child: Center(
child: Text(
'Hello, RadiantCard!',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
)
添加动画效果
RadiantCard(
width: 200,
height: 200,
color: Colors.blue,
borderRadius: BorderRadius.circular(10),
animationDuration: Duration(seconds: 1), // 动画持续时间
animationCurve: Curves.easeInOut, // 动画曲线
child: Center(
child: Text(
'Hello, RadiantCard!',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
)
4. 自定义更多属性
RadiantCard
提供了多种属性供你自定义,包括但不限于:
width
和height
:卡片的宽度和高度。color
:卡片的背景颜色。gradient
:卡片的渐变背景。borderRadius
:卡片的圆角半径。elevation
:卡片的阴影效果。animationDuration
:动画持续时间。animationCurve
:动画曲线。child
:卡片的内容。
5. 完整示例
以下是一个完整的示例,展示了如何使用 RadiantCard
创建一个带有渐变背景和动画效果的卡片:
import 'package:flutter/material.dart';
import 'package:radiant_card/radiant_card.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('RadiantCard Example'),
),
body: Center(
child: RadiantCard(
width: 200,
height: 200,
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(10),
animationDuration: Duration(seconds: 1),
animationCurve: Curves.easeInOut,
child: Center(
child: Text(
'Hello, RadiantCard!',
style: TextStyle(color: Colors.white, fontSize: 20),
),
),
),
),
),
);
}
}