Silverlight学习笔记(3):Silverlight的界面布局

在上一篇中讲述了使用VS2010开发Silverlight的一些基础知识,并且讲述了Silverlight的部署和代码安全知识,这一篇主要是讲述如何在Silverlight中摆放界面元素。
记得早年前我还在学习Java的时候,当时有两种开发Java SE的方法,一种是使用JCreator或者JBuilder之类的IDE开发(现在这二者都几乎没人用了,流行的是Eclipse或者NetBeans);一种是使用Visual J++开发。使用前一种方法开发的Java程序可以多种操作系统平台上运行,不过界面布局比较麻烦,什么CardLayout、FlowLayout、BorderLayout、GridBagLayout、GridLayout等等,开发一个复杂的界面需要开发人员对各种布局类都有所了解;使用Visual J++开发的话可以使用XY坐标来定位元素,相对来说容易多了,不过这种开发的Java软件并不是严格意义上的Java软件,它只能在Windows平台上运行。Java从出现到现在,在Java EE和Java ME上都相对比较成功,而唯独在Java SE上表现不佳,不知道跟它难以使用的界面布局有关系。
布局概述
在上一篇提到了XAML语言,它适用于在WPF和Silverlight中进行界面布局的标记语言,它是一种有特定要求的XML语言,从某种意义上来说,我觉得它和XHTML走得更近一些:首先它们都是有特定格式的XML语言,其次它们都是用于界面布局。除此之外,在XAML语言中还有一个特点,那就是每一个元素都代表着一个Silverlight中的类,并且在XAML中只能有一个顶级元素。因此在进行WPF和Silverlight开发时不能绕开的一个问题就是界面布局,在Silverlight中常见的界面布局类有Canvas、Grid和StackPanel。
Canvas、Grid和StackPanel其实都是继承自System.Windows.Controls.Panel的类,它们的继承层次关系如下图:
 
Panel类有如下比较常见的属性:
Background:用于填充 Panel 的边框之间的区域的 Brush。
Children:此 Panel 的子元素的 UIElementCollection。
Height:元素的建议高度。
HorizontalAlignment:在父元素(如面板或项控件)中构成此元素时应用于此元素的水平对齐特征。
MaxHeight:元素的最大高度约束,MaxHeight的默认值是PositiveInfinity(正无穷大)。 
MaxWidth:元素的最大宽度约束,MaxWidth的默认值是PositiveInfinity(正无穷大)。 
MinHeight:元素的最小高度约束,MinHeight的默认值分别是Auto(自动调整)。
MinWidth:元素的最小宽度约束,MinWidth的默认值分别是Auto(自动调整)。
VerticalAlignment:在父元素(如面板或项控件)中组合此元素时应用于此元素的垂直对齐特征。
Width:元素的宽度。
可以看出在这里存在着Height、MaxHeigh、MinHeight及Width、MaxWidth、MinWidth这么两组与高度和宽度相关的属性,这的确让初学的人有些模糊。这些值之间存在着什么样的关系呢?拿Width、MaxWidth、MinWidth来说,它们存在的关系如下:如果这三个值之间存在冲突,则应用程序确定宽度的实际顺序是:首先必须采用 MinWidth;然后采用 MaxWidth;最后,如果这些值中的每个值都在限制之内,则采用 Width。为什么对于Width或者Height会出现这么三个属性呢?这是跟编程有一定的关系,假如我们在一个布局容器中水平放置了三个按钮,每个按钮的宽度是60像素,即使不考虑这三个按钮之间的间隙显示这三个按钮的宽度至少需要180像素,在默认情况下Width、MaxWidth、MinWidth的默认值分别是Auto(自动调整)、PositiveInfinity(正无穷大)、0.0,这样一来按照上面的规则会采取自动调整的方式。
StackPanel布局用法
StackPane是上面提到的几种布局中最简单的一种布局方式,它在一行或者一列中显示所有的子控件,默认情况下它是在一列中显示所有元素的,不过可以通过设置它的Orientation 属性为Horizontal以指示在一行中显示所有元素。
下面是一个使用StackPanel的简单例子:

