【Flutter】Dialog组件PageView组件

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:Flutter学习
🌠 首发时间:2024年5月27日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾

目录

  • Dialog组件
    • AlertDialog和SimpleDialog
    • 底部弹出框showModalBottomSheet
    • Fluttertoast
    • 自定义Dailog
  • PageView组件
    • PageView的使用
    • PageView.builder
    • PageView上拉无限加载的实现思路
    • PageView实现无限轮播图
    • 定时器
    • 定时器加PageController实现动态轮播图

Dialog组件

AlertDialog和SimpleDialog

AlertDialogSimpleDialog 都必须在 showDialog 组件中使用,而且 SimpleDialog 中的选项需要使用 SimpleDialogOption 组件来定义。

我们新建一个页面 dialog.dart 专门来演示与弹出框有关的组件,其内容如下,记得将其添加到路由中:

import 'package:flutter/material.dart';class DialogPage extends StatefulWidget {const DialogPage({super.key});State<DialogPage> createState() => _DialogPageState();
}class _DialogPageState extends State<DialogPage> {void _alertDialog() async {var result = await showDialog(barrierDismissible: false, //表示点击灰色背景的时候是否消失弹出框context: context,builder: (context) {return AlertDialog(title: const Text("提示信息!"),content: const Text("您确定要删除吗"),actions: [TextButton(onPressed: () {Navigator.of(context).pop("确定"); //点击按钮让AlertDialog消失, 同时返回“确定”},child: const Text("确定")),TextButton(onPressed: () {Navigator.of(context).pop("取消");},child: const Text("取消"))],);});print(result);}void _simpleDialog() async {var result = await showDialog(barrierDismissible: false, //表示点击灰色背景的时候是否消失弹出框context: context,builder: (context) {return SimpleDialog(title: const Text("请选择语言"),children: [SimpleDialogOption(onPressed: () {Navigator.pop(context, "汉语");},child: const Text("汉语"),),const Divider(),SimpleDialogOption(onPressed: () {Navigator.pop(context, "英语");},child: const Text("英语"),),const Divider(),SimpleDialogOption(onPressed: () {Navigator.pop(context, "日语");},child: const Text("日语"),),const Divider(),],);});print(result);}void _modelBottomSheet() async {}void _toast() {}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("Dialog"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: _alertDialog,child: const Text('alert弹出框-AlertDialog '),),const SizedBox(height: 20),ElevatedButton(onPressed: _simpleDialog,child: const Text('select弹出框-SimpleDialog'),),const SizedBox(height: 20),ElevatedButton(onPressed: _modelBottomSheet,child: const Text('ActionSheet底部弹出框'),),const SizedBox(height: 20),ElevatedButton(onPressed: _toast,child: const Text('Toast'),),// fluttertoast],),),);}
}

由于 showDialog 的返回类型为 Future,为了接收弹出框的返回信息,我们需要在函数后面加上 async,在 前面加上 await,并用一个变量 result 来接收。

顺便说一下 showDialog 中的 barrierDismissible 参数,所谓的灰色背景指的是屏幕中除了弹出框以外的地方。

home.dart 中,我们简单写了一个按钮,可以让页面跳转到 dialog.dart

import 'package:flutter/material.dart';class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> {Widget build(BuildContext context) {return Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [ElevatedButton(onPressed: () {Navigator.pushNamed(context, "/dialog");},child: const Text("Dialog测试"),),],),);}
}

效果:

在这里插入图片描述

在这里插入图片描述

底部弹出框showModalBottomSheet

为了减小代码篇幅,下面只给出缺少的函数。

如果你想修改底部弹出框的高度,建议在其外部套上一个 Container 或者 SizedBox

void _modelBottomSheet() async {var result = await showModalBottomSheet(context: context,builder: (context) {return SizedBox(height: 240,child: Column(crossAxisAlignment: CrossAxisAlignment.center,children: [ListTile(title: const Text("分享"),onTap: () {Navigator.of(context).pop("分享");},),const Divider(),ListTile(title: const Text("收藏"),onTap: () {Navigator.of(context).pop("收藏");},),const Divider(),ListTile(title: const Text("取消"),onTap: () {Navigator.of(context).pop("取消");},),const Divider(),],),);});print(result);
}

效果:

在这里插入图片描述

Fluttertoast

如果你想实现屏幕上弹出一个提示信息,然后几秒后自动消失的效果,Flutter 中并没有这样的内置组件。这个时候我们可以使用一个第三方插件 —— Fluttertoast。

https://pub-web.flutter-io.cn/ 中搜索 fluttertoast 即可找到它,按照其使用手册即可轻松上手。

在这里插入图片描述

Readme 页面下滑,即可看到使用教程,非常简单,我们只要会复制粘贴即可:

在这里插入图片描述

记得引入 fluttertoast

void _toast() {Fluttertoast.showToast(msg: "提示信息",toastLength: Toast.LENGTH_LONG, //提示时间,只对android生效gravity: ToastGravity.CENTER, //出现位置timeInSecForIosWeb: 1, //提示时间,只对ios和web生效backgroundColor: Colors.black,textColor: Colors.white,fontSize: 16,);
}

在引入第三方插件后,记得重启项目,不能热加载,效果:

在这里插入图片描述

自定义Dailog

自定义 Dialog 对象,需要继承 Dialog 类,尽管 Dialog 提供了 child 参数可以用来写视图界面,但是往往会达不到我们想要的效果,因为默认的 Dialog 背景框是满屏的,不符合弹出框的特点。如果我们想完全定义界面,就需要重写 build 函数。

  1. 新建自定义组件 myDialog.dart

    InkWell 组件是 Flutter 中的一个特殊的交互式组件,它提供了水波纹效果和触摸事件处理能力。当用户点击 InkWell 组件时,它会显示一个水波纹动画效果,以指示用户的交互。除了点击事件外,InkWell 组件还可以处理其他手势事件,如长按、双击等。InkWell 通常用于包装其他可点击的组件,如按钮或列表项,以增强用户交互体验。

    import 'package:flutter/material.dart';class MyDialog extends Dialog {final String title; //标题final String content; //内容final Function()? onTap; //方便我们在外部获取其返回值const MyDialog({super.key,required this.title,required this.content,required this.onTap});Widget build(BuildContext context) {return Material(type: MaterialType.transparency, //设置背景透明child: Center(//包裹在Center组件中,不然会全屏child: Container(height: 240,width: 240,color: Colors.white,child: Column(children: [Padding(padding: const EdgeInsets.all(5),child: Stack(children: [Align(alignment: Alignment.centerLeft,child: Text(title,style: const TextStyle(fontSize: 18),),),Align(alignment: Alignment.centerRight,child: InkWell(onTap: onTap,child: const Icon(Icons.close),),)],),),const Divider(),Container(padding: const EdgeInsets.all(10),width: double.infinity,child: Text(content, style: const TextStyle(fontSize: 14)),)],),),),);}
    }
    
  2. 定义一个按钮,调用 MyDialog

    void _myDialog() async {var result = await showDialog(context: context,builder: (context) {return MyDialog(title: "提示!",content: "我是一个内容",onTap: () {Navigator.of(context).pop("自定义Dialog关闭");},);});print(result);
    }
    
  3. 效果

    在这里插入图片描述

PageView组件

Flutter 中的轮动图以及抖音上下滑页切换视频功能等等,这些都可以通过 PageView 轻松实现。

PageView 常见属性:

属性描述
scrollDirection默认为 Axis.horizontal:水平方法;Axis.vertical:垂直方向
children配置子元素
allowImplicitScrolling缓存当前页面的前后两页
onPageChangedpage改变的时候触发

PageView的使用

写一个 pageView.dart

import 'package:flutter/material.dart';class PageViewPage extends StatefulWidget {const PageViewPage({super.key});State<PageViewPage> createState() => _PageViewPageState();
}class _PageViewPageState extends State<PageViewPage> {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("PageView"),),body: PageView(scrollDirection: Axis.vertical,children: [Center(child:Text("第1屏", style: Theme.of(context).textTheme.headlineLarge),),Center(child:Text("第2屏", style: Theme.of(context).textTheme.headlineLarge),),Center(child:Text("第3屏", style: Theme.of(context).textTheme.headlineLarge),),Center(child:Text("第4屏", style: Theme.of(context).textTheme.headlineLarge),),Center(child:Text("第5屏", style: Theme.of(context).textTheme.headlineLarge),),],),);}
}

然后将其写在路由中,再在 home.dart 添加一个按钮用来跳转,效果就是可以上下滑动切换页面:

在这里插入图片描述

在这里插入图片描述

PageView.builder

PageView.builder 同理

import 'package:flutter/material.dart';class PageViewBuilderPage extends StatefulWidget {const PageViewBuilderPage({super.key});State<PageViewBuilderPage> createState() => _PageViewBuilderPageState();
}class _PageViewBuilderPageState extends State<PageViewBuilderPage> {Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("pageViewBuilder"),),body: PageView.builder(scrollDirection: Axis.vertical,itemCount: 6, //页数itemBuilder: (context, index) {return Center(child: Text("第$index屏",style: Theme.of(context).textTheme.headlineLarge));}),);}
}

在这里插入图片描述

PageView上拉无限加载的实现思路

新建 pageViewFullPage.dart

import 'package:flutter/material.dart';class PageViewFullPage extends StatefulWidget {const PageViewFullPage({super.key});State<PageViewFullPage> createState() => _PageViewFullPageState();
}class _PageViewFullPageState extends State<PageViewFullPage> {final List<Widget> _list = [];void initState() {super.initState();for (var i = 0; i < 10; i++) {_list.add(MyPage(text: "第${i + 1}屏"));}}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("pageview无限加载"),),body: PageView(scrollDirection: Axis.vertical, // 滑动方向为垂直方向onPageChanged: (index) {//当页面快加载完时, 继续添加页面if (index + 2 == _list.length) {setState(() {for (var i = 0; i < 10; i++) {_list.add(MyPage(text: "第${i + 1}屏"));}});}},children: _list,));}
}class MyPage extends StatefulWidget {final String text;const MyPage({super.key, required this.text});State<MyPage> createState() => _MyPageState();
}class _MyPageState extends State<MyPage> {Widget build(BuildContext context) {return Center(child:Text(widget.text, style: Theme.of(context).textTheme.headlineLarge),);}
}

无限加载的效果就是,当我们上滑到第10屏后,再下滑就会回到第1屏

PageView实现无限轮播图

实现如下效果,有三张图片可以左右一直滑动,同时图片下方有圆点跟随移动:

在这里插入图片描述

新建 pageViewSwiper.dart

