问题
I’m trying to make an iOS Action app extension with minimal UI. Basically it would just show a progress indicator until the action completed. I just want to be able to animate the view so that it slides down from the top & then slides back up when the action has completed. If anyone is familiar with Instapaper’s Share extension, then that’s the kind of basic UI I’m looking for.
The problem is that when I try to duplicate this functionality - I just have a small UIView
that animates down from the top - I get a black background behind my view. I can’t figure out how to make that background transparent so that the stuff behind my view is still visible. Does anyone know how to do this?
As a starting point I’m just using the default Action Extension template that’s created by Xcode...
- Create a new iOS app project in Xcode.
- Add a new target -> Action Extension.
- In the
ActionViewController.m
file add aviewWillAppear
method to animate the view (using a 1 second animation so that the black background is easily seen):
Code:
- (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;
}];
}
When this is run the view is animated sliding down from the top. However rather than seeing the UI of the calling App all you see is a black background.
I’ve tried a number of things - changing the modalPresentationStyle
(doesn’t seem to do anything), setting the entire view to hidden (this just makes the whole screen black), etc.
For reference this is using iOS 9.3.2 and Xcode 7.3.1.
回答1:
From what I understand from Apple docs
In iOS, an Action extension:
- Helps users view the current document in a different way
- Always appears in an action sheet or full-screen modal view
- Receives selected content only if explicitly provided by the host app
The fact that the Action extension always appear in a full-screen view on an iPhone might mean that there's no way of having a transparent background.
I am certain that a Share extension can be animated (I've done it myself) how you want it and have a transparent background. That's why Instapaper's Share extension works nicely.
回答2:
You are facing two problems:
1. When you present a view controller, the default behavior is the controller is full screen context. That is the reason you see a black screen.
2. You are trying to change self.view.frame when the controller is presented on full screen.
Yet there is a way to achieve this kind of behavior you are looking for, in one of three ways:
A. Specify "modalPresentationStyle" to "UIModalPresentationOverCurrentContext" and set the presenting controller to "definesPresentationContext". That way, when you present the controller, the presenting controller will be behind the presented controller.
And insted of changing self.view.frame you will set self.view background color to clear, and add a subview and use it as a background 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. Add the presented view controller as a Child view controller. that way the life cycle stays the same, but you can add I'ts view as a subview, and change I'ts frame.
//Presenting view controller:
-(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. Don't use UIViewController, use UIView. Use a "Decorator" object, that you pass it the ViewController you would like the view to disaply on, and the "Decorator" will add the view as subview, and deal with the animation. No need for an example for this scenario.
回答3:
It is wrong to start animations when your view hasn't yet appeared. Can you, please, try the same code in viewDidAppear. Also animating main view controller's view will make underlying layers visible, so you've got to use another view on top of view controller's main view, like this:
UIView *progressView = [[UIView alloc] init];
progressView.frame = self.view.bounds;
progressView.backgroundColor = [UIColor redColor];
[self.view addSubView:progressView];
来源:https://stackoverflow.com/questions/38708701/ios-action-app-extension-with-transparent-background