Flutter如何在Transform组件上下添加指定文本?
问题描述
我想实现如图所示的UI,需要在Transform组件上方添加“Playlist for you:”、下方添加“Playlist of the week”文本。尝试用Column组件嵌套Text时,VS Code提示该代码为死代码。以下是我的main.dart代码及相关效果图:
UI设计图

当前效果截图

代码
import 'package:flutter/material.dart'; import 'package:secondlife_mobile/PageViewHolder.dart'; import 'package:provider/provider.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Perspective PageView', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { late PageViewHolder holder; late PageController _controller; double fraction = 0.57; // By using this fraction, we're telling the PageView to show the 50% of the previous and the next page area along with the main page @override void initState() { super.initState(); holder = PageViewHolder(value: 2.0); _controller = PageController(initialPage: 2, viewportFraction: fraction); _controller.addListener(() { holder.setValue(_controller.page); }); } @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( appBar: AppBar( title: const Text("Perspective PageView"), ), body: Container( child: Center( child: AspectRatio( aspectRatio: 1, child: ChangeNotifierProvider<PageViewHolder>.value( value: holder, child: PageView.builder( controller: _controller, itemCount: 4, physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { return MyPage( number: index.toDouble(), fraction: fraction, ); }), ), ), ), ), )); } } class MyPage extends StatelessWidget { final number; final double? fraction; const MyPage({super.key, this.number, this.fraction}); @override Widget build(BuildContext context) { double? value = Provider.of<PageViewHolder>(context).value; double diff = (number - value); // diff is negative = left page // diff is 0 = current page // diff is positive = next page //Matrix for Elements final Matrix4 pvMatrix = Matrix4.identity() ..setEntry(3, 2, 1 / 0.9) //Increasing Scale by 90% ..setEntry(1, 1, fraction!) //Changing Scale Along Y Axis ..setEntry(3, 0, 0.004 * -diff); //Changing Perspective Along X Axis final Matrix4 shadowMatrix = Matrix4.identity() ..setEntry(3, 3, 1 / 1.6) //Increasing Scale by 60% ..setEntry(3, 1, -0.004) //Changing Scale Along Y Axis ..setEntry(3, 0, 0.002 * diff) //Changing Perspective along X Axis ..rotateX(1.309); //Rotating Shadow along X Axis return Stack( fit: StackFit.expand, alignment: FractionalOffset.center, children: [ Transform.translate( offset: const Offset(0.0, -47.5), child: Transform( transform: pvMatrix, alignment: FractionalOffset.center, child: Container( decoration: BoxDecoration(boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), blurRadius: 11.0, spreadRadius: 4.0, offset: const Offset( 13.0, 35.0), // shadow direction: bottom right ) ]), child: Image.asset( "assets/images/image_${number.toInt() + 1}.jpg", fit: BoxFit.fill), ), ), ), ], ); } }
解决方案
死代码提示是因为你把Column嵌套在Stack里的方式错误——Stack的fit: StackFit.expand会让子组件占满空间,Column没有合理的布局约束,导致Text无法正确渲染,IDE判定为死代码。
正确的做法是把Stack作为Column的子项,让文本和带透视效果的图片在垂直方向排列,同时保留原有的PageView交互。
1. 修改MyPage的build方法
@override Widget build(BuildContext context) { double? value = Provider.of<PageViewHolder>(context).value; double diff = (number - value); final Matrix4 pvMatrix = Matrix4.identity() ..setEntry(3, 2, 1 / 0.9) ..setEntry(1, 1, fraction!) ..setEntry(3, 0, 0.004 * -diff); return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // 上方文本 const Text( "Playlist for you:", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 20), // 带透视效果的图片区域 AspectRatio( aspectRatio: 1, child: Stack( fit: StackFit.expand, alignment: FractionalOffset.center, children: [ Transform.translate( offset: const Offset(0.0, -47.5), child: Transform( transform: pvMatrix, alignment: FractionalOffset.center, child: Container( decoration: BoxDecoration(boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.5), blurRadius: 11.0, spreadRadius: 4.0, offset: const Offset(13.0, 35.0), ) ]), child: Image.asset( "assets/images/image_${number.toInt() + 1}.jpg", fit: BoxFit.fill, ), ), ), ), ], ), ), const SizedBox(height: 20), // 下方文本 const Text( "Playlist of the week", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), ], ); }
2. 调整MyHomePage的body布局
原来的外层AspectRatio会限制整体高度,导致文本被挤压,需要移除:
body: Container( padding: const EdgeInsets.symmetric(horizontal: 20), child: Center( child: ChangeNotifierProvider<PageViewHolder>.value( value: holder, child: PageView.builder( controller: _controller, itemCount: 4, physics: const BouncingScrollPhysics(), itemBuilder: (context, index) { return MyPage( number: index.toDouble(), fraction: fraction, ); }, ), ), ), ),
修改后,文本会正确显示在图片上下方,同时保留原有的PageView透视切换效果,也不会出现死代码提示。
内容的提问来源于stack exchange,提问作者loupdaniel
相关产品推荐
相关产品推荐