import 'package:flutter/material.dart';class PageViewSwiperPage extends StatefulWidget {const PageViewSwiperPage({super.key});State<PageViewSwiperPage> createState() => _PageViewSwiperPageState();
}class _PageViewSwiperPageState extends State<PageViewSwiperPage> {List<Widget> list = [];int _currentIndex = 0;void initState() {super.initState();list = const [ImagePage(src: "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/1.jpg"),ImagePage(src: "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/2.jpg"),ImagePage(src: "https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/3.jpg"),];}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('PageView无限轮播图'),),body: Stack(children: [SizedBox(height: 200,child: PageView.builder(onPageChanged: (index) {setState(() {_currentIndex = index % list.length;});},itemCount: 1000,itemBuilder: (context, index) {return list[index % list.length];}),),Positioned(left: 0,right: 0, //设置left:0,right:0就会占满整行bottom: 2,child: Row(mainAxisAlignment: MainAxisAlignment.center,children: List.generate(list.length, (index) {return Container(margin: const EdgeInsets.all(5),width: 10,height: 10,decoration: BoxDecoration(//图标下标和圆点下标一致时,圆点显示为蓝色; 否则为灰色color: _currentIndex == index ? Colors.blue : Colors.grey,shape: BoxShape.circle //圆),);}).toList(),),)],),);}
}class ImagePage extends StatefulWidget {final double height; //图片高度final double width; //图片宽度final String src; //图片地址const ImagePage({super.key,this.height = 200,this.width = double.infinity,required this.src});State<ImagePage> createState() => _ImagePageState();
}class _ImagePageState extends State<ImagePage> {Widget build(BuildContext context) {return SizedBox(height: widget.height,width: widget.width,child: Image.network(widget.src),);}
}

定时器

我们可以使用 Timer.periodic() 来创建定时器,需要导包:

import 'dart:async';
//创建定时器, 3秒
var timer = Timer.periodic(const Duration(seconds: 3), (t) {print('afterTimer=' + DateTime.now().toString());
});

组件销毁的时候取消定时器:

void dispose() {super.dispose();timer.cancel();
}

定时器加PageController实现动态轮播图

我们将前面实现的轮播图抽离出来,方便我们实现轮播图,同时加上定时器,让其定时切换页面,实现动态轮播图的效果。

抽离为 swiper.dart

import 'dart:async';
import 'package:flutter/material.dart';class Swiper extends StatefulWidget {final double width;final double height;final List<String> list; //页面信息列表const Swiper({super.key,this.height = 200,this.width = double.infinity,required this.list});State<Swiper> createState() => _SwiperState();
}class _SwiperState extends State<Swiper> {int _currentIndex = 0;List<Widget> pageList = []; //页面列表late PageController _pageController;late Timer timer;void initState() {super.initState();//数据for (var i = 0; i < widget.list.length; i++) {pageList.add(ImagePage(width: widget.width, height: widget.height, src: widget.list[i]));}//PageController, 默认显示第一页_pageController = PageController(initialPage: 0);//定时器timer = Timer.periodic(const Duration(seconds: 3), (t) {//进行页面切换_pageController.animateToPage((_currentIndex + 1) % pageList.length,duration: const Duration(milliseconds: 300), curve: Curves.linear);});}void dispose() {super.dispose();timer.cancel();_pageController.dispose();}Widget build(BuildContext context) {return Stack(children: [SizedBox(height: 200,child: PageView.builder(controller: _pageController,onPageChanged: (index) {setState(() {_currentIndex = index % pageList.length;});},itemCount: 1000,itemBuilder: (context, index) {return pageList[index % pageList.length];}),),Positioned(left: 0,right: 0,bottom: 2,child: Row(mainAxisAlignment: MainAxisAlignment.center,children: List.generate(pageList.length, (index) {return Container(margin: const EdgeInsets.all(5),width: 10,height: 10,decoration: BoxDecoration(color: _currentIndex == index ? Colors.blue : Colors.grey,shape: BoxShape.circle //圆),);}).toList(),))],);}
}class ImagePage extends StatelessWidget {final double width;final double height;final String src;const ImagePage({super.key,this.width = double.infinity,this.height = 200,required this.src});Widget build(BuildContext context) {return SizedBox(width: width,height: height,child: Image.network(src,fit: BoxFit.cover,),);}
}

pageViewSwiper.dart

import 'package:flutter/material.dart';
import '../widget/swiper.dart';class PageViewSwiperPage extends StatefulWidget {const PageViewSwiperPage({super.key});State<PageViewSwiperPage> createState() => _PageViewSwiperPageState();
}class _PageViewSwiperPageState extends State<PageViewSwiperPage> {List<String> list = [];void initState() {super.initState();list = ["https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/1.jpg","https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/2.jpg","https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/3.jpg","https://xixi-web-tlias.oss-cn-guangzhou.aliyuncs.com/4.jpg",];}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('PageViewSwiper'),),body: ListView(children: [Swiper(list: list),],));}
}

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/333000.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何确保大模型 RAG 生成的信息是基于可靠的数据源?

在不断发展的人工智能 (AI) 领域中&#xff0c;检索增强生成 (RAG) 已成为一种强大的技术。 RAG 弥合了大型语言模型 (LLM) 与外部知识源之间的差距&#xff0c;使 AI 系统能够提供更全面和信息丰富的响应。然而&#xff0c;一个关键因素有时会缺失——透明性。 我们如何能够…

mysql中单表查询的成本

大家好。我们知道MySQL在执行一个查询时&#xff0c;经常会有多个执行方案&#xff0c;然后从中选取成本最低或者说代价最低的方案去真正的执行查询。今天我们来聊一聊单表查询的成本。 那么到底什么是成本呢&#xff1f;这里我们说的成本或者代价是由两方面组成的&#xff1a…

vscode插件-03 PHP

PHP Intelephense 如果php在远程计算机上&#xff0c;要把插件安装在远程&#xff0c;而不是本地。 这个插件&#xff0c;要求php版本大于7&#xff0c;且设置环境变量&#xff08;好像不一定要设置&#xff09;。 设置里面搜索php.executablePath&#xff0c;打开setting.js…

element ui 的el-input输入一个字后失去焦点,需重新点击输入框才能再次输入

解决方案&#xff1a; 我是form表单嵌套表格&#xff0c;里面的el-input输入框&#xff0c;输入第一个值的时候会突然失去焦点&#xff0c;需要再次点击输入框才能正常输入&#xff0c;原因是table的key值&#xff0c;需要改成正常的index即可&#xff0c;如果你是循环的&…

ESP32入门:1、VSCode+PlatformIO环境搭建

文章目录 背景安装vscode安装配置中文 安装Platform IO安装PIO 新建ESP32工程参考 背景 对于刚接触单片机的同学&#xff0c;使用vscodeplatformIO来学习ESP32是最方便快捷的&#xff0c;比IDF框架简单&#xff0c;且比arduino文件管理性能更好。但是platformIO安装较为麻烦&a…

gnocchi学习小结

背景 总结gnocchi 4.4版本gnocchi-metricd工作流程 入口 gnocchi.cli.metricd metricd stop after processing metric默认为0&#xff0c;调servicemanager run MetricdServiceManager __init__ 服务逻辑封装到MetricdServiceManager初始化中 主要由MetricProcessor, Met…

【方法】ZIP压缩文件的密码如何设置和取消?

ZIP是一种常见的压缩文件格式&#xff0c;今天来分享一下&#xff0c;ZIP压缩文件如何设置密码保护&#xff0c;以及如何取消密码&#xff0c;不清楚的小伙伴一起来看看吧&#xff01; 设置ZIP文件密码&#xff1a; 想要给ZIP压缩包设置密码&#xff0c;需要用到支持ZIP格式的…

香橙派 Kunpeng Pro使用教程:从零开始打造个人私密博客

一、引言 在这个日益互联的世界中&#xff0c;单板计算机已经成为创新和个性化解决方案的重要载体。而在单板计算机领域&#xff0c;香橙派 Kunpeng Pro凭借其强大的性能和灵活的应用潜力&#xff0c;正逐渐吸引着全球开发者和技术爱好者的目光。 作为一款集成了华为的鲲鹏处…

【AD21】文件的整理

当所有文件输出完成后&#xff0c;需要对不同的文件去做一个整理&#xff0c;方便后续工作的交接。 在项目工程文件夹下新建名称为BOM、SMT、PRJ、Gerber和DOC的文件夹。 BOM文件夹存放BOM表发给采购人员。SMT文件夹存放装配图文件和坐标文件发给贴片厂。PRJ文件夹存放工程文件…

AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研

目录 前言一、DB-GPT总体概述二、DB-GPT关键特性1、私域问答&数据处理&RAG2、多数据源&GBI3、多模型管理4、自动化微调5、Data-Driven Multi-Agents&Plugins6、隐私安全 三、服务器资源准备1、创建实例2、打开jupyterLab 四、DB-GPT启动1、激活 conda 环境2、切…

