簡體   English   中英

包含UIView的UIImage / UIImageView重繪是否已縮放

[英]UIImage/UIImageView redraw when containing UIView is scaled

我的iPad應用程序有一個導航,我在其中顯示不同頁面的屏幕截圖,因為我想一次顯示多個屏幕截圖,我將容器縮放到原始屏幕截圖的大約24%(1024x768)。

- (void) loadView
{
    // get landscape screen frame
    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);

    UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
    view.backgroundColor = [UIColor grayColor];

    self.view = view;

    // add container view for 2 images
    CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
    container = [[UIView alloc] initWithFrame:startFrame];
    container.backgroundColor = [UIColor whiteColor];

    // add image 1 (1024x768)
    UIImage *img1 = [UIImage imageNamed:@"01.jpeg"];
    UIImageView *img1View = [[UIImageView alloc] initWithImage:img1];
    [container addSubview:img1View];

    // add image 2 (1024x768)
    UIImage *img2 = [UIImage imageNamed:@"02.jpeg"];
    UIImageView *img2View = [[UIImageView alloc] initWithImage:img2];

    // move img2 to the right of img1
    CGRect newFrame = img2View.frame;
    newFrame.origin.x = 1024.0;
    img2View.frame = newFrame;

    [container addSubview:img2View];

    // scale to 24%
    container.transform = CGAffineTransformMakeScale(0.24, 0.24);

    [self.view addSubview:container];
}

但是當我使用“小”文本縮放圖像時,它看起來像這樣:

我必須使用大截圖,因為如果用戶點擊圖像,它應該縮放到100%並且清脆。

有沒有辦法如何“平滑”(動態)縮放圖像而不破壞性能? 它有兩個版本就足夠了:全px和24%版本的另一個版本。

縮小圖像看起來很糟糕的原因是它在OpenGL中進行縮放,OpenGL使用快速但低質量的線性插值。 您可能知道,UIView構建在CALayer之上,而CALayer又是OpenGL紋理的一種包裝器。 由於該層的內容位於視頻卡中,因此CALayer可以在GPU上完成所有的魔術,無論CPU是忙於加載網站,還是阻止磁盤訪問,或者其他什么。 我之所以提到這一點,只是因為注意層內紋理中的實際內容是有用的。 在你的情況下,UIImageView的圖層在其紋理上有完整的1024x768位圖圖像,並且不受容器變換的影響:UIImageView中的CALayer看不到它(讓我們看到..)246x185 on - 屏幕並重新縮放其位圖,它只是讓OpenGL做它的事情並在每次更新顯示時縮小位圖。

為了獲得更好的擴展,我們需要在CoreGraphics而不是OpenGL中進行擴展。 這是一種方法:

- (UIImage*)scaleImage:(UIImage*)image by:(float)scale
{
    CGSize size = CGSizeMake(image.size.width * scale, image.size.height * scale);
    UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
    [image drawInRect:CGRectMake(0, 0, size.width, size.height)];
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

- (void)loadView
{
    // get landscape screen frame
    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect landscapeFrame = CGRectMake(0, 0, screenFrame.size.height, screenFrame.size.width);

    UIView *view = [[UIView alloc] initWithFrame:landscapeFrame];
    view.backgroundColor = [UIColor grayColor];

    self.view = view;

    // add container view for 2 images
    CGRect startFrame = CGRectMake(-landscapeFrame.size.width/2, 0, landscapeFrame.size.width*2, landscapeFrame.size.height);
    container = [[UIView alloc] initWithFrame:startFrame];
    container.backgroundColor = [UIColor whiteColor];

    // add image 1 (1024x768)
    UIImage *img1 = [UIImage imageNamed:@"01.png"];
    img1View = [[TapImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
    img1View.userInteractionEnabled = YES; // important!
    img1View.image = [self scaleImage:img1 by:0.24];
    [container addSubview:img1View];

    // add image 2 (1024x768)
    UIImage *img2 = [UIImage imageNamed:@"02.png"];
    img2View = [[TapImageView alloc] initWithFrame:CGRectMake(1024, 0, 1024, 768)];
    img2View.userInteractionEnabled = YES;
    img2View.image = [self scaleImage:img2 by:0.24];
    [container addSubview:img2View];

    // scale to 24% and layout subviews
    zoomed = YES;
    container.transform = CGAffineTransformMakeScale(0.24, 0.24);

    [self.view addSubview:container];
}

- (void)viewTapped:(id)sender
{
    zoomed = !zoomed;

    [UIView animateWithDuration:0.5 animations:^
    {
        if ( zoomed )
        {
            container.transform = CGAffineTransformMakeScale(0.24, 0.24);
        }
        else
        {
            img1View.image = [UIImage imageNamed:@"01.png"];
            img2View.image = [UIImage imageNamed:@"02.png"];
            container.transform = CGAffineTransformMakeScale(1.0, 1.0);
        }
    }
    completion:^(BOOL finished)
    {
        if ( zoomed )
        {
            UIImage *img1 = [UIImage imageNamed:@"01.png"];
            img1View.image = [self scaleImage:img1 by:0.24];
            UIImage *img2 = [UIImage imageNamed:@"02.png"];
            img2View.image = [self scaleImage:img2 by:0.24];
        }
    }];
}

這里是TapImageView,一個UIImageView子類,告訴我們何時通過向響應者鏈發送動作來點擊它:

@interface TapImageView : UIImageView
@end

@implementation TapImageView

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [[UIApplication sharedApplication] sendAction:@selector(viewTapped:) to:nil from:self forEvent:event];
}

@end

而不是縮放容器及其所有子視圖。 從容器的內容創建UIImageView並將其框架大小調整為原始的24%。

UIGraphicsBeginImageContext(container.bounds.size);
[container renderInContext:UIGraphicsGetCurrentContext()];
UIImage *containerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIImageView *containerImageView = [[UIImageView alloc] initWithImage:containerImage];
CGRectFrame containerFrame = startFrame;
containerFrame.size.with *= 0.24;
containerFrame.size.height *= 0.24;
containerImageView.frame = containerFrame;

[self.view addSubView:containerImageView];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM