Is it possible to use a UIScrollView to see an image that is about 800px long? I tried using a UIScrollView and the UIImageView but it's not scrolling. Anybody can help please?
Use:
UIScrollView *yourScrollview = [[UIScrollView alloc] initWithFrame:(CGRect){{0,0}, {320,480}}];
UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"yourImageHere.png"]];
yourImageView.frame = yourScrollview.bounds;
yourScrollview.contentSize = yourImageView.frame.size;
yourScrollview.minimumZoomScale = 0.4;
yourScrollview.maximumZoomScale = 4.0;
[yourScrollview setZoomScale:yourScrollview.minimumZoomScale];
yourScrollview.delegate = self;
[self.view addSubview:yourScrollview];
Don't forget to add UIScrollViewDelegate in your .h file
Note: ARC code
1. Create a new Project -> Single View Application
2. Put the follow code into:
"ViewController.m"
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
-(void) viewDidLoad
{
[super viewDidLoad];
UIScrollView * scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[scrollView setContentSize:CGSizeMake(320, 800)];
UIView * myView = [[UIView alloc] initWithFrame : CGRectMake(0, 0, 320, 800)];
UIImageView * myImage = [[UIImageView alloc]initWithImage : [UIImage imageNamed:#"Test.png"]];
[myView addSubview: myImage];
[myImage release];
[scrollView addSubview: myView];
[myView release];
[self.view addSubview: scrollView];
[scrollView release];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
3. Put the Image "Test.png" into your Project (Drag Drop into Xcode -> Folder:Supporting Files)
If it is not panning it means you forgot to set the contentSize property. I have a tutorial on my website that shows how to embed a UIImageView inside a UIScrollView and set it up for both panning and zooming. It includes complete downloadable source code. See Panning and Zooming with UIScrollView
#interface ZoomViewController : UIViewController <uiscrollviewdelegate> {
IBOutlet UIScrollView *scroll;
UIImageView *image;
}
#property (nonatomic, retain) UIScrollView *scroll;
#end
</uiscrollviewdelegate></uikit>
Once check your Viewdidload method.
- (void)viewDidLoad {
image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"img_body.png"]];
[super viewDidLoad];
image = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"img_body.png"]];
scroll.contentSize = image.frame.size;
[scroll addSubview:image];
scroll.minimumZoomScale = 0.4;
scroll.maximumZoomScale = 4.0;
scroll.delegate = self;
[scroll setZoomScale:scroll.minimumZoomScale];
[super viewDidLoad];
}
Related
My problem with after pinch zoom, when I pinch zoom and after drag image then white space on top and bottom.
My Code as per apple documentation.
https://developer.apple.com/library/content/documentation/WindowsViews/Conceptual/UIScrollView_pg/ZoomZoom/ZoomZoom.html
Sample code
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
scrollView.minimumZoomScale=0.5;
scrollView.maximumZoomScale=6.0;
scrollView.contentSize=CGSizeMake(1280, 960);
scrollView.delegate = self;
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return imageView;
}
Thank you.
At first set your minimum zoom scale to 1.0:
scrollView.minimumZoomScale = 1.0;
Next, set the contentSize for scrollView:
scrollView.contentSize = [UIScreen mainScreen].bounds.size;
And if you don't want to see the extra space when bouncing, add the next line:
scrollView.bounces = NO;
Completely, the method should looks something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.minimumZoomScale = 1.0;
self.scrollView.maximumZoomScale = 6.0;
self.scrollView.bounces = NO;
self.scrollView.contentSize = [UIScreen mainScreen].bounds.size;
self.scrollView.delegate = self;
}
Hope it will help.
This is how I do it. If you image fits perfectly into the view, there will be no white space when you zoom and pan.
If your image does not fit or scale properly, there will be white space on the sides OR the top.
First make sure your image is the correct size. Next you need to add minimumZoomScale and maximumZoomScale to the scrollView. The rest will work after that. You can use auto-layout or frames. Up to you.
This example uses auto-layout:
#import "ViewController.h"
#interface AutoLayoutScrollView : UIScrollView
#property (nonatomic, weak) UIView *contentView;
#end
#implementation AutoLayoutScrollView
- (instancetype)init {
if (self = [super init]) {
UIView *view = [[UIView alloc] init];
self.contentView = view;
[self addSubview:view];
[self.contentView.leftAnchor constraintEqualToAnchor:self.leftAnchor].active = YES;
[self.contentView.rightAnchor constraintEqualToAnchor:self.rightAnchor].active = YES;
[self.contentView.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
[self.contentView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor].active = YES;
[self.contentView setTranslatesAutoresizingMaskIntoConstraints:NO];
}
return self;
}
- (void)didMoveToSuperview {
[super didMoveToSuperview];
UIView *parent = self.superview;
if (parent) {
[self.leftAnchor constraintEqualToAnchor:parent.leftAnchor].active = YES;
[self.rightAnchor constraintEqualToAnchor:parent.rightAnchor].active = YES;
[self.topAnchor constraintEqualToAnchor:parent.topAnchor].active = YES;
[self.bottomAnchor constraintEqualToAnchor:parent.bottomAnchor].active = YES;
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
}
}
#end
#interface ViewController () <UIScrollViewDelegate>
#property (nonatomic, strong) AutoLayoutScrollView *scrollView;
#property (nonatomic, strong) UIImageView *imageView;
#property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[AutoLayoutScrollView alloc] init];
[self.view addSubview:self.scrollView];
[self.scrollView.contentView.widthAnchor constraintEqualToAnchor:self.view.widthAnchor].active = YES;
[self.scrollView.contentView.heightAnchor constraintEqualToAnchor:self.view.heightAnchor].active = YES;
self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Image"]];
[self.imageView setContentMode:UIViewContentModeScaleAspectFit];
[self.scrollView.contentView addSubview:self.imageView];
[self.imageView.leftAnchor constraintEqualToAnchor:self.scrollView.contentView.leftAnchor].active = YES;
[self.imageView.rightAnchor constraintEqualToAnchor:self.scrollView.contentView.rightAnchor].active = YES;
[self.imageView.topAnchor constraintEqualToAnchor:self.scrollView.contentView.topAnchor].active = YES;
[self.imageView.bottomAnchor constraintEqualToAnchor:self.scrollView.contentView.bottomAnchor].active = YES;
[self.imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.scrollView setMinimumZoomScale:1.0];
[self.scrollView setMaximumZoomScale:3.0];
[self.scrollView setZoomScale:1.0f animated:YES];
[self.scrollView setDelegate:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
#end
I have a custom class A that is a subclass of UIView which essentially manages a UIScrollView that fits the size of the view and the contains an UIImageView that fills that scrollView.
I am having trouble setting the imageView.image of the custom class:
Here's the class
#import "BackgroundPickerView.h"
#implementation BackgroundPickerView
#synthesize scrollView;
#synthesize imageView;
#synthesize actionButton;
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
//[[NSNotificationCenter defaultCenter] addObserver:self
// selector:#selector(changeImage)
// name:#"ImageChangeNotification"
// object:nil];
//Here's where we add custom subviews
scrollView = [[UIScrollView alloc] init];
imageView = [[UIImageView alloc] init];
actionButton = [[UIButton alloc] init];
[scrollView setFrame:CGRectMake(0, 0, 321, 115)];
[imageView setFrame:CGRectMake(0, 0, 321, 115)];
[actionButton setFrame:CGRectMake(0, 0, 320, 115)];
scrollView.scrollEnabled = YES;
scrollView.minimumZoomScale = 1.0;
scrollView.maximumZoomScale = 6.0;
scrollView.contentSize = CGSizeMake(300, 200);//imageView.image.size;
[scrollView addSubview:imageView];
[self addSubview:scrollView];
}
-(void)storeImage:(UIImage *)image
{
self.imageView.image = image;
}
-(void)changeImage
{
[self.imageView setImage:[UIImage imageNamed:#"random.png"]];
}
From my other class B where I receive the image I have tried using NSNotification and a simple setter method to try setting the imageView property of the class object, but cannot seem to set the imageView.image. I have tried using
instance.imageView.image = myImageToSet
//Setter
[instance storeImage:myImageToSet];
in class B but am having no success
first of all, the initialisation of subviews in layoutSubviews not the best way, better u initialise them in the init method, because layoutSubviews may call multiple times to layout the subviews, if u place the initialisation code in the layoutSubviews there might be may subviews. in layoutSubviews u only set the frame of the subviews.
and u can do like below,
#import "BackgroundPickerView.h"
#implementation CustomViewA
//Edit change below
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
[self commonInit];
}
return self;
}
- (void)awakeFromNib
{
[self commonInit];
}
- (void)commonInit
{
_scrollView = [[UIScrollView alloc] init];
_imageView = [[UIImageView alloc] init];
_actionButton = [[UIButton alloc] init];
_scrollView.scrollEnabled = YES;
_scrollView.minimumZoomScale = 1.0;
_scrollView.maximumZoomScale = 6.0;
[_scrollView addSubview:_imageView];
[self addSubview:_scrollView];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[_scrollView setFrame:CGRectMake(0, 0, 321, 115)];
[_imageView setFrame:CGRectMake(0, 0, 321, 115)];
[_actionButton setFrame:CGRectMake(0, 0, 320, 115)];
_scrollView.contentSize = CGSizeMake(300, 200);
}
-(void)storeImage:(UIImage *)image
{
self.imageView.image = image;
}
-(void)changeImage
{
[self.imageView setImage:[UIImage imageNamed:#"random.png"]];
}
synthesise is optional
and in BackgroundPickerView.h file it is something like below
#interface BackgroundPickerView : UIView
#property (nonatomic, strong) UIScrollView *scrollView;
#property (nonatomic, strong) UIImageView *imageView;
#property (nonatomic, strong) UIButton *actionButton;
-(void)storeImage:(UIImage *)image;
-(void)changeImage;
for image u check it it should work, check the image is present or not,
Edit
For the image, in controller for example,
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_viewA = [[BackgroundPickerView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_viewA];
}
//for testing
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[_viewA storeImage:[UIImage imageNamed:#"6.png"]]; //hear do this
}
I have a UIView that I am using as a simple onboarding view. I simply shows n images, that the user can swipe through.
The only image that loads is the very first image "OnBoard-1". The other images are there when I debug the what is being added to the image view.
What am I doing wrong?
.h
#import <UIKit/UIKit.h>
#interface OnBoardingView : UIView
- (void)setImages:(NSArray *)newImages;
#end
Here is the .m file
#import "OnBoardingView.h"
#interface OnBoardingView () <UIScrollViewDelegate>
{
UIPageControl *pageControl;
NSArray *contentImages;
}
#property (nonatomic, retain) UIPageControl *pageControl;
#property (nonatomic, retain) NSArray *contentImages;
#end
#implementation OnBoardingView
#synthesize pageControl;
#synthesize contentImages;
- (id) initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) { }
return self;
}
#pragma mark - Override contentImages setter
- (void)setImages:(NSArray *)newImages {
if (newImages != self.contentImages) {
self.contentImages = newImages;
[self setup];
}
}
#pragma mark - Carousel setup
- (void)setup {
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.frame];
[scrollView setDelegate:self];
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setPagingEnabled:YES];
[scrollView setBounces:NO];
CGSize scrollViewSize = scrollView.frame.size;
for (NSInteger i = 0; i < [self.contentImages count]; i++) {
CGRect slideRect = CGRectMake(scrollViewSize.width * i, 0, scrollViewSize.width, scrollViewSize.height);
UIView *slide = [[UIView alloc] initWithFrame:slideRect];
[slide setBackgroundColor:[UIColor colorWithRed:0 green:0 blue:0 alpha:0]];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.frame];
[imageView setImage:[UIImage imageNamed:[self.contentImages objectAtIndex:i]]];
NSLog(#"Image named: %#", [self.contentImages objectAtIndex:i]);
[slide addSubview:imageView];
[scrollView addSubview:slide];
}
UIPageControl *tempPageControll = [[UIPageControl alloc] initWithFrame:CGRectMake(0, scrollViewSize.height - 20, scrollViewSize.width, 20)];
[self setPageControl:tempPageControll];
[self.pageControl setNumberOfPages:[self.contentImages count]];
[scrollView setContentSize:CGSizeMake(scrollViewSize.width * [self.contentImages count], scrollViewSize.height)];
[self addSubview:scrollView];
[self addSubview:self.pageControl];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
[self.pageControl setCurrentPage:page];
}
#end
You initialise the imageView with the frame of the scrollView, that's in any case not right and may be the cause of your problem.
BTW:
Your property handling looks a bit strange (why the synthesizing instead of just using a normal property only?), and why do you compare the arrays by pointer (newImages != self.contentImages)?
If you want to show the images in paging directly you can assign the number of pages count.And apply the swipe gesture(left and right) to imageview.And based on left and right swipe,you can change the image of imageview.
I have been searching for hours ... Needless to say, I'm rather new in programming.
My goal is to display a subview programmatically and to remove it by tapping on it.
Already working: Displaying the subview and removing it by tapping on the view (code below).
Doesn't work - whatever I try: Removing the subview by tapping exclusively on the subview.
Thanks for your help!
My .h-file:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIImageView *canvas;
UIImageView *square;
}
#property (nonatomic, strong) UIImageView *canvas;
#property (nonatomic, strong) UIImageView *square;
#property (nonatomic) NSUInteger numberOfTouchesRequired;
- (void)handleSingleTap: (UITapGestureRecognizer *)singleTapGestureRecognizer;
#end
My .m-file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize canvas;
#synthesize square;
- (void)handleSingleTap: (UITapGestureRecognizer *)singleTapGestureRecognizer {
NSLog(#"tapGesture");
[square removeFromSuperview];
}
- (void)loadView {
canvas = [[UIImageView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame]];
[canvas setImage:[UIImage imageNamed:#"canvas.png"]];
self.view = canvas;
square = [[UIImageView alloc] initWithFrame:CGRectMake(170, 320, 40, 40)];
[square setImage:[UIImage imageNamed:#"square.png"]];
[self.view setUserInteractionEnabled:YES];
[canvas addSubview:square];
NSLog(#"square");
}
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
NSLog(#"initialize");
singleTapGestureRecognizer.numberOfTapsRequired = 1;
NSLog(#"number of taps");
[self.view addGestureRecognizer:singleTapGestureRecognizer];
NSLog(#"square gestureRecognizer");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If you want to remove a subview exclusively, when you tap on that view, then you will need to add tap gesture on that view
[square addGestureRecognizer:singleTapGestureRecognizer];
rather than
[self.view addGestureRecognizer:singleTapGestureRecognizer];
Edit
Also you will need to setUserInteractionEnabled to YES of UIImage because UIImage's setUserInteractionEnabled is default to NO.
[square setUserInteractionEnabled:YES];
Instead of
[self.view addGestureRecognizer:singleTapGestureRecognizer];
you should say
[square addGestureRecognizer:singleTapGestureRecognizer];
I am an elderly attempting to learn new-by. This works fine.
#implementation MESViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view= [[QuartzLineView alloc] initWithFrame:CGRectZero];}
-(void)Play{
for(int i=0;i<2000;i++){
short int lineno=function result;
CGRect myRect=CGRectMake(0,lineno, 1024,lineno+235);
[self.view setNeedsDisplayInRect:myRect];}
However using a scrollview the view does not seem to redraw at all.
Scrollview displays and takes touch input ok.
#import <UIKit/UIKit.h
#interface MESViewController : UIViewController<UIScrollViewDelegate>
#property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
#end
#implementation MESViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView=[[UIScrollView alloc] initWithFrame: CGRectMake(0, 0, x, y)];
self.scrollView.contentSize=CGSizeMake(x,y);
UIView *myview= [[QuartzLineView alloc] initWithFrame: CGRectMake(0, 0, x, y)];
[self.scrollView addSubview:myview];
self.view=self.scrollView;}
-(void)Play{...as above}
#implementation QuartzLineView
- (instancetype)initWithFrame:(CGRect)r{
self = [super initWithFrame:CGRectMake(0, 0, x, y];
if (self) {
self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1.0];
self.multipleTouchEnabled = YES;
}
return self;}
The issue is that when you set self.view to be the scrollview, you are still calling [self.view setNeedsDisplay] which will tell the UIScrollView that it needs display, and you want to tell the QuartzLineView that it needs display.
Saving a reference to the QuartzLineView, and calling setNeedsDisplay on that should do the trick:
#implementation MESViewController{
// save a reference to the QuartzLineView
QuartzLineView* lineView;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView=[[UIScrollView alloc] initWithFrame: CGRectMake(0, 0, x, y)];
self.scrollView.contentSize=CGSizeMake(x,y);
// saving the reference here
lineView= [[QuartzLineView alloc] initWithFrame: CGRectMake(0, 0, x, y)];
[self.scrollView addSubview:lineView];
self.view=self.scrollView;
}
-(void)Play{
for(int i=0;i<2000;i++){
short int lineno=function result;
CGRect myRect=CGRectMake(0,lineno, 1024,lineno+235);
// now tell the _lineView_ to setNeedsDisplay, instead of self.view
[lineView setNeedsDisplayInRect:myRect];
}
}