当前位置: 首页 > news >正文

【Android】ViewPager

1.ViewPager的简介和作用


ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view,用于允许用户在几个页面(或称为碎片)之间左右滑动切换。它通常用于创建像画廊或轮播图那样的用户体验。

  1. ViewPager类直接继承了ViewGroup类,所有它是一个容器类,可以在其中添加其他的view类。
  2. ViewPager类需要一个PagerAdapter适配器类给它提供数据。
  3. ViewPager经常和Fragment一起使用,并且提供了专门的FragmentPagerAdapter和FragmentStatePagerAdapter类供Fragment中的ViewPager使用。

作用:

ViewPager 的主要作用包括:

  1. 页面滑动:允许用户通过水平滑动来切换不同的页面。
  2. 动画效果:提供平滑的页面切换动画,增强用户体验。
  3. 页面预加载:可以配置 ViewPager 预加载相邻的页面,这样用户在滑动时页面切换更加流畅。
  4. 页面指示器:通常与 TabLayout 或其他指示器组件结合使用,显示当前页面的位置和总数。
  5. 页面适配器:通过适配器模式,可以灵活地管理页面的内容,适配器负责提供页面视图。
  6. 自定义页面转换:开发者可以通过实现 PageTransformer 接口来自定义页面滑动时的动画和转换效果。
  7. 事件监听:提供页面切换的监听器,如 OnPageChangeListener,以便在页面切换时执行特定的操作。

2.ViewPager的适配器


简介中提到了PagerAdapter,和ListView等控件使用一样,需要ViewPager设置PagerAdapter来完成页面和数据的绑定,

这个PagerAdapter是一个基类适配器,我们经常用它来实现app引导图,它的子类有FragmentPagerAdapter和FragmentStatePagerAdapter,这两个子类适配器用于和Fragment一起使用,在安卓应用中它们就像listview一样出现的频繁。

适配器:ViewPager主要有两种Adapter用于适配填充Fragment。

PagerAdapter 是 Android 中的一个抽象类,用于为 ViewPager 提供数据和视图。当你想要在 ViewPager 中展示一系列的页面时,你需要创建一个 PagerAdapter 的子类来管理这些页面。

public class MyPagerAdapter extends PagerAdapter {private Context context;private List<Fragment> fragments;public MyPagerAdapter(Context context, List<Fragment> fragments) {this.context = context;this.fragments = fragments;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {//必须实现,用于实例化Fragment fragment = fragments.get(position);FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();fragmentManager.beginTransaction().add(container.getId(), fragment, "fragment" + position).commit();return fragment;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {//必须实现,销毁FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();fragmentManager.beginTransaction().remove((Fragment) object).commit();}@Overridepublic int getCount() {//必须实现return fragments.size();}@Overridepublic boolean isViewFromObject(View view, Object object) {//必须实现return view.equals(object);}
}

一个PagerAdapter 需要至少实现四个方法

这个东西是一个基类,我们常用的viewpager+fragment主要使用他的子类:FragmentPagerAdapter和FragmentStatePagerAdapter

首先是FragmentPagerAdapter:

特点

  • 每个页面一个 FragmentFragmentPagerAdapter 为 ViewPager 的每个页面创建一个 Fragment 实例。
  • 内存效率FragmentPagerAdapter 会保留所有页面的 Fragment 对象,这意味着用户在页面间切换时,页面状态不会丢失,但这也可能导致更多的内存使用。
  • 易于实现:相比于 PagerAdapterFragmentPagerAdapter 提供了更简单的 API 来管理 Fragment
    private static class FragmentAdapter extends FragmentPagerAdapter{private ArrayList<Fragment> fragments;public FragmentAdapter(FragmentManager fm,ArrayList<Fragment> fragments) {super(fm);this.fragments = fragments;}@Overridepublic Fragment getItem(int position) {return fragments.get(position);}@Overridepublic int getCount() {return fragments.size();}}

FragmentStatePagerAdapter:

主要特点

