具有透明背景的 iOS Action 应用扩展?
Posted
技术标签:
【中文标题】具有透明背景的 iOS Action 应用扩展?【英文标题】:iOS Action app extension with transparent background? 【发布时间】:2016-08-01 21:50:50 【问题描述】:我正在尝试用最少的 UI 制作 ios Action 应用扩展。基本上它只会显示一个进度指示器,直到操作完成。我只是希望能够为视图设置动画,使其从顶部向下滑动,然后在动作完成后向上滑动。如果有人熟悉 Instapaper 的 Share 扩展,那么这就是我正在寻找的那种基本 UI。
问题是,当我尝试复制此功能时 - 我只有一个小的 UIView
从顶部向下动画 - 我的视图后面出现黑色背景。我不知道如何使背景透明,以便我的视图后面的东西仍然可见。有谁知道怎么做?
作为起点,我只是使用 Xcode 创建的默认动作扩展模板...
-
在 Xcode 中创建一个新的 iOS 应用项目。
添加新目标 -> 操作扩展。
在
ActionViewController.m
文件中添加viewWillAppear
方法来为视图设置动画(使用1 秒动画以便容易看到黑色背景):
代码:
- (void)viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
CGRect currFrame = self.view.frame;
CGRect newFrame = currFrame;
newFrame.origin.y -= newFrame.size.height;
self.view.frame = newFrame;
[UIView animateWithDuration:1.0 animations:^
self.view.frame = currFrame;
];
当它运行时,视图动画从顶部向下滑动。但是,您看到的不是调用应用程序的 UI,而是黑色背景。
我尝试了很多方法 - 更改 modalPresentationStyle
(似乎没有做任何事情),将整个视图设置为隐藏(这只会使整个屏幕变黑)等等。
作为参考,这里使用的是 iOS 9.3.2 和 Xcode 7.3.1。
【问题讨论】:
你用故事板试过了吗? @RomOne,到底试过什么? 抱歉,我的意思是你有没有试过不使用动画,而是使用故事板将你的子视图添加到扩展控制器? 有没有动画都没有区别。我的主视图后面的任何东西都是黑色的。如果我将主视图的背景设置为透明,则结果为黑色。我仍然不确定您对使用情节提要添加子视图是什么意思。如果您使用我上面的说明创建应用程序扩展,它将创建一个故事板。向该故事板添加子视图并没有什么不同。到目前为止,我所做的一切都不会允许调用应用程序的 UI 显示在我的主视图的 UI 后面。我的主视图“后面”的任何东西总是呈现黑色。 【参考方案1】:据我了解Apple docs
在 iOS 中,Action 扩展:
帮助用户以不同的方式查看当前文档 始终出现在操作表或全屏模式视图中 仅当主机应用明确提供时才接收选定的内容
Action 扩展总是出现在 iPhone 上的全屏视图中这一事实可能意味着没有透明背景。
我确信 Share 扩展程序可以根据您的需要进行动画处理(我自己完成了)并具有透明背景。这就是 Instapaper 的 Share 扩展运行良好的原因。
【讨论】:
我认为您在这里有所作为。将扩展程序从操作扩展程序更改为共享扩展程序可以使调用应用程序 UI 在我的 UI 下方可见。我认为操作表不需要全屏?但也许那是错误的。 对我来说,操作表是 UIAlertController 的 .ActionSheet 样式。我在这里可能是错的,但是一切都表明没有办法在下面有一个带有 UI 的自定义视图。我查看了“前 11 个 iOS 操作扩展”(imore.com/amazing-action-extensions-iphone),它们都是全屏的。 看起来这是正确的答案。使用 Share 扩展允许调用应用程序的 UI 保持可见。只将扩展类型从 Share (com.apple.share-services
) 更改为 Action (com.apple.ui-services
) 会导致黑色背景。【参考方案2】:
你面临两个问题:
1。当您呈现视图控制器时,默认行为是控制器是全屏上下文。这就是您看到黑屏的原因。
2。当控制器全屏显示时,您正在尝试更改 self.view.frame。
然而,有一种方法可以通过以下三种方式之一实现您正在寻找的这种行为:
一个。将“modalPresentationStyle”指定为“UIModalPresentationOverCurrentContext”并将呈现控制器设置为“definesPresentationContext”。 这样,当您呈现控制器时,呈现控制器将位于被呈现控制器的后面。
在更改 self.view.frame 时,您将设置 self.view 背景颜色清除,并添加子视图并将其用作背景视图:
//Presenting view controller:
-(void) presentPopUpViewController
self.definesPresentationContext = YES; //self is presenting view controller
self.presentedVC.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:self.presentedVC animated:NO completion:nil];
//Presented view controller:
-(void) viewDidLoad
[super viewDidLoad];
CGRect currFrame = self.view.frame;
CGRect newFrame = currFrame;
newFrame.origin.y -= newFrame.size.height;
self.myBackroundView = [[UIView alloc] init];
self.myBackroundView.backgroundColor = [UIColor yellowColor];
self.myBackroundView.frame = newFrame;
[self.view addSubview:self.myBackroundView];
self.view.backgroundColor = [UIColor clearColor];
- (void)viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
[UIView animateWithDuration:5.0 animations:^
self.myBackroundView.frame = self.view.frame;
];
B。将呈现的视图控制器添加为子视图控制器。这样生命周期保持不变,但您可以将 I's 视图添加为子视图,并更改 I's 框架。
//呈现视图控制器:
-(void) presentChildViewController
[self addChildViewController:self.presentedVC];
[self.view addSubview:self.presentedVC.view];
[self.presentedVC didMoveToParentViewController:self];
//Presented view controller:
- (void)viewWillAppear:(BOOL)animated
[super viewWillAppear:animated];
CGRect currFrame = self.view.frame;
CGRect newFrame = currFrame;
newFrame.origin.y -= newFrame.size.height;
self.view.frame = newFrame;
[UIView animateWithDuration:1.0 animations:^
self.view.frame = currFrame;
];
C。不要使用 UIViewController,使用 UIView。使用“装饰器”对象,将您希望视图显示在其上的 ViewController 传递给它,“装饰器”会将视图添加为子视图,并处理动画。这种情况不需要举例。
【讨论】:
我试过 A 但这不起作用。对于作为 App Extension 的初学者,我无法控制呈现控制器。我确实尝试访问parentViewController
和 presentingViewController
以便我可以启用 definesPresentationContext
但这似乎没有任何作用。并且将背景颜色更改为清除不会让调用应用程序显示出来,它只会导致黑色。
B 和 C 也不起作用,因为 App Extension 无法控制视图控制器的呈现方式。应用扩展的入口点是您提供一个视图控制器。据我所知,该视图控制器的呈现方式和时间超出了您的控制范围。
@Cutterpillow 我不明白这是在扩展中呈现的第一个视图控制器。你正在寻找的东西是不可能的。对不起。【参考方案3】:
在视图尚未出现时启动动画是错误的。请您在 viewDidAppear 中尝试相同的代码。 此外,动画主视图控制器的视图将使底层可见,因此您必须在视图控制器的主视图之上使用另一个视图,如下所示:
UIView *progressView = [[UIView alloc] init];
progressView.frame = self.view.bounds;
progressView.backgroundColor = [UIColor redColor];
[self.view addSubView:progressView];
【讨论】:
没有区别。与以前相同的行为。 抱歉,没有注意到,您正在为视图控制器的主视图设置动画。您应该在此基础上创建另一个视图,如下所示: UIView *progressView = [[UIView alloc] init]; progressView.frame = self.view.bounds; progressView.backgroundColor = [UIColor redColor]; [self.view addSubView:progressView];然后你就可以执行这些动画了 所有这一切让我做的就是在我的视图控制器的视图(主视图)之上放置另一个视图。所以新视图将出现在主视图的顶部。但是,我仍然无法显示主视图背后的内容——即启动我的扩展的应用程序的内容。如果我使主视图透明或隐藏,那么它显示的只是黑色背景,上面是新视图。 一旦控制器出现,底层层次结构将被覆盖。有 3 个选项: 1. 您可能想使用容器视图来移动最顶层的控制器。主控制器仍然可见。 2. 在不使用情节提要的情况下,将最顶层控制器的视图插入到主控制器视图之上。 3. 只在主控制器之上使用视图,不添加进度控制器你更喜欢哪种方案?以上是关于具有透明背景的 iOS Action 应用扩展?的主要内容,如果未能解决你的问题,请参考以下文章