Flutter développement pratique quotidienne - épicerie petit chat (nouvelle page d'accueil, page de publicité et page coulissante)

Des amis qui élèvent des chatons viennent dans ma boutique !

Flutter Development Daily Exercises - Kitty Grocery Store (New Animation and Jump Douyin)_workersJiaDa's Blog-CSDN Blog URL Launcher est un plug-in Flutter qui permet à votre application de lancer des navigateurs Web, des applications cartographiques et des programmes d'applications de numérotation, des applications de messagerie, etc. Définissez l'identifiant de chaque image et utilisez l'identifiant comme identifiant du composant 'Hero'. L'identifiant ne peut pas être répété, sinon une erreur sera signalée et il doit être le même dans les deux pages. Ajout d'une animation d'invite de zoom au texte de la liste, cela semble très intéressant et il existe d'autres effets que vous pouvez essayer vous-même. L'exercice précédent a ajouté une page de détails, puis est passé à la page de détails de l'utilisateur Douyin de la page tierce. L'animation de Hero est ajoutée à la page de détails du saut et les éléments partagés sont excessifs. https://blog.csdn.net/zxc8890304/article/details/130317615

Le projet d'épicerie pour chats est continuellement mis à jour

Si l'idée de conception de l'APP est modifiée en catpedia, elle ne connaîtra pas le back-end, la source de données capture le paquet et l'enregistre localement

  1. Connectez-vous et inscrivez-vous, ajoutez des informations personnelles au stockage local et modifiez
  2. Version internationalisée
  3. modes jour et nuit 
  4. Suppression d'un article du panier
  5. Processus de paiement de commande à commande
  6. Tri des outils (taille de la police, couleur de la police, couleur du thème, etc.)
  7. Traitement de l'outil de bibliothèque d'images
  8. optimisation de l'interception des pages webview
  9. Optimisation globale des performances
  10. Emballage

sp_util est une belle classe utilitaire

flutter_screenutil

Besoin d'enregistrer la largeur et la hauteur lors de l'utilisation

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(375, 681),
      builder: (BuildContext context, Widget? child) =>  ChangeNotifierProvider(
        create: (context) => CarModel(),
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const StartPage(),
        ),
      ),
    );
  }
}

vue_web_flutter

Ajouter un saut de vue Web 

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebPage extends StatefulWidget {
  final String url;
  final String title;
  const WebPage({super.key, required this.url, required this.title});

  @override
  State<WebPage> createState() => _WebPageState(this.url, this.title);
}

class _WebPageState extends State<WebPage> {
  final String url;
  final String title;

  late final WebViewController controller;

  _WebPageState(this.url, this.title);
  @override
  void initState() {
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onProgress: (int progress) {
            // Update loading bar.
          },
          onPageStarted: (String url) {},
          onPageFinished: (String url) {},
          onWebResourceError: (WebResourceError error) {},
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.startsWith('https://pub.dev/')) {
              return NavigationDecision.prevent;
            }
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(Uri.parse(url));

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Column(
        children: [
          Expanded(
            child: WebViewWidget(controller: controller),
          ),
        ],
      ),
    );
  }
}

Annonces de compte à rebours, utilisez la minuterie pour compter à rebours,

second_index est l'heure définie

Définissez l'heure à modifier par vous-même, ou vous pouvez la modifier côté serveur

import 'dart:async';

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cat_1/pages/intro_page.dart';
import 'package:flutter_cat_1/tools/tools.dart';
import 'package:flutter_cat_1/web/web_page.dart';
import 'package:google_fonts/google_fonts.dart';

import '../main.dart';

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

  @override
  State<WelcomePage> createState() => _WelcomePageState();
}

class _WelcomePageState extends State<WelcomePage> {
  int second_index = 3;
  int timeIndex = 0;
  late Timer timer;

  @override
  void initState() {
    super.initState();
    timer = Timer.periodic(
      Duration(milliseconds: 50),
      (sd) {
        setState(() {
          timeIndex += 1;
          if (timeIndex % 20 == 0) {
            second_index -= 1;
          }
        });
        if (timeIndex >= 100) {
          _openMain();
        }
      },
    );
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        alignment: Alignment.center,
        children: <Widget>[
          Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Image.asset(
              "assets/IMG_8050.png",
              fit: BoxFit.cover,
            ),
          ),
          Container(
            alignment: Alignment.bottomRight,
            child: Container(
              width: 50,
              height: 50,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(25),
              ),
              alignment: Alignment.center,
              margin: const EdgeInsets.all(25),
              child: GestureDetector(
                onTap: () {
                  _openMain();
                },
                child: Stack(
                  children: <Widget>[
                    Container(
                      alignment: Alignment.center,
                      child: CircularProgressIndicator(
                        value: timeIndex / 100,
                        strokeWidth: 2,
                      ),
                    ),
                    Container(
                      alignment: Alignment.center,
                      child: Text(
                        "跳过",
                        style: TextStyle(fontSize: 12,color: Colors.white,fontWeight: FontWeight.bold,),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          Container(
            alignment: Alignment.center,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                RichText(
                  text: TextSpan(
                    text: "Flutter开发日常练习",
                    style: GoogleFonts.notoSerif(
                      color: Colors.black,
                      fontSize: 17,
                    ),
                    children: [
                      TextSpan(
                          text: "-小猫咪杂货店",
                          style: GoogleFonts.notoSerif(
                            color: Colors.black,
                            fontSize: 17,
                            // decoration: TextDecoration.underline,
                            // decorationColor: Colors.blue[800],
                          )),
                    ],
                  ),
                  textDirection: TextDirection.ltr,
                ),
                SizedBox(
                  height: 10,
                ),
                RichText(
                  text: TextSpan(
                    text: 'CSDN关注',
                    style: GoogleFonts.notoSerif(
                      fontSize: 17,
                      color: Colors.black,
                    ),
                    children: [
                      TextSpan(
                          text: 'workersJiaDa',
                          style: GoogleFonts.notoSerif(
                            fontSize: 17,
                            color: Colors.blue[800],
                            decoration: TextDecoration.underline,
                            decorationColor: Colors.blue[800],
                            fontWeight: FontWeight.bold,
                          ),
                          recognizer: TapGestureRecognizer()
                            ..onTap = () {
                              timer.cancel();
                              Navigator.of(context)
                                  .push(
                                    MaterialPageRoute(
                                      builder: (context) => WebPage(
                                          url:
                                              "https://blog.csdn.net/zxc8890304",
                                          title: "workersJiaDa的博客"),
                                    ),
                                  )
                                  .then((value) => reGetTimer());
                            }),
                    ],
                  ),
                ),
                SizedBox(
                  height: 10,
                ),
                RichText(
                  text: TextSpan(
                    text: '抖音商城搜索',
                    style: GoogleFonts.notoSerif(
                      color: Colors.black,
                      fontSize: 17,
                    ),
                    children: [
                      TextSpan(
                        text: "早睡早起的猫咪小铺子",
                        style: GoogleFonts.notoSerif(
                          fontSize: 17,
                          color: Colors.blue[800],
                          decoration: TextDecoration.underline,
                          decorationColor: Colors.blue[800],
                          fontWeight: FontWeight.bold,
                        ),
                        recognizer: TapGestureRecognizer()
                          ..onTap = () {
                            // timer.cancel();
                            launchURL('snssdk1128://user/profile/88486395468');
                          },
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  void _openMain() {
    timer.cancel();
    Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
          builder: (context) => const IntroPage(),
        ),
        (route) => false);
  }

  void reGetTimer() {
    timer = Timer.periodic(
      Duration(milliseconds: 50),
      (sd) {
        setState(() {
          timeIndex += 1;
          if (timeIndex % 20 == 0) {
            second_index -= 1;
          }
        });
        if (timeIndex >= 100) {
          _openMain();
        }
      },
    );
  }
}

 Les mots sur la page d'accueil sont

flutter_swiper_plus 

 Très brut, simple pour obtenir l'effet, pour ré-optimiser et modifier

Le jugement de isFirst a été ajouté, et il ne sera affiché que lorsque l'APP est ouvert pour la première fois.

J'ai déjà réalisé des projets internationaux et la demande à l'étranger est

Tant que vous entrez dans la page d'accueil sans cliquer sur ignorer ou entrer dans l'APP , vous entrerez à nouveau dans la page d'accueil chaque fois que vous entrerez dans l'APP

Dans ce cas, les conditions de jugement doivent être révisées.

import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cat_1/welcome/welcome_page.dart';
import 'package:flutter_swiper_plus/flutter_swiper_plus.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:sp_util/sp_util.dart';

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

  @override
  State<StartPage> createState() => _StartPageState();
}

class _StartPageState extends State<StartPage> {
  bool _isLogin = false;
  bool _isFirst = false;
  bool _islastPage = false;
  int pageInt = 1;
  final List _welcomeList = ["welcome_1.png", "welcome_2.png", "welcome_3.png"];

  @override
  void initState() {
    super.initState();
    _isFirst = SpUtil.getBool("first")!;

    if (_isFirst) {
      String? tokenStr = SpUtil.getString('token');
      _isLogin = (tokenStr == null || tokenStr.isEmpty) ? false : true;
      new Future.delayed(Duration(seconds: 0), () {
        Navigator.of(context).pushAndRemoveUntil(
            MaterialPageRoute(
              builder: (context) => WelcomePage(),
            ),
            (route) => false);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return 
    Container(
      color: Colors.white,
      height: ScreenUtil().screenHeight,
      child: Stack(
        children: [
          Swiper(
            itemBuilder: (context, index) {
              return Image.asset(
                "assets/${_welcomeList[index]}",
                fit: BoxFit.cover,
              );
            },
            itemCount: _welcomeList.length,
            loop: false,
            onIndexChanged: (index) {
              pageInt = index + 1;
              if (index == _welcomeList.length - 1) {
                setState(() {
                  _islastPage = true;
                });
              } else {
                setState(() {
                  _islastPage = false;
                });
              }
            },
          ),
          Container(
            width: 100,
            height: 40,
            alignment: Alignment.center,
            margin: EdgeInsets.only(
              left: ScreenUtil().screenWidth / 2 - 50,
              bottom: 40,
              top: ScreenUtil().screenHeight - 80,
              right: ScreenUtil().screenWidth / 2 - 50,
            ),
            child: Text(
              "$pageInt / 3",
              style: const TextStyle(
                  color: Colors.white,
                  fontSize: 30,
                  fontWeight: FontWeight.bold,
                  decoration: TextDecoration.none),
            ),
          ),
          Container(
            width: 100,
            height: 40,

            margin: EdgeInsets.only(
              left: ScreenUtil().screenWidth / 2 + 100,
              bottom: 40,
              top: ScreenUtil().screenHeight - 80,
              // right: ScreenUtil().screenWidth / 2 - 10,
            ),
            // decoration: BoxDecoration(
            //   border: Border.all(color: Colors.blue[900], width: 2),
            //   borderRadius: BorderRadius.circular(8),
            // ),
            child: Center(
              child: TextButton(
                onPressed:() => _jumpWelcome(),
                  // Navigator.push(context, MaterialPageRoute(
                  //   builder: (context) {
                       
                  //   },
                  // ));
              
                child: _islastPage
                    ? Text(
                        "立即进入",
                        style: GoogleFonts.notoSerif(
                            fontSize: 17,
                            color: Colors.blue[700],
                            fontWeight: FontWeight.bold),
                      )
                    : Text(
                        "跳过",
                        style: GoogleFonts.notoSerif(
                            fontSize: 17,
                            color: Colors.blue[700],
                            fontWeight: FontWeight.bold),
                      ),
              ),
            ),
          )
        ],
      ),
    );
  }

  _jumpWelcome() {
    SpUtil.putBool('first',true);
    String? tokenStr = SpUtil.getString("token");
    _isLogin = (tokenStr == null || tokenStr.isEmpty) ? false : true;
        Navigator.of(context).pushAndRemoveUntil(
            MaterialPageRoute(
              builder: (context) => WelcomePage(),
            ),
            (route) => false);
  }
}

 La barre coulissante latérale est également relativement simple

import 'package:flutter/material.dart';
import 'package:flutter_cat_1/welcome/start_page.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';

class DrawerPage extends StatelessWidget {
  const DrawerPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Drawer(
      elevation: 300,
      child: Stack(
        children: <Widget>[
          Column(
            children: <Widget>[
              UserAccountsDrawerHeader(
                accountName: Text("铲屎官铲屎官铲屎官"),
                accountEmail: Text("饲养员饲养员饲养员"),
                currentAccountPicture: CircleAvatar(
                  backgroundImage: AssetImage("assets/IMG_9406.png"),
                ),
                arrowColor: Colors.red,
                onDetailsPressed: () {},
                decoration: BoxDecoration(
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withOpacity(0.5),
                      offset: Offset(10, 10),
                      blurRadius: 45,
                      spreadRadius: 0.0,
                    ),
                  ],
                  image: DecorationImage(
                      image: AssetImage(
                        "assets/IMG_0259.png",
                      ),
                      fit: BoxFit.cover),
                ),
              ),
              Expanded(
                child: ListView(
                  padding: EdgeInsets.symmetric(vertical: 10),
                  children: <Widget>[
                    ListTile(
                      title: Text('个人中心'),
                    ),
                    Divider(),
                    ListTile(
                      title: Text('我的小猫咪'),
                    ),
                    Divider(),
                    ListTile(
                      title: Text("我的订单"),
                    ),
                    Divider(),
                    ListTile(
                      title: Text("关于我们"),
                    ),
                    Divider(),
                  ],
                ),
              ),
            ],
          ),
          Positioned(
            bottom: 20,
            right: 20,
            child: InkWell(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                crossAxisAlignment: CrossAxisAlignment.end,
                children: <Widget>[
                  GestureDetector(
                    onTap: () => Navigator.of(context).pushAndRemoveUntil(
                        MaterialPageRoute(
                      builder: (context) {
                        return StartPage();
                      },
                    ), (route) => false),
                    child: MenuItemButton(
                        child: Column(
                      children: const <Widget>[
                        Icon(
                          Icons.power_settings_new_outlined,
                          color: Colors.red,
                        ),
                        Text(
                          "退出登录",
                          style: TextStyle(
                            color: Colors.red,
                            fontSize: 12,
                          ),
                        ),
                      ],
                    )),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Adresse DEMO 

GitHub - HelloJiada/flutter_cat_1 Contribuez au développement de HelloJiada/flutter_cat_1 en créant un compte sur GitHub. https://github.com/HelloJiada/flutter_cat_1.git

Je suppose que tu aimes

Origine blog.csdn.net/zxc8890304/article/details/130371789
conseillé
Classement