引言
文件读写
参考:
- 使用 Xamarin.Android 对外部存储进行的文件访问 - Xamarin | Microsoft Docs
- Xamarin 中的文件系统访问 - Xamarin | Microsoft Docs
- 关于xamarin.forms Android创建文件与写文件 (ftp) - 懒猫口米 - 博客园
外部读写
应用可以在外部存储上保留两种不同类型的文件:
- 专用 文件 – 专用文件是特定于应用程序的文件(但仍然全局可读且全局可写)。 Android 期望专用文件存储在外部存储上的特定目录中。 尽管这些文件称为“专用”,但它们仍然可见,并且可由设备上的其他应用访问,Android 并没有对它们提供任何特殊保护。
// 专用外部存储目录
// /storage/emulated/0/Android/data/com.companyname.app/files/
Android.Content.Context.GetExternalFilesDir(string type)
- 公共 文件 – 这些文件不被视为特定于应用程序,可自由共享。
// 主外部存储目录
// /storage/emulated/0/
Android.OS.Environment.ExternalStorageDirectory
代码语言:javascript复制Android 将外部存储视为危险权限,这通常要求用户授予其访问资源的权限。 用户可以随时撤销此权限。 这意味着在进行任何文件访问之前都应执行运行时权限请求。 应用会被自动授予读取和写入其自己的专用文件的权限。 在用户授予了权限之后,应用可以读取和写入属于其他应用的专用文件。
//global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath :得到安卓的根目录
//Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)::得到安卓data目录
var path = global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
// 创建文件
System.IO.Directory.CreateDirectory(path);
外部存储权限
所有 Android 应用都必须在 AndroidManifest.xml 中为外部存储声明两个权限之一。
若要标识权限,必须将以下两个 uses-permission
元素之一添加到 AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
注意:下面有误
如上,在安卓项目里有个Properties的文件下有个AndroidManifest.xml的文件。在
代码语言:javascript复制<application android:label="cardionNet2.Android"></application>
下加
代码语言:javascript复制这个目测有误,直接加进去就是了,不需要放在这个;里
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.demoapp" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="DemoApp.Android" android:theme="@style/MainTheme"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
</manifest>
代码语言:javascript复制写入外部存储之前的第一步是检查它是可读或可写。
Android.OS.Environment.ExternalStorageState
属性保存标识外部存储状态的字符串。 此属性会返回表示状态的字符串。
bool isReadonly = Environment.MediaMountedReadOnly.Equals(Environment.ExternalStorageState);
bool isWriteable = Environment.MediaMounted.Equals(Environment.ExternalStorageState);
完全限定
代码语言:javascript复制bool isReadonly = Android.OS.Environment.MediaMountedReadOnly.Equals(Android.OS.Environment.ExternalStorageState);
bool isWriteable = Android.OS.Environment.MediaMounted.Equals(Android.OS.Environment.ExternalStorageState);
应用生命周期
参考:
- Xamarin.Forms 应用生命周期 - Xamarin | Microsoft Docs
Application
基类提供下列功能:
- 生命周期方法
OnStart
、OnSleep
和OnResume
。 - 页导航事件
PageAppearing
、PageDisappearing
。 - 模式导航事件
ModalPushing
、ModalPushed
、ModalPopping
和ModalPopped
。
生命周期方法
Application
类包含三个虚拟方法,可以替代以响应生命周期更改:
OnStart
- 在启动应用程序时调用它。OnSleep
- 每当应用程序转入后台时调用它。OnResume
- 应用程序发送到后台后恢复时调用。
布局
参考:
- 搞懂Xamarin.Forms布局,看这篇应该就够了吧 - 何旭 - 博客园
- JoesWeek/Cnblogs: 博客园第三方Android客户端,Xamarin App,Material Design风格
- jsuarezruiz/awesome-xamarin-forms: A curated list of awesome Xamarin.Forms libraries and resources
- Xamarin.Forms UI Snippets
JarBinding Bugly
Xamarin.Forms Shell
参考:
- 创建 Xamarin.Forms Shell 应用程序 - Xamarin | Microsoft Docs
- Xamarin.Forms 第28局:Shell - 简书
- Xamarin.FormsShell基础教程(9)Shell相关类体系 - 大学霸 - 博客园
视觉层次结构
代码语言:javascript复制Shell -> FlyoutItem / TabBar -> Tab -> ShellContent -> ContentPage FloutItem: 浮出控件 TabBar: 底部选项卡栏 Tab: 分组内容 当
Tab
中存在多个ShellContent
,时,会在内部再次分布, 若Tab
父级是TabBar
,则会在那个页面显示 顶部导航选项卡,以对应多个ShellContent
, 若Tab
父级是FlyoutItem
,则会在对应条下显示多个子条 (ShellContent
) 若在FloutItem / TabBar
中直接写ShellContent
,则会将每个ShellContent
隐式包裹在一个Tab
中补充: 和
TabBar
类是ShellItem
类的别名,而Tab
类是ShellSection
类的别名。 因此,也可以 Shell -> FlyoutItem / ShellItem -> ShellSection -> ShellContent -> ContentPage 因此,在为FlyoutItem
对象创建自定义呈现器时应重写CreateShellItemRenderer
方法,在为Tab
对象创建自定义呈现器时应重写CreateShellSectionRenderer
方法。
<!-- When the Flyout is visible this will be a menu item you can tie a click behavior to -->
<MenuItem Text="Logout" StyleClass="MenuItemLayoutStyle" Clicked="OnMenuItemClicked">
</MenuItem>
侧边浮出注销按钮
当 侧边 (Flyout) 浮出显示 时,MenItem
就会显示
MenuItem
: 浮出控件的菜单项
浮出控件
参考:
- Xamarin.Forms Shell 浮出控件 - Xamarin | Microsoft Docs
代码语言:javascript复制可以通过图标或从屏幕的一侧轻扫来访问它。 浮出控件由可选标头、浮出控件项、可选菜单项和可选页脚组成:
<!--
When the Flyout is visible this defines the content to display in the flyout.
FlyoutDisplayOptions="AsMultipleItems" will create a separate flyout item for each child element
https://docs.microsoft.com/dotnet/api/xamarin.forms.shellgroupitem.flyoutdisplayoptions?view=xamarin-forms
-->
<FlyoutItem Title="首页" Icon="icon_about.png">
<ShellContent Route="HomePage" ContentTemplate="{DataTemplate local:HomePage}" />
</FlyoutItem>
<FlyoutItem Title="列表" Icon="icon_feed.png">
<ShellContent Route="ItemsPage" ContentTemplate="{DataTemplate local:ItemsPage}" />
</FlyoutItem>
<FlyoutItem Title="设置" Icon="icon_setting.png">
<ShellContent Route="SettingPage" ContentTemplate="{DataTemplate local:SettingPage}" />
</FlyoutItem>
隐式转换
代码语言:javascript复制<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Xaminals.Controls"
xmlns:views="clr-namespace:Xaminals.Views"
x:Class="Xaminals.AppShell">
<FlyoutItem Title="Cats"
Icon="cat.png">
<Tab>
<ShellContent ContentTemplate="{DataTemplate views:CatsPage}" />
</Tab>
</FlyoutItem>
<FlyoutItem Title="Dogs"
Icon="dog.png">
<Tab>
<ShellContent ContentTemplate="{DataTemplate views:DogsPage}" />
</Tab>
</FlyoutItem>
</Shell>
等同于下方:
代码语言:javascript复制<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:Xaminals.Controls"
xmlns:views="clr-namespace:Xaminals.Views"
x:Class="Xaminals.AppShell">
<ShellContent Title="Cats"
Icon="cat.png"
ContentTemplate="{DataTemplate views:CatsPage}" />
<ShellContent Title="Dogs"
Icon="dog.png"
ContentTemplate="{DataTemplate views:DogsPage}" />
</Shell>
此隐式转换自动将每个 ShellContent
对象包装在 Tab
对象中,而 Tab
则包装在 FlyoutItem
对象中。
即
Shell
中默认FlyoutItem
,FlyoutItem
/TabBar
中默认Tab
备注 子类化的
Shell
对象中的所有FlyoutItem
对象都会自动添加到Shell.FlyoutItems
集合, 该集合定义将在浮出控件中显示的项的列表。
定义 FlyoutItem 外观
通过将 Shell.ItemTemplate
附加属性设置为 DataTemplate
可自定义每个 FlyoutItem
的外观:
<Shell ...>
...
<Shell.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="0.2*,0.8*">
<Image Source="{Binding FlyoutIcon}"
Margin="5"
HeightRequest="45" />
<Label Grid.Column="1"
Text="{Binding Title}"
FontAttributes="Italic"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
</Shell.ItemTemplate>
</Shell>
FontAttributes="Italic"
此示例以斜体显示每个FlyoutItem
对象的标题:
Shell.ItemTemplate
是一个附加属性,因此可将不同的模板附加到特定的 FlyoutItem
对象。
替换浮出控件内容
浮出项表示浮出控件内容,可以选择将其替换为你自己的内容,方法是将 Shell.FlyoutContent
可绑定属性设置为 object
:
<Shell ...
x:Name="shell">
...
<Shell.FlyoutContent>
<CollectionView BindingContext="{x:Reference shell}"
IsGrouped="True"
ItemsSource="{Binding FlyoutItems}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"
TextColor="White"
FontSize="Large" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Shell.FlyoutContent>
</Shell>
在此示例中,将浮出控件内容替换为
CollectionView
,它显示了FlyoutItems
集合中每个项的标题。
此外,可以通过将 Shell.FlyoutContentTemplate
可绑定属性设置为 DataTemplate
来定义浮出控件内容:
<Shell ...
x:Name="shell">
...
<Shell.FlyoutContentTemplate>
<DataTemplate>
<CollectionView BindingContext="{x:Reference shell}"
IsGrouped="True"
ItemsSource="{Binding FlyoutItems}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"
TextColor="White"
FontSize="Large" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</DataTemplate>
</Shell.FlyoutContentTemplate>
</Shell>
FlyoutItem 选择
场景: 有时候,默认并不需要显示第一个
首次运行使用浮出控件的 Shell 应用程序时,Shell.CurrentItem
属性将设置为子类化的 Shell
对象中的第一个 FlyoutItem
对象。 但是,此属性可以设置为另一个 FlyoutItem
,如以下示例所示:
<Shell ...
CurrentItem="{x:Reference aboutItem}">
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
...
</FlyoutItem>
<ShellContent x:Name="aboutItem"
Title="About"
Icon="info.png"
ContentTemplate="{DataTemplate views:AboutPage}" />
</Shell>
此示例将
CurrentItem
属性设置为名为aboutItem
的ShellContent
对象,这将导致选中并显示该对象。 在此示例中,隐式转换用于将ShellContent
对象包装在Tab
对象中,后者包装在FlyoutItem
对象中。
假设有一个名为 aboutItem
的 ShellContent
对象,则等效的 C# 代码为:
CurrentItem = aboutItem;
在此示例中,CurrentItem
属性是在子类化的 Shell
类中设置的。 或者,可通过 Shell.Current
静态属性在任何类中设置 CurrentItem
属性:
Shell.Current.CurrentItem = aboutItem;
FlyoutItem 可见性
浮出项在浮出控件中默认可见。 但是,可以使用 FlyoutItemIsVisible
属性将项隐藏在浮出控件中,并使用 IsVisible
属性将其从浮出控件中删除:
- 类型为
bool
的FlyoutItemIsVisible
指示项是否已隐藏在浮出控件中但仍可以通过GoToAsync
导航方法进行访问。 此属性的默认值为true
。 - 类型为
bool
的IsVisible
指示是否应从可视化树中移除项,从而不在浮出控件中显示。 它的默认值为true
。
备注 还有一个
Shell.FlyoutItemIsVisible
附加属性,可在FlyoutItem
、MenuItem
、Tab
和ShellContent
对象上设置该属性。
以编程方式打开和关闭浮出控件
代码语言:javascript复制<Shell ...
FlyoutIsPresented="{Binding IsFlyoutOpen}">
</Shell>
代码语言:javascript复制Shell.Current.FlyoutIsPresented = false;
底部导航栏
参考:
- Xamarin.Forms Shell 选项卡 - Xamarin | Microsoft Docs
<TabBar>
<ShellContent Title="About" Icon="icon_about.png" Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
<ShellContent Title="Browse" Icon="icon_feed.png" ContentTemplate="{DataTemplate local:ItemsPage}" />
</TabBar>
目测,不加 Title
, Icon
就会隐藏起来,那么这个时候就只能通过代码导航到这里了。
<!--
If you would like to navigate to this content you can do so by calling
await Shell.Current.GoToAsync("//LoginPage");
-->
<TabBar>
<ShellContent Route="LoginPage" ContentTemplate="{DataTemplate local:LoginPage}" />
</TabBar>
单页
代码语言:javascript复制
TabBar
中只有 一个ShellContent
,就不会显示底部选项卡导航栏
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:Xaminals.Views"
x:Class="Xaminals.AppShell">
<TabBar>
<Tab>
<ShellContent ContentTemplate="{DataTemplate views:CatsPage}" />
</Tab>
</TabBar>
</Shell>
底部选项卡
倘若单个 TabBar
对象中有多个 Tab
对象,则 Tab
对象呈现为底部选项卡:
类型为 string
的 Title
属性,可定义选项卡标题。 类型为 ImageSource
的 Icon
属性,可定义选项卡图标:
如果 TabBar
上有五个以上的选项卡,则显示“更多”选项卡,可用于访问其他选项卡:
底部和顶部选项卡
如果一个 Tab
对象中存在多个 ShellContent
对象时,则将在底部选项卡中添加一个顶部选项卡栏,通过该选项卡栏可以导航 ContentPage
对象:
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:Xaminals.Views"
x:Class="Xaminals.AppShell">
<TabBar>
<Tab Title="Domestic"
Icon="paw.png">
<ShellContent Title="Cats"
ContentTemplate="{DataTemplate views:CatsPage}" />
<ShellContent Title="Dogs"
ContentTemplate="{DataTemplate views:DogsPage}" />
</Tab>
<Tab Title="Monkeys"
Icon="monkey.png">
<ShellContent ContentTemplate="{DataTemplate views:MonkeysPage}" />
</Tab>
</TabBar>
</Shell>
选项卡选择
首次运行使用选项卡栏的 Shell 应用程序时,Shell.CurrentItem
属性将设置为子类化的 Shell
对象中的第一个 Tab
对象。 但是,此属性可以设置为另一个 Tab
,如以下示例所示:
<Shell ...
CurrentItem="{x:Reference dogsItem}">
<TabBar>
<ShellContent Title="Cats"
Icon="cat.png"
ContentTemplate="{DataTemplate views:CatsPage}" />
<ShellContent x:Name="dogsItem"
Title="Dogs"
Icon="dog.png"
ContentTemplate="{DataTemplate views:DogsPage}" />
</TabBar>
</Shell>
补充
同时显示 浮出、底部导航栏
参考:
- Xamarin Form Shell:弹出型v/s TabBar - 我爱学习网
- app shell - 在 Xamarin.Forms 中同时使用 TabBar 和 Flyout - 爱编程的大狗
代码语言:javascript复制没办法直接在Shell中,同时显式定义
FlyoutItem
和TabBar
只能通过FlyoutItem
隐式达到效果注意: 并没有在
FlyoutItem
上使用FlyoutDisplayOptions="AsMultipleItems"
, 这会导致首页、游戏、频道、动态
也显示在侧边浮出栏
<!-- 显示在底部导航栏 -->
<FlyoutItem Title="首页" Icon="icon_about.png">
<Tab Title="首页" Icon="icon_about.png">
<ShellContent x:Name="HotPageItem"
Title="热门"
ContentTemplate="{DataTemplate local:HotPage}" />
<ShellContent x:Name="RecomPageItem"
Title="推荐"
ContentTemplate="{DataTemplate local:RecomPage}" />
<ShellContent x:Name="LastPageItem"
Title="最新"
ContentTemplate="{DataTemplate local:LastPage}" />
</Tab>
<Tab Title="游戏" Icon="icon_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
<Tab Title="频道" Icon="icon_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
<Tab Title="动态" Icon="icon_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
</FlyoutItem>
<!-- 显示在侧边浮出栏 -->
<FlyoutItem Title="关于" Icon="icon_about.png">
<ShellContent ContentTemplate="{DataTemplate local:HomePage}" />
</FlyoutItem>
<FlyoutItem Title="设置" Icon="icon_setting.png">
<ShellContent ContentTemplate="{DataTemplate local:SettingPage}" />
</FlyoutItem>
补充
让首页默认选中 第二个 推荐
,在 首页
项使用 CurrentItem
<Tab Title="首页" Icon="icon_about.png" CurrentItem="{x:Reference RecomPageItem}">
<ShellContent x:Name="HotPageItem"
Title="热门"
ContentTemplate="{DataTemplate local:HotPage}" />
<ShellContent x:Name="RecomPageItem"
Title="推荐"
ContentTemplate="{DataTemplate local:RecomPage}" />
<ShellContent x:Name="LastPageItem"
Title="最新"
ContentTemplate="{DataTemplate local:LastPage}" />
</Tab>
Shell 添加手势、滑动
参考:
- c# - 在 Xamarin Shell 中的 tabbar 页面之间滑动_c _帮酷编程问答
- [Feature] Swipe left/right to navigate between upper/bottom tabs of Shell · Issue #12435 · xamarin/Xamarin.Forms
官方没有实现 底部选项导航栏(包括子项顶部导航栏) 滑动动画切换页面 见 [Feature] Swipe left/right to navigate between upper/bottom tabs of Shell · Issue #12435 · xamarin/Xamarin.Forms
Xamarin.Forms 滑动、手势
参考:
- softlion/XamarinFormsGesture: Xamarin Form Gesture Effects
- Xamarin.Forms ScrollView - Xamarin | Microsoft Docs
- Xamarin.Forms CarouselView 滚动 - Xamarin | Microsoft Docs
滚动视图 ScrollView 在Xamarin.Forms中,滚动视图ScrollView用来实现长内容的滚动显示。虽然ScrollView的Content属性只能设置一个值,即ScrollView只能包含一个子元素,但它实际是一个布局控件,一个特殊的布局元素。 在使用的时候,ScrollView要求父容器给它分配固定的大小,同时子元素并且有固定的大小。这样,ScrollView才能根据各自大小计算滚动量。ScrollView不仅提供了当前滚动量ScrollX和ScrollY,还提供内容总量ContentSize。这样,开发者就可以计算滚动进度,显示给用户。同时,利用ScrollView提供的滚动结束事件Scrolled,可以提示用户,或者加载新的内容。
Q&A
补充
解析 Markdown
参考:
- NumerousTechnology/MdView: The flexible Markdown control for Xamarin.Forms.
- dotnet-ad/MarkdownView: Native markdown rendering on top of Xamarin.Forms & Markdig.
- SuavePirate/MarkdownTextView: A Xamarin.Forms component to display markdown text in a TextView
V**
参考:
- c# - V**client in xamarin - Stack Overflow
- vpnhood/VpnHood: Undetectable Fast Portable V**
内网穿透
参考:
- FastTunnel/FastTunnel: 开源免费跨平台的内网穿透工具 远程内网计算机 域名访问内网站点 反向代理内网服务 花生壳 端口转发 http代理 微信 小程序 like ngrok and frp. NAT ssh proxy tunnel reverse-proxy
自动升级
参考:
- C# Xamarin For Android自动升级项目实战 - 跟着阿笨一起玩.NET - 博客园
- xamarin.forms 版本自动更新(针对android) - sxsean - 博客园
- XamarinAndroid获取当前版本号-Android-CSDN问答
- C#使用Xamarin开发可移植移动应用终章(11.获取设备信息与常用组件,开源一个可开发模版.) - GuZhenYin - 博客园
- Android开发之自带下载器DownloadManager的使用示例代码_Android_脚本之家
- android 8.0以上无法唤起apk安装界面问题_vulgar_rabbit的博客-CSDN博客
- Android7.0、8.0安装apk以及安装apk弹出“选择打开方式”的解决方案_Lone_Star斌 的博客-CSDN博客
- 系统自带DownloadManager详解_Demi的博客-CSDN博客
- WVector/AppUpdate: