[Xamarin]删除Android及iOS控制端堆栈
来源:互联网 发布:淘宝钻级店铺转让 编辑:程序博客网 时间:2024/06/02 02:26
Xamarin开发跨平台App新人一名。
最近组里Xamarin的项目中的一个要求,假设有 A->B->C->D 这样经由控制端跳页的流程,跳到D之后按返回键时希望能够直接返回到A。
做法就是跳到D之后删除之前在控制端堆栈中删除到A为止的控制端。
Android和iOS原生的实现代码已经有不少了,参考一些之后再这里贴一下Xamarin中C#的实现代码。
Android端:
我主要参考了以下这篇文章的Java代码
http://www.jianshu.com/p/263d40582a08
思路就是把所有的Activity(控制端类)抽象出一个基础Activity,让所有的Activity继承这个CommonActivity。
利用List以及多态性做成一个管理所有Activity的类ActivityCollector,然后添加一些需要的方法比如AddActivity,RemoveActivity。
public abstract class CommonActivity : Activity{ // 抽象控制基类}
public class ActivityCollector { private static List<CommonActivity> activities = new List<CommonActivity>(); public static List<CommonActivity> Activities { get { return activities; } } public static void AddActivity(CommonActivity activity) { activities.Add(activity); } public static void RemoveActivity(CommonActivity activity) { activities.Remove(activity); } public static void FinishAll() { foreach(CommonActivity activity in activities) { if (!activity.IsFinishing) { activity.Finish(); } } } }
那么如何利用ActivityCollector来管理控制堆栈呢?
简单地说就是要结合AndroidApp生命周期,在某个Activity被创建或是被销毁时同步更新ActivityCollector中的内容,
这就需要在CommonActivity的OnCreate和OnDestroy中添加一些代码
public abstract class CommonActivity : Activity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); ActivityCollector.AddActivity(this); } protected override void OnDestroy() { base.OnDestroy(); ActivityCollector.RemoveActivity(this); }}
回到项目要求。在页面D生成时,删除堆栈中直到页面A的所有Activity,就能在D页面按下返回键时直接返回到A页面。
如果有必要可能需要加一些判断语句判断是不是从C页面跳转到D页面防止误删。
public class ActivityOfD : Activity{ protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); // 可以根据需要添加一些判断语句 for (int i = ActivityCollector.Activities.Count - 2; i >= 0; i--) { if ( !(ActivityCollector.Activities[i] is ActivityOfA) ) { ActivityCollector.Activities[i].Finish(); } } }}
iOS端:
iOS端的做法和Android端不太一样。iOS的SDK已经提供了控制端堆栈管理API:UINavigationController类,而Xamarin也已经帮我们包装成了C#类,可以直接调用。
我主要参考这篇文章的部分代码。
http://www.jianshu.com/p/90a104ac6633
C#中无法将NSMutableArray类强制转换成ViewController数组(应该说C#的默认数组都是继承自Array类而不是NSArray类),因此我们用List来处理,代码如下。
public class ViewControllerOfD : CommonViewController{ public override void ViewWillAppear (bool animated) { base.ViewWillAppear (animated); // 可以根据需要添加一些判断语句 List<UIViewController> controllers = new List<UIViewController> (NavigationController.ViewControllers); for (int i = controllers.Count - 2; i >= 0; i--) { if( !(controllers[i] is ViewControllerOfA)) { controllers.RemoveAt(i); } } NavigationController.SetViewControllers(controllers.ToArray(), true); }}
NavigationControler.ViewControllers = controllers.ToArray();
这样做产生了一个问题,虽然画面可以按照预想在页面D按back键时直接跳转回页面A,但屏幕上方的导航栏却依然还是退到页面C的导航栏,需要多次按下back键才能回退到页面A的导航栏。
百思不得其解之时得到了前辈的指点,我查阅了iOS的官方开发者文档
https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html
以及UINavigationController类的文档
https://developer.apple.com/documentation/uikit/uinavigationcontroller
如上官方示意图表示了NavigationController的构成。原来ViewControllers的堆栈与NavigationBar(导航栏)是NavigationController下不同的成员。
所以只去改掉ViewControllers的话当然不会影响到导航栏。但当我试图直接改变UINavigationBar.Item时,又会在运行中报出“Cannot set items managed by viewController”的异常。
再一查文档发现原来就如字面意思iOS SDK规定不允许直接修改ViewController管理下的导航栏控件。
那么该怎么办呢?
其实很简单,NavigationController里提供了设置ViewController堆栈的方法SetViewController,该方法会自动帮我们一起设置好相应的导航栏堆栈。最终的代码如之前所示。
iOS端的问题卡了有半天才解决,感觉自己还是对iOS原生应用开发不熟悉,还需要多积累经验和多读官方文档。
- [Xamarin]删除Android及iOS控制端堆栈
- Xamarin.Android 4.8.00013 & Xamarin.iOS 1.3.250.0 Patched Executable
- xamarin c#开发ios/android 应用
- Xamarin for Android/IOS离线安装说明
- xamarin c#开发ios/android 应用
- xamarin c#开发ios/android 应用
- Xamarin.Android开发及常见问题的解决
- Android&iOS崩溃堆栈上报
- Android&iOS崩溃堆栈上报
- Android-activity堆栈及管理
- Xamarin.iOS启动图片过渡及广告展示
- Xamarin.iOS设备标识OpenUDID(及UMID简介)
- xamarin.ios中设置button的边框及样式
- Android Fragment跳转堆栈内存控制
- LINK: WinRT, Xamarin.Android, Xamarin.iOS - How to implement a "pull-to-refresh" list
- Xamarin Evolve 2013:竭尽全力让C#服务iOS与Android
- [转]Xamarin-Visual Studio开发iOS、Android应用
- Xamarin体验:使用C#开发iOS/Android应用
- FZU 2282 错排问题dp
- python 网络爬虫报错“UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position”解决方案
- 语义化命名标签规则
- scala函数
- Java程序输出到JSP页面
- [Xamarin]删除Android及iOS控制端堆栈
- Android Studio debugger 灵活使用
- java 同步与异步的区别
- Cocos2d-js
- C语言简单应用
- vs2015Visual Studio Installer打包安装项目.net framework 的存放路径
- Python入门系列——第8篇
- java堆栈
- Linux终端tty设备驱动