Flutter development prática diária - pequena mercearia para gatos (nova página de boas-vindas, página de publicidade e página deslizante)

Amigos que criam gatinhos vêm à minha loja! Pesquisa no shopping Douyin

Flutter Development Daily Exercises - Kitty Grocery Store (New Animation and Jump Douyin)_workersJiaDa's Blog-CSDN Blog URL Launcher é um plug-in do Flutter que permite que seu aplicativo inicie navegadores da Web, aplicativos de mapa e programas de aplicativos de discagem, aplicativos de e-mail, etc. Defina o id de cada imagem, e use o id como identificação do componente 'Herói', o id não pode ser repetido, senão será reportado um erro, e deve ser o mesmo nas duas páginas. Adicionado uma animação de prompt de zoom ao texto na lista, parece muito interessante e há outros efeitos que você pode experimentar. O exercício anterior adicionou uma página de detalhes e, em seguida, saltou para a página de detalhes do usuário Douyin da página de terceiros. A animação do Hero é adicionada à página de detalhes do salto e os elementos compartilhados são excessivos. https://blog.csdn.net/zxc8890304/article/details/130317615

O projeto da mercearia para gatos está em constante atualização

Se a ideia de design do APP for alterada para catpedia, ele não conhecerá o back-end, a fonte de dados captura o pacote e o salva localmente

  1. Faça login e registre-se, adicione informações pessoais ao armazenamento local e modifique
  2. versão internacionalizada
  3. modo dia e noite 
  4. Remoção de itens do carrinho
  5. Pedido para solicitar o processo de pagamento
  6. Classificação de ferramentas (tamanho da fonte, cor da fonte, cor do tema, etc.)
  7. Processamento da ferramenta da biblioteca de imagens
  8. otimização de interceptação de página webview
  9. Otimização geral do desempenho
  10. Embalagem

sp_util é uma boa classe utilitária

flutter_screenutil

Necessidade de registrar largura e altura ao usar

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(),
        ),
      ),
    );
  }
}

webview_flutter

Adicionar salto de visualização da 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),
          ),
        ],
      ),
    );
  }
}

Anúncios de contagem regressiva, use o Timer para fazer a contagem regressiva,

second_index é o tempo definido

Defina o tempo para modificar você mesmo, ou você pode modificá-lo no lado do servidor

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();
        }
      },
    );
  }
}

 As palavras na página de boas-vindas são

flutter_swiper_plus 

 Muito rudimentar, simples de conseguir o efeito, de re-otimizar e modificar

Foi adicionado o julgamento de isFirst, que será exibido somente quando o APP for aberto pela primeira vez.

Já fiz projetos internacionais antes, e a demanda no exterior é

Contanto que você entre na página de boas-vindas sem clicar em pular ou entrar no APP , você entrará na página de boas-vindas novamente toda vez que entrar no APP

Neste caso, as condições de julgamento precisam ser revistas.

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);
  }
}

 A barra deslizante lateral também é relativamente simples

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

endereço DEMO 

GitHub - HelloJiada/flutter_cat_1 Contribua para o desenvolvimento HelloJiada/flutter_cat_1 criando uma conta no GitHub. https://github.com/HelloJiada/flutter_cat_1.git

Acho que você gosta

Origin blog.csdn.net/zxc8890304/article/details/130371789
Recomendado
Clasificación