Image doesn't scroll with text - objective-c

Sorry for my english firstly.
I have an image and a text which are both must be scrolled.But they don't.
So here i have a piece of my code,where i've trying to do what i need to:
self.newsBody.text = [self bodyWithoutTags:self.newsContent];
NSData *imgData = [ServerRequest getImgFromServer:self.newsImage];
UIImage *img = [UIImage imageWithData:imgData];
self.scrollView.contentSize = CGSizeMake(320, 225);
self.newsImageView.image = img;
self.newsImageView.contentMode = UIViewContentModeScaleAspectFit;
self.newsImageView.clipsToBounds = YES;;
self.newsImageView.frame = CGRectMake(0, 0, 320, 204);
self.newsBody.frame = CGRectMake(0, 202, 320, 225);
self.newsBody.clipsToBounds = YES;
self.newsBody.autoresizesSubviews = YES;
self.newsBody.scrollEnabled = NO;
[self.scrollView addSubview:self.newsImageView];
[self.scrollView addSubview:self.newsBody];
Thank you for help!

Your real content size ...
self.newsImageView.frame = CGRectMake(0, 0, 320, 204);
self.newsBody.frame = CGRectMake(0, 202, 320, 225);
... is 320 x ( 202 + 225 ), which is 320 x 427. But you do set scroll view's content size to ...
self.scrollView.contentSize = CGSizeMake(320, 225);
... which is actually wrong. Scrolling is done when you do set correct content size and content size is bigger than scroll view itself. Otherwise it's not scrolling, no need to scroll if your content is smaller than scroll view itself.

Related

How to convert uitextview content to a image in custom size?