<navigation:Page x:Class="SilverlightDemo1.StackPanelDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="StackPanelDemo Page"> <StackPanel Height="100" Name="stackPanel1" Width="200" Background="Yellow"> <Button Content="按钮一" Height="23" Name="button1" Width="100" /> <Button Content="按钮二" Height="23" Name="button2" Width="200" /> <Button Content="按钮三" Height="23" Name="button3" Width="400" /> </StackPanel> </navigation:Page>

这个Page的显示效果如下:
 
在上面的代码中我们设置StackPanel的Width为200,没有设置MaxWidth、MinWidth的值,最终实际显示宽度为200,因为此时MaxWidth和MinWidth都采用了默认值,因为这这三个值有冲突但是都在限制(没有找到具体对限制的定义,周公推测为MinWidth≤Width≤MaxWidth,如果您觉得周公的推测不正确,请告知以免误导大家,谢谢)之内,所以最终实际宽度为200。
如果设置StackPanel的Width、MaxWidth、MinWidth分别为200、400、100,最终实际显示宽度仍为200,原因同上,如下图所示:
 
如果设置StackPanel的Width、MaxWidth、MinWidth分别为200、100、100,最终实际显示宽度为100,这里MaxWidth和MinWidth都是100,而Width却是200不在限制之内,所以最终显示宽度为MinWidth设置的宽度,如下图所示:
 
如果设置StackPanel的Width、MaxWidth、MinWidth分别为200、400、500,最终实际显示宽度为500,这里MaxWidth和MinWidth分别是400和500,而Width却是200不在限制之内,所以最终显示宽度也为MinWidth设置的宽度,如下图所示:
 
Grid布局用法
Grid布局是Silverlight一种比较复杂的布局,它有点像我们HTML中的Table元素,将空间划分为行和列组成的单元格,在每个单元格中可以放置其它元素,下面是一个使用Grid的例子:

<navigation:Page x:Class="SilverlightDemo1.GridDemo1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="400" d:DesignHeight="300" Title="GridDemo1 Page"> <Grid x:Name="LayoutRoot" Background="Pink"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="200" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Button Content="按钮一" Height="23" HorizontalAlignment="Left" Name="button1" VerticalAlignment="Center" Width="75" Grid.Column="0" Grid.Row="0" /> <Button Content="按钮二" Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Center" Name="button2" VerticalAlignment="Top" Width="75" /> <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Center" Name="textBox1" VerticalAlignment="Center" Width="80" Text="文本框" /> </Grid> </navigation:Page>

它的显示效果如下:
 
当然Grid也可以像HTML中的Table一样跨行或者跨列,这需要通过设置控件的RowSpan或者ColumnSpan属性,下面就是一个例子:

<navigation:Page x:Class="SilverlightDemo1.GridDemo1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="400" d:DesignHeight="300" Title="GridDemo1 Page"> <Grid x:Name="LayoutRoot" Background="Pink"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition Height="200" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Button Content="按钮一" Height="220" HorizontalAlignment="Left" Name="button1" Width="75" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" /> <Button Content="按钮二" Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Center" Name="button2" VerticalAlignment="Top" Width="75" /> <TextBox Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" Height="23" Name="textBox1" VerticalAlignment="Center" Width="80" Text="文本框" /> <Button Content="按钮三" Grid.Column="2" Height="23" HorizontalAlignment="Left" Name="button3" VerticalAlignment="Top" Width="75" /> <Button Content="按钮四" Grid.Column="3" Grid.Row="1" Height="23" HorizontalAlignment="Left" Name="button4" VerticalAlignment="Top" Width="75" /> </Grid> </navigation:Page>

它的显示效果如下:
 
Canvas布局用法
相比Grid和Grid的布局方式来说,Canvas提供了另外一种途径来布置我们的控件,它采用了我们比较熟悉的利用坐标的方式的,在使用Canvas布局时可以设置每个控件Top和Left属性,也就是设置控件距离它所在的容器的距离,下面就是一个例子:

<navigation:Page x:Class="SilverlightDemo1.CanvasDemo1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="640" d:DesignHeight="480" Title="CanvasDemo1 Page"> <Canvas Height="240" Name="canvas1" Width="300" Background="Teal"> <Button Canvas.Left="40" Canvas.Top="161" Content="登录" Height="23" Name="button1" Width="75" /> <TextBlock Canvas.Left="40" Canvas.Top="56" Height="23" Name="textBlock1" Text="用户名" /> <TextBlock Canvas.Left="40" Canvas.Top="102" Height="23" Name="textBlock2" Text="密码" /> <Button Canvas.Left="183" Canvas.Top="161" Content="取消" Height="23" Name="button2" Width="75" /> <TextBox Canvas.Left="138" Canvas.Top="56" Height="23" Name="textBox1" Width="120" /> <PasswordBox Canvas.Left="138" Canvas.Top="102" Height="23" Name="passwordBox1" Width="120" /> </Canvas> </navigation:Page>

它的显示效果如下:
 
在代码中我们对用户名所对应的文本框的设置是:
<TextBox Canvas.Left="138" Canvas.Top="56" Height="23" Name="textBox1" Width="120" />
于是就会在距离Canvas顶部56、左边138处显示一个高度为23、宽度为120的文本框。
布局的综合使用
虽然在XAML中只能有一个顶级元素,但是这并不意味着在一个界面中只使用一种界面布局,我们完全可以在外层布局中嵌套内层布局,就像我们在HTML的Table中再次嵌套Table一样,下面是一个简单的例子:

<navigation:Page x:Class="SilverlightDemo1.Graphics" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation" d:DesignWidth="800" d:DesignHeight="600" Title="Chapter10 Page"> <StackPanel Width="800" Height="600" Orientation="Vertical"> <Canvas Width="800" Height="200" Background="White"> <Canvas.Resources> <Storyboard x:Name="myStroryboard"> <DoubleAnimation Storyboard.TargetName="myTransform" Storyboard.TargetProperty="Angle" From="0" To="360" Duration="0:0:5" RepeatBehavior="Forever"/> </Storyboard> </Canvas.Resources> <Image Canvas.Left="50" Canvas.Top="50" Height="100" Name="image01" Stretch="Fill" Width="100" Source="image/15.jpg" MouseEnter="Image_MouseEnter" MouseLeave="Image_MouseLeave"> <Image.RenderTransform> <RotateTransform x:Name="myTransform" Angle="15" CenterX="50" CenterY="50"></RotateTransform> </Image.RenderTransform> </Image> <Image Canvas.Left="350" Canvas.Top="0" Height="100" Name="image02" Stretch="Fill" Width="100" Source="image/15.jpg"> </Image> <Image Canvas.Left="350" Canvas.Top="0" Height="100" Name="image03" Stretch="Fill" Width="100" Source="image/15.jpg" Opacity="0.8"> <Image.RenderTransform> <TransformGroup> <ScaleTransform ScaleY="-0.75"></ScaleTransform> <TranslateTransform Y="180" X="30"></TranslateTransform> <SkewTransform AngleX="-15"></SkewTransform> </TransformGroup> </Image.RenderTransform> <Image.OpacityMask> <LinearGradientBrush StartPoint="0.5,0.0" EndPoint="0.5,1.0"> <GradientStop Offset="0.0" Color="#00000000"></GradientStop> <GradientStop Offset="1.0" Color="#FF000000"></GradientStop> </LinearGradientBrush> </Image.OpacityMask> </Image> </Canvas> <Canvas Width="800" Height="200"> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image31" Stretch="Fill" Width="200" Source="image/14.jpg" /> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image32" Stretch="Fill" Width="200" Source="image/14.jpg"> <Image.RenderTransform> <RotateTransform Angle="15" CenterX="0" CenterY="0"></RotateTransform> </Image.RenderTransform> </Image> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image33" Stretch="Fill" Width="200" Source="image/14.jpg"> <Image.RenderTransform> <RotateTransform Angle="30" CenterX="50" CenterY="300"></RotateTransform> </Image.RenderTransform> </Image> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image34" Stretch="Fill" Width="200" Source="image/14.jpg"> <Image.RenderTransform> <RotateTransform Angle="45" CenterX="0" CenterY="50"></RotateTransform> </Image.RenderTransform> </Image> </Canvas> <Canvas Width="800" Height="200"> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image1" Stretch="Fill" Width="200" Source="image/14.jpg" /> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image2" Stretch="Fill" Width="200" Source="image/14.jpg"> <Image.RenderTransform> <RotateTransform Angle="15"></RotateTransform> </Image.RenderTransform> </Image> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image3" Stretch="Fill" Width="200" Source="image/14.jpg"> <Image.RenderTransform> <RotateTransform Angle="30"></RotateTransform> </Image.RenderTransform> </Image> <Image Canvas.Left="100" Canvas.Top="10" Height="100" Name="image4" Stretch="Fill" Width="200" Source="image/14.jpg"> <Image.RenderTransform> <RotateTransform Angle="40"></RotateTransform> </Image.RenderTransform> </Image> </Canvas> </StackPanel> </navigation:Page>

它的显示效果如下:
 
总结:本篇主要讲述了Silverlight中几种常见的布局:StackPanel可以将控件按行或者按列布局,这是一种比较简单的布局方式;Grid可以采用类似于HTML中Table的方式布局,并且可以设置控件跨行或者跨列摆放;Canvas控件采用类似于坐标定位的方式对控件进行布局。还有一些布局在本篇中没有讲述,读者朋友可以在学习时借鉴这些知识来学习,其实利用这些布局已经足够实现复杂的界面了。
下一篇将讲述常用控件的学习。
周公(zhoufoxcn)
2010-10-11

转载于:https://www.cnblogs.com/zhoufoxcn/archive/2010/10/11/2515619.html

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

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

相关文章

pov-inc_yourself劳自己-懒惰的设计师的POV和一些Figma

pov-incAre you ready and lazy enough (you will fully understand with continue reading this)? Coffee and tea next to you? Alright. This article is going to (not) kick you in your a**. It will be a bit of ‘lesson learned’, for sure a bit of FIGMA, and a …

Geary 0.13.0 发布,GNOME 3 Email 客户端应用

百度智能云 云生态狂欢季 热门云产品1折起>>> Geary 0.13.0 发布了&#xff0c;Geary 是一个电子邮件应用&#xff0c;用于 GNOME 3 桌面版本&#xff0c;它允许阅读、查找和发送电子&#xff0c;并提供简洁、现代化的界面。这是一个重要的新版本&#xff0c;具有许…

轻型本地服务器_一小时超轻型漂移机

轻型本地服务器Iwas introduced to the world of Hyper Light Drifter through a series of visions — titans ravage a broken city, a shallow sea is stained red by floating corpses, a skinny dog leads me into the yawning abyss of a pillar in the center of the se…

聊聊前端面试

大家好&#xff0c;我是若川。今天分享一篇面试相关的文章。点击下方卡片关注我、加个星标&#xff0c;或者查看源码等系列文章。学习源码整体架构系列、年度总结、JS基础系列最近 Zoom 国内又开放招聘了&#xff0c;我们组有了前端的 HC&#xff0c;所以我也参加了几场面试。合…

mysql读写分离和分布式_MySQL主从复制与读写分离

MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践Mysql作为目前世界上使用最广泛的免费数据库&#xff0c;相信所有从事系统运维的工程师都一定接触过。但在实际的生产环境中&#xff0c;由单台Mysql作为独立的数据库是完全不能满足实际需求的&#xff0c;无论是在安全…

ux和ui_UI和UX设计师的10种软技能

ux和ui重点 (Top highlight)As designers, whether it be UI, UX, or Product Design, we tend to direct our focus and energy on developing and mastering tangible skills.作为设计师&#xff0c;无论是UI&#xff0c;UX还是产品设计&#xff0c;我们都将重点和精力放在开…

SQLServer中批量插入数据方式的性能对比 (转)

转自&#xff1a;http://www.cnblogs.com/wlb/archive/2010/03/02/1676136.html 昨天下午快下班的时候&#xff0c;无意中听到公司两位同事在探讨批量向数据库插入数据的性能优化问题&#xff0c;顿时来了兴趣&#xff0c;把自己的想法向两位同事说了一下&#xff0c;于是有了本…

VueConf China 2021 《Vue3生态进展-尤雨溪》 Reaction

大家好&#xff0c;我是若川。今天分享昨天Vueconf的一篇文章&#xff0c;来了解下Vue的生态进展。另外今晚7点&#xff0c;Vuebeijing社区邀请了尤大会在视频号直播&#xff0c;可以加我微信 ruochuan12&#xff0c;告诉观看地址提前预约。点击下方卡片关注我、加个星标&#…

Plsql运行mysql脚本_oracle中PLSQL语句