  • 按需加载:当用户浏览到某个页面时,FragmentStatePagerAdapter 会创建该页面的 Fragment,而当用户离开该页面时,对应的 Fragment 可能会被销毁,以节省内存。
  • 状态保存FragmentStatePagerAdapter 会在 Fragment 被销毁前保存其状态,以便在用户返回该页面时恢复 Fragment 的状态。
  • 适用于大量页面:由于它会销毁不在屏幕上的 Fragment,因此更适合用于拥有大量页面的 ViewPager
    private static class FragmentStateAdapter extends FragmentStatePagerAdapter{private ArrayList<Fragment> fragments;public FragmentStateAdapter(FragmentManager fm,ArrayList<Fragment> fragments) {super(fm);this.fragments = fragments;}@Overridepublic Fragment getItem(int position) {return fragments.get(position);}@Overridepublic int getCount() {return fragments.size();}}

FragmentPagerAdapter 相比,FragmentStatePagerAdapter 更适合用于页面数量较多的情况。FragmentPagerAdapter 会保留所有页面的 Fragment 在内存中,而 FragmentStatePagerAdapter 则仅在需要时加载 Fragment,这样可以减少内存的使用。

在fragment中的区别:

  1. ViewPager默认会保留当前页和前后两页的内容,即一共三页。首页之前没有了所以只保留当前页和后一页;
  2. 对于不保留的内容,FragmentPagerAdapter 只进行到对Fragment的destroyView,不会destroy和detach;
  3. 而FragmentStatePagerAdapter会执行destroy和detach,当划回去的时候会再次执行attach和create;
  4. 因此,FragmentPagerAdapter适用于数量较少的场景,用空间换时间;FragmentStatePagerAdapter适用于数量较多的场景,每次会执行destroy,节约内存。

3.viewpager2

首先介绍一下viewpager2:

  1. 基于 RecyclerViewViewPager2 是建立在 RecyclerView 基础上的,因此它继承了 RecyclerView 的所有优点,如高效的视图回收机制和灵活的布局管理。
  2. 灵活的缓存策略ViewPager2 允许开发者通过 offscreenPageLimit 属性来控制预加载的页面数量,提供了更灵活的缓存策略。
  3. 支持垂直和水平滑动ViewPager2 支持垂直滑动,这使得它可以在不同的布局方向上使用。
  4. 适配器:使用 RecyclerView.Adapter 或 FragmentStateAdapter 作为其适配器。FragmentStateAdapter 是专为 ViewPager2 设计的,用于管理 Fragment 的生命周期。
  5. 新特性ViewPager2 支持更多的自定义动画和转换效果,可以通过 PageTransformer 来实现。
  6. 更好的性能:由于基于 RecyclerViewViewPager2 在性能上通常优于 ViewPager,特别是在处理大量数据或复杂布局时。

ViewPager2 的运作机制

ViewPager2 的运作离不开两个关键组件:PagerAdapter 和 PageTransformer。PagerAdapter,例如 FragmentStatePagerAdapter 或 FragmentPagerAdapter,负责管理 Fragment 的集合,根据当前位置创建或销毁 Fragment。

PageTransformer 则用于控制页面之间的过渡效果。开发者可以自定义 PageTransformer,实现缩放、平移或淡入淡出的效果,为用户提供更加流畅、生动的视觉体验。

我们以常用的ViewPager2的多Fragment页面切换为例展示一下使用

1.制作一个fragment的xml文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:tools="http://schemas.android.com/tools"tools:context=".View.myFragment"><com.example.weatherwindknow.View.MyViewandroid:id="@+id/mv"android:layout_width="200dp"android:layout_height="200dp"android:layout_gravity="center_horizontal"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

我们在这里绑定了我们的类

在fragment类中:

public class myFragment extends Fragment {FragmentMyBinding binding;@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {binding = FragmentMyBinding.inflate(inflater,container,false);return binding.getRoot();}@Overridepublic void onDestroyView() {super.onDestroyView();binding = null;}
}

2、制作Adapter

我们可以直接使用上面的示例

这里我们使用FragmentStateAdapter。

public class MyviewPagerAdapter extends FragmentStateAdapter {List<Fragment> List;public MyviewPagerAdapter(@NonNull FragmentActivity fragmentActivity, List<Fragment> fragmentList) {super(fragmentActivity);this.List = fragmentList;}@NonNull@Overridepublic Fragment createFragment(int position) {return List.get(position);}@Overridepublic int getItemCount() {return List != null ? List.size() : 0;}
}

createFragment:用于返回指定的frgment界面

getItemCount:用于加载容器大小

3.在活动中使用

        List<Fragment> fragmentList = new ArrayList<>();fragmentList.add(new myFragment());fragmentList.add(new myFragment());fragmentList.add(new myFragment());fragmentList.add(new myFragment());fragmentList.add(new myFragment());MyviewPagerAdapter adapter = new MyviewPagerAdapter(this,fragmentList);binding.viewPager.setAdapter(adapter);

我们这里可以看出来逻辑:首先加载数据,再把数据加载进适配器,再设置适配器。

4.TabLayout / 指示器CircleIndicator

这两个东西的作用是一个知识器的效果

我们先来介绍指示器CircleIndicator:这是一个简单的圆点指示器,我们使用时

首先引入库:

implementation 'me.relex:circleindicator:2.1.6'

其次将这个加入我们的布局中(一般使用是RelativeLayout)

<RelativeLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"><me.relex.circleindicator.CircleIndicator3android:id="@+id/indicator"android:layout_width="match_parent"android:layout_height="48dp"app:ci_width="5dp"app:ci_height="5dp"app:ci_margin="5dp"app:ci_orientation="horizontal"app:ci_gravity="center"/><androidx.viewpager2.widget.ViewPager2android:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"/>
</RelativeLayout>

之后开始使用,依据如下步骤即可使用

ViewPager2 viewpager = view.findViewById(R.id.viewpager);
viewpager.setAdapter(mAdapter);CircleIndicator3 indicator = view.findViewById(R.id.indicator);
indicator.setViewPager(viewpager);
adapter.registerAdapterDataObserver(indicator.getAdapterDataObserver());

接下来介绍tablayout:

首先加入布局中:

    <LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><com.google.android.material.tabs.TabLayoutandroid:id="@+id/tabs"android:layout_width="match_parent"android:layout_height="wrap_content"app:tabMode="fixed" /><androidx.viewpager2.widget.ViewPager2android:id="@+id/viewPager"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"/> </LinearLayout>

之后在代码中将两个关联一下即可:

// 将 TabLayout 与 ViewPager 关联
tabLayout.setupWithViewPager(viewPager);

自定义标签:我们可以自定义标签的文本、图标。

TabLayout tabLayout = findViewById(R.id.tabs);// 添加标签
tabLayout.addTab(tabLayout.newTab().setText("标签1"));
tabLayout.addTab(tabLayout.newTab().setText("标签2"));
tabLayout.addTab(tabLayout.newTab().setText("标签3"));// 设置标签的图标
tabLayout.getTabAt(0).setIcon(R.drawable.ic_tab1);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_tab2);
tabLayout.getTabAt(2).setIcon(R.drawable.ic_tab3);

除了代码设置,我们还可以静态改变,设置两个样式分别代表选中未选中,app:tabTextAppearance="@style/TabLayoutTextUnSelected"

监听标签的点击事件:我们可以为标签设置点击事件监听器。

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {@Overridepublic void onTabSelected(TabLayout.Tab tab) {// 当标签被选中时}@Overridepublic void onTabUnselected(TabLayout.Tab tab) {// 当标签未被选中时}@Overridepublic void onTabReselected(TabLayout.Tab tab) {// 当标签被重新选中时}
});

动态添加和删除标签:我们可以在运行时动态地添加和删除标签。

// 添加标签
TabLayout.Tab newTab = tabLayout.newTab();
newTab.setText("新标签");
tabLayout.addTab(newTab);// 删除标签
tabLayout.removeTabAt(index);

tablayout监听:

        binding.tabMode.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {TextView textView = new TextView(MainActivity.this);@Overridepublic void onTabSelected(TabLayout.Tab tab) {//选中时的变化}public void onTabUnselected(TabLayout.Tab tab) {//未选中的变化}@Overridepublic void onTabReselected(TabLayout.Tab tab) {//重复选中的变化,当用户再次点击已经选中的Tab时,这个方法就会被调用。}});

我们可以在 onTabSelected中处理选中的时候情况,更改样式等等,但是要在 onTabSelected中设置内容,并且在 onTabUnSelected中清除掉我们的样式,否则会出现叠加爆掉的情况

相关文章:

【Android】ViewPager

1.ViewPager的简介和作用 ViewPager是android扩展包v4包中的类&#xff0c;这个类可以让用户左右切换当前的view&#xff0c;用于允许用户在几个页面&#xff08;或称为碎片&#xff09;之间左右滑动切换。它通常用于创建像画廊或轮播图那样的用户体验。 ViewPager类直接继承了…...

[go] 命令模式

命令模式 将“请求”封装成对象&#xff0c;以便使用不同的请求、队列或者日志来参数化其他对象。命令模式也支持可撤销的操作。 模型说明 触发者类负责对请求进行初始化&#xff0c;其中必须包含一个成员变量来存储对于命令对象的引用。触发命令&#xff0c;而不同接受者直接…...

代码随想录冲冲冲 Day48 单调栈Part2

42. 接雨水 关键点有以下几个 首先是怎么去理解接雨水 其实就是找每一个段的左边第一个最大值和右边第一个最大值 既然是最大值 那么单调栈就是递增的 左边第一个最大值其实就是pop掉中间的之后st.top 由于是出现大于等于情况时候进行操作 所以右边最大值就是i 接下来就…...

企业内训|Nvidia智算中心深度技术研修-某智算厂商研发中心

课程概述 此企业内训课程“Nvidia智算中心的深度技术研修”专为某智算厂商研发中心设计&#xff0c;内容涵盖了从基础设施构建到高性能计算优化的全方位技术要点。课程为期七天&#xff0c;分模块详细讲解了NV算力资源的网络架构、存储优化、智算集群的建设与自动化管理、NCCL…...

《算法笔记》例题解析 第3章入门模拟--3图形输出(9题)2021-03-03

例题 旋转方阵 题目描述 Time Limit: 1000 ms Memory Limit: 256 mb 打印出一个旋转方阵,见样例输出。 输入描述: 输入一个整数n(1 < n < 20), n为方阵的行数。 输出描述: 输出一个大小为n*n的距阵 输入 5 输出 1 16 15 14 13 2 17 24 23 12 3 18 25 22 11 4 1…...

合宙Air201模组LuatOS:PWRKEY控制,一键解决解决关机难问题

不知不觉间&#xff0c;我们已经发布拉期课程&#xff1a;hello world初体验&#xff0c;点灯、远程控制、定位和扩展功能&#xff0c;你学的怎么样&#xff1f;很多伙伴表示已经有点上瘾啦&#xff01;合宙Air201&#xff0c;如同我们一路升级打怪的得力法器&#xff0c;让开发…...

Kafka 命令详解及使用示例

文章目录 Kafka 命令详解及使用示例Kafka 命令详解kafka-topics.sh&#xff1a;主题管理创建主题创建带副本的主题修改主题分区数了解分区分布列出主题查看主题详情删除主题 kafka-console-producer.sh&#xff1a;消息生产者发送消息到主题带键值对的消息消息生产性能优化带分…...

重生归来之挖掘stm32底层知识(1)——寄存器

概念理解 要使用stm32首先要知道什么是引脚和寄存器。 如下图所示&#xff0c;芯片通过这些金属丝与电路板连接&#xff0c;这些金属丝叫做引脚。一般做软件开发是不需要了解芯片是怎么焊的&#xff0c;只要会使用就行。我们平常通过编程来控制这些引脚的输入和输出&#xff0c…...

Qt构建JSON及解析JSON

目录 一.JSON简介 JSON对象 JSON数组 二.Qt中JSON介绍 QJsonvalue Qt中JSON对象 Qt中JSON数组 QJsonDocument 三.Qt构建JSON数组 四.解析JSON数组 一.JSON简介 一般来讲C类和对象在java中是无法直接直接使用的&#xff0c;因为压根就不是一个规则。但是他们在内存中…...

合宙Air201模组LuatOS扩展功能:温湿度传感器篇!

通过前面几期的学习&#xff0c;同学们的学习热情越来越高。 合宙Air201模组除了支持3种定位方式外&#xff0c;还具有丰富的扩展功能&#xff0c;比如&#xff1a;通过外扩BTB链接方案&#xff0c;最多可支持21个IO接口&#xff1a;SPI、I2C、UART等多种接口全部支持。 本期…...

主流敏捷工具scrum工具

在当今的快速变化和高需求的业务环境中&#xff0c;敏捷开发已经成为许多企业实现快速迭代和响应市场需求的重要方法。而在众多敏捷工具中&#xff0c;选择适合自己团队的工具尤为重要。 今天&#xff0c;我们将对比几款主流的敏捷工具&#xff0c;供参考 1. Leangoo领歌&…...

探索微服务架构:从理论到实践,深度剖析其优缺点

微服务架构&#xff08;Microservice Architecture&#xff09;是一种软件开发架构形式&#xff0c;它的核心 思想是将大型应用程序拆分成一组小的服务&#xff0c;每个服务都运行在其独立的进程中&#xff0c;并且 服务与服务之间通过轻量级的通信机制&#xff08;如HTTP REST…...

2024 年最佳 Chrome 验证码扩展,解决 reCAPTCHA 问题

验证码&#xff0c;特别是 reCAPTCHA&#xff0c;已成为在线安全的不可或缺的一部分。虽然它们在区分人类和机器人方面起着至关重要的作用&#xff0c;但它们也可能成为合法用户和从事网络自动化的企业的主要障碍。无论您是试图简化在线体验的个人&#xff0c;还是依赖自动化工…...

Go语言现代web开发defer 延迟执行

The defer statement will delay the execution of a function until the surrounding function is completed. Although execution is postponed, funciton arguments will be evaluated immediately. defer语句将延迟函数的执行&#xff0c;直到周围的函数完成。虽然执行被延…...

Vue路由二(嵌套多级路由、路由query传参、路由命名、路由params传参、props配置、<router-link>的replace属性)

目录 1. 嵌套(多级)路由2. 路由query传参3. 路由命名4. 路由params传参5. props配置6. <router-link>的replace属性 1. 嵌套(多级)路由 pages/Car.vue <template><ul><li>car1</li><li>car2</li><li>car3</li></ul…...

【RabbitMQ】可靠性传输

概述 作为消息中间件来说&#xff0c;最重要的任务就是收发消息。因此我们在收发消息的过程中&#xff0c;就要考虑消息是否会丢失的问题。结果是必然的&#xff0c;假设我们没有采取任何措施&#xff0c;那么消息一定会丢失。对于一些不那么重要的业务来说&#xff0c;消息丢失…...

【论文阅读】PERCEIVER-ACTOR: A Multi-Task Transformer for Robotic Manipulation

Abstract transformers凭借其对大型数据集的扩展能力&#xff0c;彻底改变了视觉和自然语言处理。但在机器人操作中&#xff0c;数据既有限又昂贵。通过正确的问题表述&#xff0c;操纵仍然可以从变形金刚中受益吗&#xff1f;我们使用peract来研究这个问题&#xff0c;peract…...

Linux 常用指令

Linux 常用指令 这是本人在备战 CSP 初赛做 Linux 指令题时&#xff0c;心血来潮整理的&#xff0c;希望对大家有帮助。如有错误或有补充&#xff0c;麻烦私信或评论指出。 表格按字母顺序排列 命令作用alias对命令重命名cal显示日历的指令cat查看文本文件的内容cd改变当前工…...

使用 PHPstudy 建立ThinkPHP8 本地集成环境

安装Composer 下载地址&#xff1a;https://getcomposer.org/Composer-Setup.exehttps://getcomposer.org/Composer-Setup.exe 打开PHPstudy创建网站&#xff1a; cmd终端进入PHPstudy www根目录下&#xff1a; 执行代码&#xff1a;cd phpstudy www 根目录地址 cd C:\phpst…...

【系统架构设计】软件的知识产权保护+标准化概论+应用数学+云计算

【系统架构设计】软件的知识产权保护标准化概论应用数学云计算 软件的知识产权保护标准化概论应用数学云计算 软件的知识产权保护 在该部分内容中&#xff0c;以下几点需要注意&#xff1a; 如果作品是委托创作的&#xff0c;著作权的归属应通过委托人和受托人之间的合同来确…...

GLM-4.1V-9B-Base保姆级教学:Web界面截图+问题输入框最佳实践

GLM-4.1V-9B-Base保姆级教学&#xff1a;Web界面截图问题输入框最佳实践 1. 认识GLM-4.1V-9B-Base GLM-4.1V-9B-Base是智谱开源的视觉多模态理解模型&#xff0c;专门用于处理图像内容识别、场景描述、目标问答和中文视觉理解任务。这个模型已经完成了Web化封装&#xff0c;可…...

Win11共享打印机连接失败?绕过安全策略的终极指南

1. Win11共享打印机连接失败的真相 最近帮朋友处理Win11共享打印机的问题时&#xff0c;发现这个看似简单的操作居然能卡住这么多人。明明按照传统方法一步步操作&#xff0c;却总是提示各种错误。其实这背后是微软在Win11 22H2版本后引入的新安全策略在作祟 - 他们默认关闭了S…...

BetterJoy终极指南:让Switch手柄在Windows上完美运行

BetterJoy终极指南&#xff1a;让Switch手柄在Windows上完美运行 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcode.com/g…...

南京大学发布“视频侦探“系统:让AI像侦探一样从长视频中找线索

这项由南京大学与中科院自动化所联合进行的研究发表于2026年的计算机视觉与模式识别(CVPR)会议&#xff0c;论文编号为arXiv:2603.22285。有兴趣深入了解的读者可以通过该编号查询完整论文内容。当我们观看一部两小时的电影时&#xff0c;想要回答"主角在什么时候第一次露…...

解锁浏览器潜能:用户脚本实用指南

解锁浏览器潜能&#xff1a;用户脚本实用指南 【免费下载链接】greasyfork An online repository of user scripts. 项目地址: https://gitcode.com/gh_mirrors/gr/greasyfork 你是否常常觉得浏览器功能不够用&#xff1f;想让网页自动完成重复操作&#xff1f;希望个性…...

解决Gradio share=True报错:手动下载并配置frpc_linux_amd64_v0.3文件的保姆级教程

解决Gradio shareTrue报错的完整实战指南&#xff1a;从手动配置frpc到深度优化 当你兴奋地准备向客户展示刚完成的Gradio应用时&#xff0c;却在终端看到红色的报错信息——shareTrue参数失效了。这种场景对开发者来说再熟悉不过&#xff1a;本地调试一切正常&#xff0c;但需…...

STM32CubeIDE工程复制粘贴保姆级教程:告别重复配置,5分钟搞定新项目

STM32CubeIDE工程复制粘贴保姆级教程&#xff1a;告别重复配置&#xff0c;5分钟搞定新项目 每次启动新项目时&#xff0c;你是否还在重复那些繁琐的初始化步骤&#xff1f;从零开始配置时钟树、外设参数、中断优先级&#xff0c;不仅耗时费力&#xff0c;还容易出错。对于经验…...

YOLO-v8.3实战:用AI识别图片中的物体,5分钟完成你的第一个检测项目

YOLO-v8.3实战&#xff1a;用AI识别图片中的物体&#xff0c;5分钟完成你的第一个检测项目 你是否曾经好奇&#xff0c;那些能自动识别照片中物体的人工智能是如何工作的&#xff1f;想象一下&#xff0c;你拍了一张街景照片&#xff0c;AI不仅能告诉你照片里有汽车、行人和红…...

UV固化三防漆好用吗?光固化速度与设备要求

UV固化三防漆好用吗&#xff1f;光固化速度与设备要求高效快速的固化优势 UV固化三防漆&#xff08;也称紫外光固化保形涂层&#xff09;是一种专为印刷电路板&#xff08;PCB&#xff09;设计的保护材料&#xff0c;通过紫外光照射触发光引发剂瞬间聚合&#xff0c;实现快速固…...

WSL 启动闪退问题排查

第一步&#xff1a;检查当前状态在开始折腾 BIOS 之前&#xff0c;我们先确认一下系统到底有没有识别到虚拟化。按下快捷键 Ctrl Shift Esc 打开任务管理器。点击左侧的“性能”图标&#xff0c;选择 “CPU”。看右下角的信息&#xff0c;找到 “虚拟化”&#xff1a;如果是“…...