I create a uitextview and I can add text and images to it with NSAttributedString and NSTextAttachment
self.tvContent = [[UITextView alloc] initWithFrame:CGRectMake(0, 20,
self.view.frame.size.width, self.view.frame.size.height - 64)];
self.tvContent.font = [UIFont fontWithName:#"Arial" size:16.0f];
self.tvContent.backgroundColor = [UIColor whiteColor];
self.tvContent.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
self.tvContent.contentInset = UIEdgeInsetsMake(0, 0, 10, 0);
self.tvContent.layoutManager.allowsNonContiguousLayout=NO;
[self.view addSubview:self.tvContent];
And I convert its content to image with following code
- (UIImage *)imageFromView:(UITextView *)view {
CGRect tmpFrame = self.view.frame;
CGRect aFrame = view.frame;
aFrame.size.height = [view sizeThatFits:[[UIScreen mainScreen] bounds].size].height;
view.frame = aFrame;
UIGraphicsBeginImageContext([view sizeThatFits:[[UIScreen mainScreen] bounds].size]);
CGContextRef resizedContext = UIGraphicsGetCurrentContext();
[view.layer renderInContext:resizedContext];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
view.frame = tmpFrame;
return image;
}
This image's max-width is 375(iPhone 6), if I wrote less content, such as 1234, the image's width is 40, so how can I convert the content to image with custom size, such as the width is 750, and the height is as long as the content height? Any ideas? many thanks.
The UITextView only renders within it's current frame, so you need to either resize the frame to the desired size before rendering, or create a temporary UITextView object to use for rendering purpose.
Here is how rendering with a temporary object can be done:
// Your call to get the image
UIImage *image = [self imageFromTextView:self.tvContent width:750.0]; // Any width you want
// Your text view properties that also can be used for rendering purpose
- (void)setupTextViewProperties:(UITextView *)textView {
textView.font = [UIFont fontWithName:#"Arial" size:16.0f];
textView.backgroundColor = [UIColor whiteColor];
textView.textContainerInset = UIEdgeInsetsMake(10, 10, 10, 10);
textView.contentInset = UIEdgeInsetsMake(0, 0, 10, 0);
textView.layoutManager.allowsNonContiguousLayout=NO;
}
Set up of the temporary UITextView object used for rendering.
- (UIImage *)imageFromTextView:(UITextView *)view width:(CGFloat)desiredWidth {
// Create a new temporary UITextView to use for rendering
CGRect frame = CGRectMake(0.0, 0.0, desiredWidth, 0.0);
UITextView *temporaryTextView = [[UITextView alloc] initWithFrame:frame];
// Setup the temporary text view
// You can have different font, colors etc from the original view
[self setupTextViewProperties:temporaryTextView];
temporaryTextView.attributedText = view.attributedText;
// Calculate the height needed for content with width
CGSize size = CGSizeMake(desiredWidth, 0.0);
size = [temporaryTextView sizeThatFits:size];
// Resize the temporary view
// Note that the calculated size can contain a width smaller that desired with
temporaryTextView.frame = CGRectMake(0.0, 0.0, desiredWidth, size.height);
// Get the image
return [self imageFromView:temporaryTextView];
}
Helper that can render any view as an image.
- (UIImage *)imageFromView:(UIView *)view {
CGSize size = view.bounds.size;
UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

Same zooming in 2 scrollview

I am working on Pic Collage type of application. I have two scrollviews as shown in the figure below.
I have used this code to create an image to save in gallery
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
But this creates an image of 320 X 460 resolution image which is not good for sharing or adding as a profile or cover photo on facebook/twitter etc.
This is why I tried to create everything programmatically when user clicks on Done. The only problem that I am facing is I am not able to get the same zoom scale here. When I am creating everything again programmatically, the scroll view should be zoomed so that when I combine the view for 640 X 960 resolution image, the scrollview subview i.e. image should also look like what user has set in the scrolls. Here is the code:
UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 640, 960)];
[mainView setBackgroundColor:[UIColor grayColor]];
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, 20, 290, 920)];
[scrollView setBackgroundColor:[UIColor redColor]];
[mainView addSubview:scrollView];
UIScrollView *scrollView11 = [[UIScrollView alloc] initWithFrame:CGRectMake(330, 20, 290, 920)];
[scrollView11 setBackgroundColor:[UIColor redColor]];
[mainView addSubview:scrollView11];
[scrollView1.layer setBorderWidth:0.0];
[scrollView2.layer setBorderWidth:0.0];
[[[scrollView1 subviews] objectAtIndex:0] removeFromSuperview];
[[[scrollView2 subviews] objectAtIndex:0] removeFromSuperview];
[scrollView1 setFrame:CGRectMake(20, 20, 290, 920)];
[scrollView2 setFrame:CGRectMake(330, 20, 290, 920)];
UIImageView *imgV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 290, 100)];
[imgV setImage:[self resizeImage:[UIImage imageNamed:#"photo1.png"] width:1166 height:960]];
//[imgV sizeToFit];
[scrollView1 addSubview:imgV];
UIImageView *imgV1 = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 290, 100)];
[imgV1 setImage:[self resizeImage:[UIImage imageNamed:#"photo2.png"] width:846 height:960]];
//[imgV1 sizeToFit];
[scrollView2 addSubview:imgV1];
scrollView1.contentSize = imgV.image.size;
scrollView2.contentSize = imgV1.image.size;
NSLog(#"scrollview subviews - %#",[scrollView1 subviews]);
[self initScrollView:scrollView1];
[self initScrollView:scrollView2];
[self centerScrollViewContents:scrollView1 withImageView:imgV];
[self centerScrollViewContents:scrollView2 withImageView:imgV1];
CGFloat newZoomScale = scrollView1.zoomScale;
// Figure out the rect we want to zoom to, then zoom to it
CGSize scrollViewSize = scrollView1.bounds.size;
CGFloat w = scrollViewSize.width / newZoomScale;
CGFloat h = scrollViewSize.height / newZoomScale;
CGFloat x = point.x - (w / 2.0f);
CGFloat y = point.y - (h / 2.0f);
CGRect rectToZoomTo = CGRectMake(rect.origin.x*2, rect.origin.y*2, rect.size.width*2, rect.size.height*2);
CGRect rectToZoom = CGRectMake(x, y, w, h);
[scrollView1 zoomToRect:rectToZoom animated:YES];
newZoomScale = scrollView2.zoomScale;
// Figure out the rect we want to zoom to, then zoom to it
scrollViewSize = scrollView2.bounds.size;
w = scrollViewSize.width / newZoomScale;
h = scrollViewSize.height / newZoomScale;
x = point1.x - (w / 2.0f);
y = point1.y - (h / 2.0f);
rectToZoomTo = CGRectMake(rect1.origin.x*2, rect1.origin.y*2, rect1.size.width*2, rect1.size.height*2);
rectToZoom = CGRectMake(x, y, w, h);
[scrollView2 zoomToRect:rectToZoom animated:YES];
[mainView addSubview:scrollView1];
[mainView addSubview:scrollView2];
[scrollView1.layer setBorderWidth:0.0];
[scrollView2.layer setBorderWidth:0.0];
Please help.
Thanks in Advance!

UIImage/UIImageView redraw when containing UIView is scaled

My iPad app has a navigation where I show screenshots of the different pages and because I want to show more than one screenshot at once I scale the container to around 24% of the original screenshots (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];
}
but when I scale images with "small" text it looks sth like this:
I have to use the big screenshots because if a user taps the image it should scale to 100% and be crispy clear.
is there a way how I can scale the images "smoothly" (on the fly) without ruining performance?
it would be enough to have two versions: the full-px one and another for the 24% version.
The reason the scaled-down image looks crappy is it's being scaled in OpenGL, which is using fast-but-low-quality linear interpolation. As you probably know, UIView is built on top of CALayer, which is in turn a sort of wrapper for OpenGL textures. Because the contents of the layer reside in the video card, CALayer can do all of its magic on the GPU, independent of whether the CPU is busy loading a web site, blocked on disk access, or whatever. I mention this only because it's useful to pay attention to what's actually in the textures inside your layers. In your case, the UIImageView's layer has the full 1024x768 bitmap image on its texture, and that isn't affected by the container's transform: The CALayer inside the UIImageView doesn't see that it's going to be (let's see..) 246x185 on-screen and re-scale its bitmap, it just lets OpenGL do its thing and scale down the bitmap every time it updates the display.
To get better scaling, we'll need to do it in CoreGraphics instead of OpenGL. Here's one way to do it:
- (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];
}
}];
}
And here's TapImageView, a UIImageView subclass that tells us when it's been tapped by sending an action up the responder chain:
#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
Instead of scaling the container and all of its subviews. Create a UIImageView from the contents of the container and adjust its frame size to 24% of the original.
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];

