UIWebView Transparent background in ios8 - ios

I am using a UIWebview,but there is some black background behind the web view in ios8. The same is working fine in ios7. I also set opaque to NO.

Try adding UIWebview as subview programmatically.
WebView = [[UIWebView alloc]initWithFrame:CGRectMake(264, 10, 745, 576)];
WebView.userInteractionEnabled = YES;
[self setBorderToView: WebView];
WebView.scrollView.bounces = NO;
[WebView setBackgroundColor:[UIColor clearColor]];
[WebView setOpaque:NO];
[WebView loadHTMLString: embedHTML baseURL: nil];
[self.view addSubview: WebView];
Hope this helps you!

I also faced same issue, after not getting proper solution I did a trick using Masking.
CALayer *aLayer = [CALayer layer];
aLayer.backgroundColor = [UIColor blackColor].CGColor;
aLayer.frame = CGRectMake(origin.x, origin.y, widthOfVideo, heightOfVideo);
objWebView.layer.mask = aLayer;
And This worked for me. Hope that can be helpful to you.

Put a instance variable in the in the header file or your class:
// instance variable for interval timer
NSTimer *BackgroundIntervalTimer;
Put these methods in the implementation file:
- (void)startUIWebViewBackgroundFixTimer {
// if > iOS 8 start fixing background color of UIWebPDFView
if (!SYSTEM_VERSION_LESS_THAN(#"8.0")) {
// hide pdfWebView until background fixed
self.pdfWebView.alpha = 0.0;
// start interval timer
BackgroundIntervalTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(fixBackground) userInfo:nil repeats:YES];
}
}
- (void)stopUIWebViewBackgroundFixTimer {
[BackgroundIntervalTimer invalidate];
BackgroundIntervalTimer = nil;
}
- (void)fixBackground {
// stop timer interval
[self stopUIWebViewBackgroundFixTimer];
// Assuming self.webView is our UIWebView
// We go though all sub views of the UIWebView and set their backgroundColor to white
UIView *v = self.pdfWebView;
while (v) {
//v.backgroundColor = [UIColor whiteColor];
v = [v.subviews firstObject];
if ([NSStringFromClass([v class]) isEqualToString:#"UIWebPDFView"]) {
[v setBackgroundColor:[UIColor whiteColor]];
// background set to white so fade view in and exit
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.pdfWebView.alpha = 1.0;
}
completion:nil];
return;
}
}
// UIWebPDFView doesnt exist yet so exit and try later
[self startUIWebViewBackgroundFixTimer];
}
Now put this line right after the line where you load the pdf:
// if iOS 8 check if pdfWebView got subview of class UIWebPDFView
[self startUIWebViewBackgroundFixTimer];

Related

How to disable the animation scrolling in a UIScrollView in Objective C?

I loaded a pdf in a scrollview, and I would like to go directly to the next page without having the animation scrolling.
CGRect scrollViewRect = CGRectInset(viewRect, -scrollViewOutset, 0.0f);
theScrollView = [[UIScrollView alloc] initWithFrame:scrollViewRect]; // All
theScrollView.autoresizesSubviews = NO;
theScrollView.contentMode = UIViewContentModeRedraw;
theScrollView.showsHorizontalScrollIndicator = NO;
theScrollView.showsVerticalScrollIndicator = NO;
theScrollView.scrollsToTop = NO;
theScrollView.delaysContentTouches = NO;
theScrollView.pagingEnabled = YES;
theScrollView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
theScrollView.backgroundColor = [UIColor clearColor];
theScrollView.delegate = self;
[self.view addSubview:theScrollView];
Is it possible ?
You have to use below method to jump on direct offset of your next page by below method.
[objUIScrollView setContentOffset:CGPointMake(YOUR_X, YOUR_Y) animated:NO]
animated = NO;
If you are loading PDF through WebView than you need to follow below code:
webview.scrollView.contentOffset = CGPointMake(YOUR_X, YOUR_Y);
Note : Use this above code in your Next Button page or after loading
WebView properly may be in below method.
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
}
Hope this will work as you expected.
Sure, simply use:
[theScrollView scrollRectToVisible:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f) animated:NO];
or
[theScrollView setContentOffset:CGPointMake(0.0f, 0.0f) animated:NO];
and change the CGPoint or CGRect to the offset of the page of your liking.