2024年03月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,共50分) 第1题 期末考试结束了,全班的语文成绩都储存在列表score中,班主任老师请小明找到全班最高分,小明准备用Python来完成,以下哪个选项,可以获取最高分呢?( ) A:min(score) B:max(score) C:sco…

夏日将至,给手机装个“液冷”降温可行吗?

夏天出门在外&#xff0c;手机总是更容易发热&#xff0c;尤其是顶着大太阳用手机的时候&#xff0c;更是考验手机的散热能力。如果你也是一个对手机体验有追求的人&#xff0c;比较在意手机的温度&#xff0c;那么可以考虑入手一个微泵液冷手机壳。 【什么是微泵液冷壳&#…

【Spring Security + OAuth2】OAuth2

Spring Security OAuth2 第一章 Spring Security 快速入门 第二章 Spring Security 自定义配置 第三章 Spring Security 前后端分离配置 第四章 Spring Security 身份认证 第五章 Spring Security 授权 第六章 OAuth2 文章目录 Spring Security OAuth21、OAuth2简介1.1、OAu…

数据结构(三)循环链表

文章目录 一、循环链表&#xff08;一&#xff09;概念&#xff08;二&#xff09;示意图&#xff08;三&#xff09;操作1. 创建循环链表&#xff08;1&#xff09;函数声明&#xff08;2&#xff09;注意点&#xff08;3&#xff09;代码实现 2. 插入&#xff08;头插&#x…

vue3 3D炫酷模型banner图

项目场景&#xff1a; 在官网首页展示3D炫酷动画模型&#xff0c;让整个模型都展示出来。 问题描述 主要是3D动画的展示效果&#xff0c;有些3d模型网站可以从51建模网站中获取。 案例代码&#xff1a; <script setup> import * as imgs from ../units/img import { o…

如果查看svn的账号和密码

一、找到svn存放目录&#xff08;本地默认存放SVN用户信息的目录为&#xff1a;C:\Users\Administrator\AppData\Roaming\Subversion\auth\svn.simple&#xff09;每个人的电脑环境不一样&#xff0c;因人而异。 如果找不到直接搜索svn.simple 二、下载密码查看工具 链接: 百…

基础—SQL—DDL—建表、查表、修改表以及总结

一、DDL—表—创建表与数据类型的设定 &#xff08;1&#xff09;要求 根据需求创建表(设计合理的数据类型、长度) 设计一张员工信息表&#xff0c;要求如下: 1、编号&#xff08;纯数字) 2、员工工号(字符串类型&#xff0c;长度不超过10位) 3、员工姓名&#xff08;字符串类…

初学迁移学习的理解

1.迁移学习&#xff08;Transfer Learning&#xff09;是什么&#xff1f; 简而言之&#xff0c;迁移学习(Transfer Learning)是一种机器学习方法&#xff0c;就是把为任务 A 开发的模型作为初始点&#xff0c;重新使用在为任务 B 开发模型的过程中。 迁移学习是通过从已学习…

01JAVA基础

目录 1.基础语法 1.1 注释 1.2 关键字 1.3 常量 1.4 数据类型 1.5 变量 1.6 标识符 1.7 类型转换 2.算数运算符和分支语句 2.1 算数运算符 1.常规运算符 2.赋值运算符 3.自增自减 4.关系运算符 5.逻辑运算符 6.三元运算符 2.2 数据输入(Scanner) 2.3 分支判断…

mac 安装java jdk8 jdk11 jdk17 等

oracle官网 https://www.oracle.com/java/technologies/downloads/ 查看当前电脑是英特尔的x86 还是arm uname -m 选择指定版本&#xff0c;指定平台的安装包&#xff1a; JDK8 JDK11的&#xff0c;需要当前页面往下拉&#xff1a; 下载到的安装包&#xff0c;双击安装&#x…