1.set autot off 禁止使用autotrace命令 set autot on 这个命令包括exp 和 stat(执行语句、生成explain plan、生成统计信息) set autot trace 不执行sql语句&#xff0c;但(生成explain plan、生成统计信息) set autot trace exp stat 与上句同 set autot trace st1.set autot…

2019年,你需要关注这些Node API和Web框架

对于Node.js框架和开源软件来说&#xff0c;2018年是非常有趣的一年。开发者社区讨论了企业赞助对开源项目的作用以及如何维护那些没有经济支持却有数百万人使用的项目。同样&#xff0c;安全问题也得到了极大关注&#xff0c;一些流行的Node/JS软件包被劫持&#xff0c;Github…

ai创造了哪些职业_关于创造职业的思考

ai创造了哪些职业When I was growing up, the idea of a creative career wasn’t an option.当我长大时&#xff0c;创意事业的想法不是一个选择。 I had enjoyed doodling, arts and crafts as a kid, so as I grew up, it was a natural transition into Photoshop and lat…

Windows Mobile,用C#更改网络连接(SSID、IP Address、Subnet Mask、Gatew... (转)

前几天在做一个改变PDA无线网络连接的SSID和IP的功能是发现了一个好东西OpenNETCF Framework使用OpenNETCF.Net包&#xff0c;实现了任意改变PDA无线网络连接的功能。并且不需要Reset PDA。现在正在做一个IP Manager For Windows Mobile的小程序。实现搜索当前网卡可见的SSID、…

一文读懂vuex4源码,原来provide/inject就是妙用了原型链?

1. 前言你好&#xff0c;我是若川&#xff0c;欢迎加我微信ruochuan12&#xff0c;加群长期交流学习。这是学习源码整体架构系列 之 vuex4 源码&#xff08;第十篇&#xff09;。学习源码整体架构系列文章(有哪些必看的JS库)&#xff1a;jQuery、underscore、lodash、sentry、v…

Spring4.3x教程之一IOCDI

SpringIOC也称为DI&#xff0c;对属性内容的注入可以通过属性的setXXX方法进行也可以通过构造方法进行&#xff0c;当然还可以使用工厂模式进行属性内容的注入。 什么是DI&#xff1f;什么是IOC&#xff1f; DI&#xff1a;Dependency Injection依赖注入 其实一个类中的属性就是…

战神4 幕后花絮 概念艺术_幕后花絮:品牌更新的背后

战神4 幕后花絮 概念艺术Under the Hood gives you an inside look at different parts of Waze — straight from the people working on them every day.在引擎盖下&#xff0c;您可以深入了解Waze的不同部分-直接来自每天进行工作的人员。 Traffic is the worst. It makes …

C#日期控件(js版)

js 脚本代码: <script type"text/javascript"> //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // 这是一个日历 Javascript 页…

python第三周测试_python第三周小测

1.读取一个文件&#xff0c;显示除了井号(#)开头的行意外的所有行# -*- coding: utf-8 -*-"""Created on Tue May 28 09:37:08 2019author: Omega_Sendoh"""#打开文件f open("install-sh","r")#读取文件的所有行&#xff0…

「Vueconf」探索 Vue3 中 的 JSX

大家好&#xff0c;我是若川。今天再分享 Vueconf 的一篇文章。另外 Vueconf 主办方提供的录播链接是&#xff1a; https://www.bilibili.com/read/mobile?id11408693&#xff0c;感兴趣可以复制观看。点击下方卡片关注我、加个星标。学习源码整体架构系列、年度总结、JS基础…

安卓加载asset中的json文件_Android解析Asset目录下的json文件

在app module中的src/main/assets目录下我们准备了两个json文件&#xff1a;destination.json如下&#xff1a;{"main/tabs/sofa": {"isFragment": true,"asStarter": false,"needLogin": false,"pageUrl": "main/tabs…

一文搞懂 Promise、Genarator、 Async 三者的区别和联系

非985/211大学毕业&#xff0c;软件工程专业&#xff0c;前端&#xff0c;坐标&#xff1a;北京工作三年多&#xff0c;第一家人数 30 多人的创业公司&#xff0c;1 年多。第二家属于前端技术不错的公司&#xff0c;2 年多。01我是一个喜欢在技术领域“折腾”的人&#xff0c;技…