На основе ответа Лутца и ответа на на этот вопрос следующий код контроллера пользовательского представления создает копию фонового представления табличного представления.Однако существует проблема с автоматическим вращением, которое рассматривается во втором фрагменте кода ниже.
// You also need to link against QuartzCore.framework
#import <QuartzCore/QuartzCore.h>
- (void) loadView
{
CGRect mainViewFrame = [self mainViewFrame];
self.view = [[[UIView alloc] initWithFrame:mainViewFrame] autorelease];
CAGradientLayer* gradient = [CAGradientLayer layer];
gradient.frame = self.view.bounds;
UIColor* startColor = [UIColor colorWithRed:226.0/255.0 green:229.0/255.0 blue:234.0/255.0 alpha:1.0];
UIColor* endColor = [UIColor colorWithRed:208.0/255.0 green:210.0/255.0 blue:216.0/255.0 alpha:1.0];
// Cast to (id) is necessary to get rid of a compiler warning
gradient.colors = [NSArray arrayWithObjects:(id)startColor.CGColor, (id)endColor.CGColor, nil];
// Inserting at index position 0 ensures that the gradient is drawn
// in the background even if the view already has subviews or other
// sublayers
[view.layer insertSublayer:gradient atIndex:0];
// add more subviews
}
- (CGRect) mainViewFrame
{
// add your frame calculating code here
}
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
[UIView animateWithDuration:duration
delay:0
options:UIViewAnimationCurveLinear
animations:^{
((CALayer*)[self.view.layer.sublayers objectAtIndex:0]).frame = self.view.bounds;
}
completion:NULL];
}
Проблема с приведенным выше кодом заключается в том, что во время работы анимации вращения исходный кодбелый фон виден очень недолго.К сожалению, я недостаточно разбираюсь в слоях, чтобы это исправить, поэтому я начал искать альтернативу CAGradientLayer
.Я установил CALayer.contents
с изображением градиента.
Большая часть приведенного ниже кода посвящена созданию изображения шаблона, необходимого в качестве входных данных для конструктора удобства, только на этот раз градиент рисуется «вручную» с помощью Core.Графика вместо CAGradientLayer
.Кстати, код рисования градиента в значительной степени основан на учебнике Core Graphics 101 Рэя Вендерлиха .
#import <QuartzCore/QuartzCore.h>
- (void) loadView
{
CGRect mainViewFrame = [self mainViewFrame];
self.view = [[[UIView alloc] initWithFrame:mainViewFrame] autorelease];
UIColor* startColor = [UIColor colorWithRed:226.0/255.0 green:229.0/255.0 blue:234.0/255.0 alpha:1.0];
UIColor* endColor = [UIColor colorWithRed:208.0/255.0 green:210.0/255.0 blue:216.0/255.0 alpha:1.0];
UIImage* backgroundPattern = [self gradientImageWithSize:CGSizeMake(1, mainViewFrame.size.height)
startColor:startColor
endColor:endColor];
self.view.layer.contents = (id)backgroundPattern.CGImage;
// add more subviews
}
- (CGRect) mainViewFrame
{
// add your frame calculating code here
}
- (UIImage*) gradientImageWithSize:(CGSize)size startColor:(UIColor*)startColor endColor:(UIColor*)endColor
{
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0, 0, size.width, size.height);
[self drawLinearGradientWithContext:context rect:rect startColor:startColor.CGColor endColor:endColor.CGColor];
UIImage* gradientImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return gradientImage;
}
- (void) drawLinearGradientWithContext:(CGContextRef)context rect:(CGRect)rect startColor:(CGColorRef)startColor endColor:(CGColorRef)endColor
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSArray* colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil];
// NSArray is toll-free bridged, so we can simply cast to CGArrayRef
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,
(CFArrayRef)colors,
locations);
// Draw the gradient from top-middle to bottom-middle
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
// Remember context so that later on we can undo the clipping we are going to
// add to the Core Graphics state machine
CGContextSaveGState(context);
// Add clipping with the specified rect so that we can simply draw into the
// specified context without changing anything outside of the rect. With this
// approach, the caller can give us a context that already has other stuff
// in it
CGContextAddRect(context, rect);
CGContextClip(context);
// Finally draw the gradient
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
// Undo clipping
CGContextRestoreGState(context);
// Cleanup memory allocated by CGContextDrawLinearGradient()
CGGradientRelease(gradient);
// Cleanup memory allocated by CGColorSpaceCreateDeviceRGB()
CGColorSpaceRelease(colorSpace);
}
Мне нравится этот код, потому что
- Он автоматически вращается чисто
- Не существует специального кода для обработки автоматического вращения
- Функции, связанные с градиентом, могут быть реорганизованы в отдельный служебный класс, чтобы сделать их более пригодными для повторного использования