如何使我的3D透视PageView在我点击时导航到特定页面?

huangapple go评论60阅读模式
英文:

How to make my 3D Perspective PageView to navigate to specific page when I click?

问题

I'm trying to make my 3D Perspective PageView to navigate to specific page when I click the center Image. I followed this tutorial on youtube (https://www.youtube.com/watch?v=o-98lLOxohw) and customized it on my own project.

This is how my project looks like right now when I run it.

如何使我的3D透视PageView在我点击时导航到特定页面?

And this is my home.dart file.
I'll include my github repository link if you want to have a better look.
https://github.com/loupdaniel/Second-Life_Mobile

import 'package:flutter/material.dart';
import 'package:secondlife_mobile/PageViewHolder.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  // ... (code continues)
}

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),
            ),
          ),
        ),
      ],
    );
  }
}
英文:

I'm trying to make my 3D Perspective PageView to navigate to specific page when I click the center Image. I followed this tutorial on youtube (https://www.youtube.com/watch?v=o-98lLOxohw) and customized it on my own project.

This is how my project looks like right now when I run it.

如何使我的3D透视PageView在我点击时导航到特定页面?

And this is my home.dart file.
I'll include my github repository link if you want to have a better look.
https://github.com/loupdaniel/Second-Life_Mobile

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

import &#39;package:flutter/material.dart&#39;;
import &#39;package:secondlife_mobile/PageViewHolder.dart&#39;;
import &#39;package:provider/provider.dart&#39;;
import &#39;package:url_launcher/url_launcher.dart&#39;;
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State&lt;MyHomePage&gt; createState() =&gt; _MyHomePageState();
}
class _MyHomePageState extends State&lt;MyHomePage&gt; {
final PageStorageBucket bucket = PageStorageBucket();
late PageViewHolder holder;
late PageController _controller;
double fraction =
0.57; // By using this fraction, we&#39;re telling the PageView to show the 50% of the previous and the next page area along with the main page
Future&lt;void&gt; _launchURL(String url) async {
final Uri uri = Uri(scheme: &quot;https&quot;, host: url);
if (!await launchUrl(
uri,
mode: LaunchMode.inAppWebView,
)) {
throw &#39;Can not launch url&#39;;
}
}
@override
void initState() {
super.initState();
holder = PageViewHolder(value: 2.0);
_controller = PageController(initialPage: 2, viewportFraction: fraction);
_controller.addListener(() {
holder.setValue(_controller.page);
});
}
int index = 1;
int currentIndex = 0;
final PageController controller = PageController();
List&lt;String&gt; images = [
&quot;https://i.ytimg.com/vi/PWADVtWyE9Q/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLDcneFqOxHd28mCncQxT3jOErmk9Q&quot;,
&quot;https://i.ytimg.com/vi/djzDWMy1z7k/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLCHwD_IA2ERzpZVxNvxCEOGr4fyTw&quot;,
&quot;https://i.ytimg.com/vi/n8OxyKNBsuQ/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAtW45_cxRqEWfUVw19UMts_9Q0lQ&quot;,
&quot;https://i.ytimg.com/vi/7bDFD_WcU9I/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAsgAH6VRN4w0HKtVc528WA5QSZ2w&quot;,
&quot;https://i.ytimg.com/vi/_ABk7TmjnVk/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAxCeIml0HUbjJ3igi1FFe1esdwdg&quot;,
&quot;https://i.ytimg.com/vi/-8m0XFea2zE/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLDBOBRGDJeDjhT1HbRobSN2Tp6hMA&quot;,
&quot;https://i.ytimg.com/vi/mXLS2IzZSdg/hq720.jpg?sqp=-oaymwE2CNAFEJQDSFXyq4qpAygIARUAAIhCGAFwAcABBvABAfgB_gmAAtAFigIMCAAQARhdIFsoZTAP&amp;rs=AOn4CLDS13MjaIBxjjhccIktpAb0azBG9g&quot;,
&quot;https://i.ytimg.com/vi/HuzlYAMwwJY/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLCmfMS9RENZuIJMQ8k2cf6MbHIpug&quot;,
&quot;https://i.ytimg.com/vi/-nt_u4vo-DI/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAgUinltWhU-qqmgc_JroDLPt3OEg&quot;,
&quot;https://i.ytimg.com/vi/tqtZIyN_Alg/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLD4woxvyiNXgmSile7PLz7uoRPQOQ&quot;,
];
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: const Color.fromARGB(255, 223, 234, 244),
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
title: const Text(&#39;AppBar&#39;),
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 30,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
&#39;Playlist for you&#39;,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
),
const SizedBox(height: 15),
Container(
child: Center(
child: AspectRatio(
aspectRatio: 1,
child: ChangeNotifierProvider&lt;PageViewHolder&gt;.value(
value: holder,
child: PageView.builder(
controller: _controller,
itemCount: 4,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return MyPage(
number: index.toDouble(),
fraction: fraction,
);
},
),
),
),
),
),
Transform.translate(
offset: const Offset(0, -85),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
&#39;Watch videos&#39;,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
//https://www.youtube.com/watch?v=7a_RXHOkJLM
//https://github.com/Programmer9211/Flutter-Carousel-Slider/blob/main/lib/main.dart
Transform.translate(
offset: const Offset(0, -65),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
alignment: Alignment.center,
child: SizedBox(
height: 162,
width: 335,
child: PageView.builder(
controller: controller,
onPageChanged: (index) {
setState(() {
currentIndex = index % images.length;
});
},
itemBuilder: (context, index) {
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 35),
child: SizedBox(
height: 100,
width: 400,
child: Image.network(
images[index % images.length],
fit: BoxFit.fill,
),
),
);
},
),
),
),
],
),
),
////Your Playlist of the week text
Transform.translate(
offset: const Offset(0, -30),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
&#39;Playlist of the week&#39;,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
),
Transform.translate(
offset: const Offset(0, -15),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 35),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 150,
child: ListView(
scrollDirection: Axis.horizontal,
children: &lt;Widget&gt;[
GestureDetector(
onTap: () {
_launchURL(&quot;www.google.com&quot;);
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
&#39;assets/images/album1.jpg&#39;,
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL(&quot;www.google.com&quot;);
},
child: SizedBox(
height: 180.0,
width: 220.0,
child: Image.asset(
&#39;assets/images/album2.jpg&#39;,
height: 180.0,
width: 220.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL(&quot;www.google.com&quot;);
},
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
&#39;assets/images/album3.jpg&#39;,
height: 160.0,
width: 200.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL(&quot;www.google.com&quot;);
},
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
&#39;assets/images/album4.jpg&#39;,
height: 160.0,
width: 200.0,
),
),
),
const SizedBox(
width: 30,
),
GestureDetector(
onTap: () {
_launchURL(&quot;www.google.com&quot;);
},
child: SizedBox(
height: 160.0,
width: 200.0,
child: Image.asset(
&#39;assets/images/album5.jpg&#39;,
height: 160.0,
width: 200.0,
),
),
),
],
),
),
],
),
),
),
),
],
),
),
),
),
);
}
}
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&lt;PageViewHolder&gt;(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(
&quot;assets/images/image_${number.toInt() + 1}.jpg&quot;,
fit: BoxFit.fill),
),
),
),
],
);
}
}

<!-- end snippet -->

答案1

得分: 1

以下是您要翻译的内容:

你可以使用`GestureDetector`或`InkWell`小部件来处理任何小部件上的`onTap`或触摸功能。在您的代码中添加这两个小部件之一。

示例代码: -

    GestureDetector(
      onTap: (() {
    	Navigator.push(
    	  context,
    	  MaterialPageRoute(
    		  builder: (context) => const SecondPage()), // 跳转到SecondPage
    	);
      }),
      child: 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,
    			  );
    			},
    		  ),
    		),
    	  ),
    	),
      ),
    ),

完整代码: -

    import 'package:flutter/material.dart';
    import 'package:secondlife_mobile/PageViewHolder.dart';
    import 'package:provider/provider.dart';
    import 'package:url_launcher/url_launcher.dart';
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key});
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      final PageStorageBucket bucket = PageStorageBucket();
    
      late PageViewHolder holder;
      late PageController _controller;
      double fraction =
          0.57; // 通过使用这个分数,我们告诉PageView显示前一个页面和下一个页面的50%区域,以及主页面
    
      Future<void> _launchURL(String url) async {
        final Uri uri = Uri(scheme: "https", host: url);
        if (!await launchUrl(
          uri,
          mode: LaunchMode.inAppWebView,
        )) {
          throw '无法启动网址';
        }
      }
    
      @override
      void initState() {
        super.initState();
        holder = PageViewHolder(value: 2.0);
        _controller = PageController(initialPage: 2, viewportFraction: fraction);
        _controller.addListener(() {
          holder.setValue(_controller.page);
        });
      }
    
      int index = 1;
    
      int currentIndex = 0;
    
      final PageController controller = PageController();
    
      List<String> images = [
        "https://i.ytimg.com/vi/PWADVtWyE9Q/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDcneFqOxHd28mCncQxT3jOErmk9Q",
        "https://i.ytimg.com/vi/djzDWMy1z7k/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCHwD_IA2ERzpZVxNvxCEOGr4fyTw",
        "https://i.ytimg.com/vi/n8OxyKNBsuQ/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAtW45_cxRqEWfUVw19UMts_9Q0lQ",
        "https://i.ytimg.com/vi/7bDFD_WcU9I/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAsgAH6VRN4w0HKtVc528WA5QSZ2w",
        "https://i.ytimg.com/vi/_ABk7TmjnVk/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAxCeIml0HUbjJ3igi1FFe1esdwdg",
        "https://i.ytimg.com/vi/-8m0XFea2zE/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLDBOBRGDJeDjhT1HbRobSN2Tp6hMA",
        "https://i.ytimg.com/vi/mXLS2IzZSdg/hq720.jpg?sqp=-oaymwE2CNAFEJQDSFXyq4qpAygIARUAAIhCGAFwAcABBvABAfgB_gmAAtAFigIMCAAQARhdIFsoZTAP&rs=AOn4CLDS13MjaIBxjjhccIktpAb0azBG9g",
        "https://i.ytimg.com/vi/HuzlYAMwwJY/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCmfMS9RENZuIJMQ8k2cf6MbHIpug",
        "https://i.ytimg.com/vi/-nt_u4vo-DI/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLAgUinltWhU-qqmgc_JroDLPt3OEg",
        "https://i.ytimg.com/vi/tqtZIyN_Alg/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLD4woxvyiNXgmSile7PLz7uoRPQOQ",
      ];

      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            backgroundColor: const Color.fromARGB(255, 223, 234, 244),
            appBar: AppBar(
              backgroundColor: Colors.transparent,
              centerTitle: true,
              title: const Text('AppBar'),
            ),
            body: SingleChildScrollView(
              child: SizedBox(
                height: MediaQuery.of(context).size.height,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const SizedBox(
                      height: 30,
                    ),
                    const Padding

<details>
<summary>英文:</summary>

You can use `GestureDetector` or `InkWell` Widget to handle `onTap` or touch function on any Widget. Add either of this Widget in your code 

Sample Code : - 

    GestureDetector(
      onTap: (() {
    	Navigator.push(
    	  context,
    	  MaterialPageRoute(
    		  builder: (context) =&gt; const SecondPage()), // Navigate to SecondPage
    	);
      }),
      child: Container(
    	child: Center(
    	  child: AspectRatio(
    		aspectRatio: 1,
    		child: ChangeNotifierProvider&lt;PageViewHolder&gt;.value(
    		  value: holder,
    		  child: PageView.builder(
    			controller: _controller,
    			itemCount: 4,
    			physics: const BouncingScrollPhysics(),
    			itemBuilder: (context, index) {
    			  return MyPage(
    				number: index.toDouble(),
    				fraction: fraction,
    			  );
    			},
    		  ),
    		),
    	  ),
    	),
      ),
    ),

Full Code : -

    import &#39;package:flutter/material.dart&#39;;
    import &#39;package:secondlife_mobile/PageViewHolder.dart&#39;;
    import &#39;package:provider/provider.dart&#39;;
    import &#39;package:url_launcher/url_launcher.dart&#39;;
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key});
    
      @override
      State&lt;MyHomePage&gt; createState() =&gt; _MyHomePageState();
    }
    
    class _MyHomePageState extends State&lt;MyHomePage&gt; {
      final PageStorageBucket bucket = PageStorageBucket();
    
      late PageViewHolder holder;
      late PageController _controller;
      double fraction =
          0.57; // By using this fraction, we&#39;re telling the PageView to show the 50% of the previous and the next page area along with the main page
    
      Future&lt;void&gt; _launchURL(String url) async {
        final Uri uri = Uri(scheme: &quot;https&quot;, host: url);
        if (!await launchUrl(
          uri,
          mode: LaunchMode.inAppWebView,
        )) {
          throw &#39;Can not launch url&#39;;
        }
      }
    
      @override
      void initState() {
        super.initState();
        holder = PageViewHolder(value: 2.0);
        _controller = PageController(initialPage: 2, viewportFraction: fraction);
        _controller.addListener(() {
          holder.setValue(_controller.page);
        });
      }
    
      int index = 1;
    
      int currentIndex = 0;
    
      final PageController controller = PageController();
    
      List&lt;String&gt; images = [
        &quot;https://i.ytimg.com/vi/PWADVtWyE9Q/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLDcneFqOxHd28mCncQxT3jOErmk9Q&quot;,
        &quot;https://i.ytimg.com/vi/djzDWMy1z7k/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLCHwD_IA2ERzpZVxNvxCEOGr4fyTw&quot;,
        &quot;https://i.ytimg.com/vi/n8OxyKNBsuQ/hqdefault.jpg?sqp=-oaymwEcCOADEI4CSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAtW45_cxRqEWfUVw19UMts_9Q0lQ&quot;,
        &quot;https://i.ytimg.com/vi/7bDFD_WcU9I/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAsgAH6VRN4w0HKtVc528WA5QSZ2w&quot;,
        &quot;https://i.ytimg.com/vi/_ABk7TmjnVk/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAxCeIml0HUbjJ3igi1FFe1esdwdg&quot;,
        &quot;https://i.ytimg.com/vi/-8m0XFea2zE/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLDBOBRGDJeDjhT1HbRobSN2Tp6hMA&quot;,
        &quot;https://i.ytimg.com/vi/mXLS2IzZSdg/hq720.jpg?sqp=-oaymwE2CNAFEJQDSFXyq4qpAygIARUAAIhCGAFwAcABBvABAfgB_gmAAtAFigIMCAAQARhdIFsoZTAP&amp;rs=AOn4CLDS13MjaIBxjjhccIktpAb0azBG9g&quot;,
        &quot;https://i.ytimg.com/vi/HuzlYAMwwJY/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLCmfMS9RENZuIJMQ8k2cf6MbHIpug&quot;,
        &quot;https://i.ytimg.com/vi/-nt_u4vo-DI/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLAgUinltWhU-qqmgc_JroDLPt3OEg&quot;,
        &quot;https://i.ytimg.com/vi/tqtZIyN_Alg/hq720.jpg?sqp=-oaymwEcCNAFEJQDSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&amp;rs=AOn4CLD4woxvyiNXgmSile7PLz7uoRPQOQ&quot;,
      ];
    
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            backgroundColor: const Color.fromARGB(255, 223, 234, 244),
            appBar: AppBar(
              backgroundColor: Colors.transparent,
              centerTitle: true,
              title: const Text(&#39;AppBar&#39;),
            ),
            body: SingleChildScrollView(
              child: SizedBox(
                height: MediaQuery.of(context).size.height,
                child: Column(
                  mainAxisSize: MainAxisSize.min,
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const SizedBox(
                      height: 30,
                    ),
                    const Padding(
                      padding: EdgeInsets.symmetric(horizontal: 35),
                      child: Text(
                        &#39;Playlist for you&#39;,
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.w400,
                        ),
                      ),
                    ),
                    const SizedBox(height: 15),
                    GestureDetector(
                      onTap: (() {
                        Navigator.push(
                          context,
                          MaterialPageRoute(
                              builder: (context) =&gt;
                                  const SecondPage()), // Navigate to SecondPage
                        );
                      }),
                      child: Container(
                        child: Center(
                          child: AspectRatio(
                            aspectRatio: 1,
                            child: ChangeNotifierProvider&lt;PageViewHolder&gt;.value(
                              value: holder,
                              child: PageView.builder(
                                controller: _controller,
                                itemCount: 4,
                                physics: const BouncingScrollPhysics(),
                                itemBuilder: (context, index) {
                                  return MyPage(
                                    number: index.toDouble(),
                                    fraction: fraction,
                                  );
                                },
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                    Transform.translate(
                      offset: const Offset(0, -85),
                      child: const Padding(
                        padding: EdgeInsets.symmetric(horizontal: 35),
                        child: Text(
                          &#39;Watch videos&#39;,
                          style: TextStyle(
                            fontSize: 17,
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                      ),
                    ),
    
                    //https://www.youtube.com/watch?v=7a_RXHOkJLM
                    //https://github.com/Programmer9211/Flutter-Carousel-Slider/blob/main/lib/main.dart
                    Transform.translate(
                      offset: const Offset(0, -65),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          Container(
                            alignment: Alignment.center,
                            child: SizedBox(
                              height: 162,
                              width: 335,
                              child: PageView.builder(
                                controller: controller,
                                onPageChanged: (index) {
                                  setState(() {
                                    currentIndex = index % images.length;
                                  });
                                },
                                itemBuilder: (context, index) {
                                  return Padding(
                                    padding:
                                        const EdgeInsets.symmetric(horizontal: 35),
                                    child: SizedBox(
                                      height: 100,
                                      width: 400,
                                      child: Image.network(
                                        images[index % images.length],
                                        fit: BoxFit.fill,
                                      ),
                                    ),
                                  );
                                },
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                    ////Your Playlist of the week text
                    Transform.translate(
                      offset: const Offset(0, -30),
                      child: const Padding(
                        padding: EdgeInsets.symmetric(horizontal: 35),
                        child: Text(
                          &#39;Playlist of the week&#39;,
                          style: TextStyle(
                            fontSize: 17,
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                      ),
                    ),
                    Transform.translate(
                      offset: const Offset(0, -15),
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 35),
                        child: SingleChildScrollView(
                          child: Column(
                            children: [
                              SizedBox(
                                height: 150,
                                child: ListView(
                                  scrollDirection: Axis.horizontal,
                                  children: &lt;Widget&gt;[
                                    GestureDetector(
                                      onTap: () {
                                        _launchURL(&quot;www.google.com&quot;);
                                      },
                                      child: SizedBox(
                                        height: 180.0,
                                        width: 220.0,
                                        child: Image.asset(
                                          &#39;assets/images/album1.jpg&#39;,
                                          height: 180.0,
                                          width: 220.0,
                                        ),
                                      ),
                                    ),
                                    const SizedBox(
                                      width: 30,
                                    ),
                                    GestureDetector(
                                      onTap: () {
                                        _launchURL(&quot;www.google.com&quot;);
                                      },
                                      child: SizedBox(
                                        height: 180.0,
                                        width: 220.0,
                                        child: Image.asset(
                                          &#39;assets/images/album2.jpg&#39;,
                                          height: 180.0,
                                          width: 220.0,
                                        ),
                                      ),
                                    ),
                                    const SizedBox(
                                      width: 30,
                                    ),
                                    GestureDetector(
                                      onTap: () {
                                        _launchURL(&quot;www.google.com&quot;);
                                      },
                                      child: SizedBox(
                                        height: 160.0,
                                        width: 200.0,
                                        child: Image.asset(
                                          &#39;assets/images/album3.jpg&#39;,
                                          height: 160.0,
                                          width: 200.0,
                                        ),
                                      ),
                                    ),
                                    const SizedBox(
                                      width: 30,
                                    ),
                                    GestureDetector(
                                      onTap: () {
                                        _launchURL(&quot;www.google.com&quot;);
                                      },
                                      child: SizedBox(
                                        height: 160.0,
                                        width: 200.0,
                                        child: Image.asset(
                                          &#39;assets/images/album4.jpg&#39;,
                                          height: 160.0,
                                          width: 200.0,
                                        ),
                                      ),
                                    ),
                                    const SizedBox(
                                      width: 30,
                                    ),
                                    GestureDetector(
                                      onTap: () {
                                        _launchURL(&quot;www.google.com&quot;);
                                      },
                                      child: SizedBox(
                                        height: 160.0,
                                        width: 200.0,
                                        child: Image.asset(
                                          &#39;assets/images/album5.jpg&#39;,
                                          height: 160.0,
                                          width: 200.0,
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        );
      }
    }
    
    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&lt;PageViewHolder&gt;(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(
                      &quot;assets/images/image_${number.toInt() + 1}.jpg&quot;,
                      fit: BoxFit.fill),
                ),
              ),
            ),
          ],
        );
      }
    }




</details>



huangapple
  • 本文由 发表于 2023年2月14日 02:12:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439721.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定