CATransition black color issue when push right to left

May be this types of issue occurred with many developer, I also tried to find on Google but there is no luck to solve my problem.
In my app rootViewController set on window dynamically, I mean user can change root view at run time application. So first I am removing current rootViewController from UIWindow and then I set new rootViewController on UIWindow with specific animation.
This animation done by CATransition with transition.type = kCATransitionPush;.
My app working very well except animation of new rootViewController. As above I said that I used kCATransitionPush with CATransition
EDITED:
Below is my code:
-(void) changeRootViewController
{
for(UIView *subViews in self.window.rootViewController.view.subviews)
[subViews removeFromSuperview];
[self.window.rootViewController.view removeFromSuperview];
self.window.rootViewController.view = nil;
[self.window.rootViewController removeFromParentViewController];
MainRootViewController *mainRootVC = [[MainRootViewController alloc] init];
CATransition *animation = [CATransition animation];
[animation setDuration:0.4];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
animation.fillMode = kCAFillModeForwards;
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
self.window.rootViewController = mainRootVC;
[[self.window layer] addAnimation:animation forKey:nil];
}
I also tried to set clearColor and whiteColor of background of UIWindow. But not working.
My Problem is : While animation is process (right to left) I am getting black shadow. So anybody can help me to hide this black shadow? Please give you golden suggestion.
Thanks.
Add in the delegate (didFinishLaunchingWithOptions method) these two lines :
self.window.backgroundColor = [UIColor whiteColor];
self.window.tintColor = [UIColor whiteColor];
I was having same requirement, I have 3 images of full screen size at splash screen which should slide from right to left. But used of CATransition doesn't solve the issue. So I have used scrollview with paging. Added 3 images in scrollview and then start animation.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
size = [UIScreen mainScreen].bounds.size;
imageArray = [[NSMutableArray alloc] init];
[imageArray addObject:[UIImage imageNamed:#"splashScreen1.png"]];
[imageArray addObject:[UIImage imageNamed:#"splashScreen2.png"]];
[imageArray addObject:[UIImage imageNamed:#"splashScreen3.png"]];
self.splashScrollView.frame = CGRectMake(0,0,size.width,size.height);
self.splashScrollView.contentSize = CGSizeMake(size.width * imageArray.count, size.height);
self.splashScrollView.pagingEnabled = YES;
CGFloat xPos = 0.0;
for (UIImage *image in imageArray) {
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(xPos, 0.0, size.width, size.height);
[self.splashScrollView addSubview:imageView];
xPos += size.width;
}
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(startAnimation) userInfo:nil repeats:NO];
}
This(startAnimation) method scrolled scrollView upto the width of image, on completion of first image animation, I have started second image animation which scrolled to the edge of scrollview width.
-(void) startAnimation{
[UIView animateWithDuration:2.0
animations:^{
self.splashScrollView.contentOffset = CGPointMake(size.width, 0.0);
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0
animations:^{
self.splashScrollView.contentOffset = CGPointMake((self.splashScrollView.contentSize.width - CGRectGetWidth(self.splashScrollView.frame)), 0.0);
} completion:^(BOOL finished) {
//At animation end go to login
}];
}];
}

UITapGestureRecognizer only works after initialization and reload of viewcontroller

In my app i have a viewcontroller with a calendar in it (CKCalendar). Only one month is shown at the same time and with scrolling one can switch months. On certain days in the calendar are events which a highlighted by a circle.
Months are switched with the code
- (void) nextMonth:(UISwipeGestureRecognizer *)swipe {
[self.calView moveCalendarToNextMonth];
[self drawItemsForCurrentMonth];
}
The method drawItemsForCurrentMonth calls the next piece of code for every items that needs highlighting.
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSArray* res = [self calculateDayCirclePosition:date];
CGFloat x = [[res objectAtIndex:0] floatValue] + (DEFAULT_CELL_WIDTH-DEFAULT_CIRCLE_WIDTH-CELL_BORDER_WIDTH)/2;
CGFloat y = [[res objectAtIndex:1] floatValue] + (DEFAULT_CELL_HEIGHT-DEFAULT_CIRCLE_WIDTH)/2;
AgendaCircleView* circleView = [[AgendaCircleView alloc] initWithFrame:CGRectMake(x,y,self.circleWidth,self.circleWidth)];
circleView.date = date;
AgendaViewController* avc;
if([appDelegate.viewController.frontViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navVC = (UINavigationController*)appDelegate.viewController.frontViewController;
avc = (AgendaViewController*)[navVC visibleViewController];
}
UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:avc action:#selector(didSelectDate:)];
tapGesture.enabled = YES;
tapGesture.delegate = avc;
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
[circleView addGestureRecognizer:tapGesture];
circleView.userInteractionEnabled = YES;
circleView.alpha = 0.5;
circleView.layer.cornerRadius = (self.circleWidth/2);
if(fill) {
circleView.backgroundColor = [appDelegate.dataController.rijschoolItem getColor1];
}
else {
circleView.layer.borderWidth = 1.0f;
circleView.backgroundColor = [UIColor clearColor];
circleView.layer.borderColor = [UIColor whiteColor].CGColor;
}
[circleView setNeedsDisplay];
[self.calendarContainer addSubview:circleView];
[self.calendarContainer bringSubviewToFront:circleView];
[self.calendarContainer setUserInteractionEnabled:YES];
This code works fine when the viewcontroller is initialized. Clicking on the circle fires the didSelectDate method. However when i change months the tapgesturerecognizer does not work anymore. When months are changed i use the exact same code that is used when initializing the viewcontroller. The strange thing is that when i open an other detailed viewcontroller and throw it on the view stack and go back, it is working again.
I've tried to use
gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer but this does not solve the problem.
Furthermore i've tried to use setNeedsLayout but this is not working either.
Any ideas?
Ok, I found the problem. So for others who might encounter the same type of problem. You have to make sure that the view is not animating while adding the gesturerecognizers.
I had this block of code
[UIView animateWithDuration:0.4 animations:^{
calendar.alpha = 1.0;
}];
[self drawItemsForCurrentMonth];
changed into
[UIView animateWithDuration:0.4 animations:^{
calendar.alpha = 1.0;
} completion:^(BOOL finished) {
if(finished) {
[self drawItemsForCurrentMonth];
}
}];
Having the method drawItemsForCurrentMonth after the animation block does not necessarily guarantee that the block is has actually finished. Luckily there is a completion block which covers that aspect.

IOS: How to detect animation is in progress

This has been asked before but none of the answers are straightforward enough to help little old me.
What exactly does .isAnimating in an UIIimage view do? And how to properly use it?
I am emulating the tap to focus animation in the iPhone camera (yellowish square that pops up and then shrinks when you tap on the preview). That works fine, but I want it to not happen multiple times if it is already animating. This code does the animation but multiple taps gives multiple animationed squares. I suspect it is not just .isAnimating but I'm also doing something else wrong because I tried it with my own boolean too and that fails.
-(void)focusSquarePopUp:(CGPoint)touchPoint;
{
UIImage *focusSquareImage = [UIImage imageNamed:#"yellowFocusSquare"];
UIImageView *tmpView = [[UIImageView alloc] initWithImage:focusSquareImage];
if (!(tmpView.isAnimating))
{
tmpView.center = touchPoint;
tmpView.opaque = YES;
tmpView.alpha = 1.0f;
[self.view addSubview:tmpView];
tmpView.hidden = NO;
// shrink to half size in .3 second
[UIView animateWithDuration:0.3 delay:0 options:0 animations:^{
tmpView.transform = CGAffineTransformMakeScale(.5, .5);
NSLog(#"in animation isAnimating %hhd", tmpView.isAnimating);
} completion:^(BOOL finished) {
// Once the animation is completed hide the view for good
tmpView.hidden = YES;
}];
}
NSLog(#"done animating isAnimating %hhd", tmpView.isAnimating);
[tmpView release];
}
If there is question where this has a solid answer, that would be great.
EDIT - here is the working code.
-(void)focusSquarePopUp:(CGPoint)touchPoint;
{
if (animationInProgress)
return;
animationInProgress = true;
UIImageView *tmpView = [[UIImageView alloc] initWithImage:sp_ui->focus_square];
tmpView.center = touchPoint;
tmpView.opaque = YES;
tmpView.alpha = 1.0f;
[self.view addSubview:tmpView];
tmpView.hidden = NO;
// shrink to half size in .3 second
[UIView animateWithDuration:0.3 delay:0 options:0 animations:^{
tmpView.transform = CGAffineTransformMakeScale(.5, .5);
} completion:^(BOOL finished) {
// Once the animation is completed hide the view for good
tmpView.hidden = YES;
animationInProgress = false;
}];
[tmpView release];
}
I suspect on your code. On your tapping on method focusSquarePopUp: you create new instances of tmpView and focusSquareImage and it adding on self view. That why you found number of animated square equal to number of tap. When you create new instance of those variable then sure isAnimating is firstly you got NO value and it enter animation block code.
Why not you create instance of tmpView and focusSquareImage in .h file of class?? In fact its problem of variable declarations and scope of variables.
Your code should be like this,
Declare instance in animation class (i.e. self.view) .h file
UIImage *focusSquareImage;
UIImageView *tmpView;
Now in .m file viewDidLoad method,
in viewDidLoad
focusSquareImage = [UIImage imageNamed:#"yellowFocusSquare"];
tmpView = [[UIImageView alloc] initWithImage:focusSquareImage];
Your animation method implementation should be,
-(void)focusSquarePopUp:(CGPoint)touchPoint;
{
if (!(tmpView.isAnimating))
{
tmpView.center = touchPoint;
tmpView.opaque = YES;
tmpView.alpha = 1.0f;
[self.view addSubview:tmpView];
tmpView.hidden = NO;
// shrink to half size in .3 second
[UIView animateWithDuration:0.3 delay:0 options:0 animations:^{
tmpView.transform = CGAffineTransformMakeScale(.5, .5);
NSLog(#"in animation isAnimating %hhd", tmpView.isAnimating);
} completion:^(BOOL finished) {
// Once the animation is completed hide the view for good
tmpView.hidden = YES;
[tmpView release];
}];
}
}
Another option of method implementation,
-(void)focusSquarePopUp:(CGPoint)touchPoint;
{
if(!tmpView){
focusSquareImage = [UIImage imageNamed:#"yellowFocusSquare"];
tmpView = [[UIImageView alloc] initWithImage:focusSquareImage];
if (!(tmpView.isAnimating))
{
tmpView.center = touchPoint;
tmpView.opaque = YES;
tmpView.alpha = 1.0f;
[self.view addSubview:tmpView];
tmpView.hidden = NO;
// shrink to half size in .3 second
[UIView animateWithDuration:0.3 delay:0 options:0 animations:^{
tmpView.transform = CGAffineTransformMakeScale(.5, .5);
NSLog(#"in animation isAnimating %hhd", tmpView.isAnimating);
} completion:^(BOOL finished) {
// Once the animation is completed hide the view for good
tmpView.hidden = YES;
[tmpView release];
tmpView = nil;
}];
}
}
}
isAnimating is UIImageView property and it has nothing to do with UIView animation methods
isAnimating is used when you want a UIImageView to alternate between multiple images. For example in the following code the UIImageView display 3 images and alternate between them
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
UIImage *image1 = [UIImage imageNamed:#"image1.png"];
UIImage *image2 = [UIImage imageNamed:#"image2.png"];
UIImage *image3 = [UIImage imageNamed:#"image3.png"];
imageView.animationImages = #[image1, image2, image3];
imageView.animationDuration = 1;
NSLog(#"isAnimating %d",imageView.isAnimating); // isAnimating 0
[imageView startAnimating];
NSLog(#"isAnimating %d",imageView.isAnimating); // isAnimating 1
[self.view addSubview:imageView];
Your case is completely different you are using UIView animation blocks and to know if the animation in its block is finished or not you will need to add a Boolean flag instance variable animationFinished and set it to YES in the completion block of the animation

Imitating screenshot flash animation on iOS

Im looking for a way to copy the "blink" animation, that is played when pressing home+lock.
Does anyone know if this animation is available somehow?
On an iOS device you take a screenshot when you press home + lock and the screen flashes white. Do you mean this effect? If so, try this:
Add a UIView with a white background color to your view hierarchy such that it covers the whole screen. Then, start an animation that fades the opacity of this view to zero. On completion, remove the view from its superview:
[UIView animateWithDuration: 0.5
animations: ^{
whiteView.alpha = 0.0;
}
completion: ^(BOOL finished) {
[whiteView removeFromSuperview];
}
];
Try:
[UIView animateWithDuration:1 animations:^{
self.view.backgroundColor = [UIColor blackColor];
for (UIView *view2 in self.view.subviews) {
view2.backgroundColor = [UIColor blackColor];
}
}];
[UIView animateWithDuration:1 animations:^{
self.view.backgroundColor = [UIColor whiteColor];
for (UIView *view2 in self.view.subviews) {
view2.backgroundColor = [UIColor whiteColor];
}
}];
I have found very easy way to imitate exactly the Screenshot Flash Apple uses. I wish everyone try it at least once.
UIView * flashView = [[UIView alloc] initWithFrame:self.view.frame];
flashView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:flashView];
[UIView animateWithDuration:1 delay:0.3 options:0 animations:^{
flashView.alpha = 0;
} completion:^(BOOL finished)
{
[flashView removeFromSuperview];
}];
}
These examples gave me inspiration, but did not give me the desired effect. This is my attempt, looks pretty close to the real deal.
func mimicScreenShotFlash() {
let aView = UIView(frame: self.view.frame)
aView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(aView)
UIView.animateWithDuration(1.3, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
aView.alpha = 0.0
}, completion: { (done) -> Void in
aView.removeFromSuperview()
})
}
Two problems with the current solutions:
putting views over other views can (in my experience with UICollectionView and other crap) trigger autolayout. Autolayout is bad. Autolayout makes the machine do a burst of work and can have side effects other than just calculating for no reason other than to burn CPU and battery. So, you don't want to give it reasons to autolayout, for instance, adding a subview to a view that really, really cares about keeping itself laid out nicely.
your view doesn't cover the whole screen necessarily, so if you want to flash the whole screen, you're better off using a UIWindow ... this should insulate from any view controllers that are touchy about having subviews added
This is my implementation, a category on UIView. I've included methods to take a screenshot before flashing the window, and saving it to the camera roll afterwards. Note that UIWindow seems to want to do its own animations when being added, it will normally fade in over maybe a third of a second. There may be a better way of telling it not to do this.
// stupid blocks
typedef void (^QCompletion)(BOOL complete);
#interface UIView (QViewAnimation)
+ (UIImage *)screenshot; // whole screen
+ (void)flashScreen:(QCompletion)complete;
- (UIImage *)snapshot; // this view only
- (void)takeScreenshotAndFlashScreen;
#end
#implementation UIView (QViewAnimation)
+ (UIImage *)screenshot;
{
NSArray *windows = [[UIApplication sharedApplication] windows];
UIWindow *window = nil;
if (windows.count) {
window = windows[0];
return [window snapshot];
} else {
NSLog(#"Screenshot failed.");
return nil;
}
}
- (UIImage *)snapshot;
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
+ (void)flashScreen:(QCompletion)complete;
{
UIScreen *screen = [UIScreen mainScreen];
CGRect bounds = screen.bounds;
UIWindow * flash = [[UIWindow alloc] initWithFrame:bounds];
flash.alpha = 1;
flash.backgroundColor = [UIColor whiteColor];
[UIView setAnimationsEnabled:NO];
[flash makeKeyAndVisible];
[UIView setAnimationsEnabled:YES];
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationCurveEaseOut
animations:^{
flash.alpha = 0;
}
completion: ^(BOOL finished)
{
flash.hidden = YES;
[flash autorelease];
if (complete) {
complete(YES);
}
}];
}
- (void)takeScreenshotAndFlashScreen;
{
UIImage *image = [UIView screenshot];
[UIView flashScreen:^(BOOL complete){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0),
^{
UIImageWriteToSavedPhotosAlbum(image,self,#selector(imageDidFinishSaving:withError:context:),nil);
});
}];
}
- (void)imageDidFinishSaving:(UIImage *)image
withError:(NSError *)error
context:(void *)context;
{
dispatch_async(dispatch_get_main_queue(),^{
// send an alert that the image saved
});
}
#end

Resources