sub CALayer can not be displayed

my code is like this:
// layer
highlightLayer = [[CALayer alloc]init];
highlightLayer.frame = CGRectMake(0, 420, 320, 11);
highlightLayer.backgroundColor = [UIColor greenColor].CGColor;
CALayer *contentLayer = [[CALayer alloc]init];
contentLayer.frame = CGRectMake(0, 420, 80, 11);
contentLayer.backgroundColor = [UIColor redColor].CGColor;
[highlightLayer addSublayer:contentLayer];
[contentLayer release];
but this sublayer does not appear. i don't know why.
Because contentLayer's frame is outside highlightLayer's bounds (0, 0, 320, 11). contentLayer's frame is expressed in highlightLayer's coordinate system. I think you should simply adjust contentLayer's frame origin.

Showing a Title and an Image Into the Table Header

I am trying to show into the header of my UITableViewController a title and under it an image illustrating the title. The next code (written into the viewDidLoad method) shows only the image, and this image over the rest of the table sections. How I can fix it to do what I want?
// Creates a header view.
UIView *containerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 60)] autorelease];
UILabel *headerLabel = [[[UILabel alloc] initWithFrame:CGRectMake(10, 20, 300, 40)] autorelease];
headerLabel.text = self.name;
headerLabel.textColor = [UIColor blackColor];
headerLabel.font = [UIFont boldSystemFontOfSize:16];
headerLabel.backgroundColor = [UIColor clearColor];
GRect imageRect = CGRectMake(0.0f, 0.0f, 320.0f, 109.0f);
UIImageView *headerImage = [[UIImageView alloc] initWithFrame:imageRect];
UIImage *image = [UIImage imageNamed:self.imagePath];
[headerImage setImage:image];
headerImage.opaque = YES;
[containerView addSubview:headerLabel];
[containerView addSubview:headerImage];
self.tableView.tableHeaderView = containerView;
Thanks for reading.
Just adjust the views' frames accordingly. The container view's frame must be tall enough to contain the label and image view, and the image view's y coordinate must be set so that it is positioned below the label. The frame rects you are using in your code do not match.