I'm trying to subclass a UIView that contains a UIScrollView inside of it. This is the code I'm using:
UIViewSubclass.h
#property (nonatomic, retain) UIScrollView *scroll;
UIViewSubclass.m
#synthesize itemScrollView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setUpScrollViewWithIdentifier:#"id"];
}
return self;
}
-(void)setUpScrollViewWithIdentifier:(NSString*)scrollViewID {
NSLog(#"Setting up Scroll View with the id of: %#",scrollViewID); //This is working
scroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 90)];
//Subview of the scroll view
UIView *test = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 50, 50)];
test.backgroundColor = [UIColor blueColor];
[scroll addSubview:test];
[self addSubview:scroll]; // Adds the scrollview to the UIView
NSLog(#"Subviews: %#",self.subviews);
}
ViewController.h
#import "UIViewSubclass.h"
IBOutlet UIViewSubclass *menuView;
View Controller.m
- (void)viewDidLoad
{
menuView = [[UIViewSubclass alloc]init];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
I also linked the view up in the storyboard and set the view's class to UIViewSubclass but for somereason the scroll view won't appear. But when i check this NSLog:
NSLog(#"Subviews: %#",self.subviews);
It gives me this in the debugger:
Subviews: (
"<UIScrollView: 0x1d5a20e0; frame = (0 0; 320 90); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x1d5a2420>; layer = <CALayer: 0x1d5a1c60>; contentOffset: {0, 0}>"
)
So what am I doing wrong?
scroll.contentSize = fooSize;
might be what you missing.
Related
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 am trying to add header and footer (both of them as UIViews) but for some reason my footer sticks to the bottom, I'm using the KVO method for watching my content size.
I'm presenting here the method where I think the problem is:
- (void)updateLayout
{
// Update the frame of the header view so that it scrolls with the webview content
CGRect newHeaderFrame = self.headerView.frame;
CGRect newFooterFrame = self.footerView.frame;
newHeaderFrame.origin.y = -CGRectGetMinY([self.webView convertRect:self.innerHeaderView.frame toView:self.webView.scrollView]);
newFooterFrame.origin.y = self.webView.scrollView.contentSize.height;
[self.headerView setFrame:newHeaderFrame];
[self.footerView setFrame:newFooterFrame];
if ([self didTapToFullScreen])
{
// The delegate was already called in this case, in the tap gesture callback method
return;
}
BOOL fullScreen = (newHeaderFrame.origin.y < 0);
if (([self isZooming] && [self didSwitchToFullScreen]) || (fullScreen == [self isFullScreen]))
{
return;
}
[self setSwitchToFullScreen:fullScreen];
[self setFullScreen:fullScreen];
// Call the delegate for the full screen
[self.fullScreenDelegate emailView:self showFullScreen:fullScreen];
}
Here's the full project
How I can place the footer to the bottom of the UIWebView ?
You can set the views on UIWebView scroll view, and fiddle with the offsets.
#interface ViewController ()<UIWebViewDelegate>
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#property (nonatomic, strong) UIView *headerView;
#property (nonatomic,strong) UIView *footerView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.headerView = [[UIView alloc] initWithFrame:CGRectMake(0, -100, [UIScreen mainScreen].bounds.size.height, 100)];
self.headerView.backgroundColor = [UIColor blueColor];
self.footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
self.footerView.backgroundColor = [UIColor yellowColor];
NSString *urlText = #"http://stackoverflow.com/questions/15921974/how-to-load-url-on-launch-in-a-webview-osx-project";
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlText]]];
self.webView.delegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - WebView delegate
-(void) webViewDidFinishLoad:(UIWebView *)webView {
self.webView.scrollView.contentInset = UIEdgeInsetsMake(100.0,0.0,100.0,0.0);
if(![self.headerView superview])
{
[webView.scrollView addSubview:self.headerView];
[webView.scrollView bringSubviewToFront:self.headerView];
}
NSString *result = [webView stringByEvaluatingJavaScriptFromString:#"document.body.offsetHeight;"];
NSInteger height = [result integerValue];
self.footerView.frame = CGRectMake(0, height, [UIScreen mainScreen].bounds.size.height, 100);
if(![self.footerView superview])
{
[webView.scrollView addSubview:self.footerView];
[webView.scrollView bringSubviewToFront:self.footerView];
}
[self.webView.scrollView setContentOffset:
CGPointMake(0, -self.webView.scrollView.contentInset.top) animated:NO];
}
#end
Another option would be to add top padding to the HTML ("margin-top:100px") and then the header view would not be in minus offset.
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];
}
}
I have a ViewController in a storyboard consisting of two UIViews and a table at the bottom. the center of the screen contains a UIView defined in the storyboard with an outlet called middleSectionView. I want to programmatically add a subView to middleSectionView. The programmatically added subView is not appearing. Here's my code:
RoundedRect.m:
#import "RoundedRect.h"
#implementation RoundedRect
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSLog(#"RoundedRect: initWithFrame: entering");
UIView* roundedView = [[UIView alloc] initWithFrame: frame];
roundedView.layer.cornerRadius = 5.0;
roundedView.layer.masksToBounds = YES;
roundedView.layer.backgroundColor = [UIColor redColor].CGColor;
UIView* shadowView = [[UIView alloc] initWithFrame: frame];
shadowView.layer.shadowColor = [UIColor blackColor].CGColor;
shadowView.layer.shadowRadius = 5.0;
shadowView.layer.shadowOffset = CGSizeMake(3.0, 3.0);
shadowView.layer.opacity = 1.0;
// [shadowView addSubview: roundedView];
}
return self;
}
#end
.h:
...
#property (strong, nonatomic) IBOutlet UIView *middleSectionView;
.m:
...
#import "RoundedRect.h"
...
- (void)viewDidLoad
{
RoundedRect *roundRect= [[RoundedRect alloc] init];
roundRect.layer.masksToBounds = YES;
roundRect.layer.opaque = NO;
[self.middleSectionView addSubview:roundRect]; // This is not working
[self.middleSectionView bringSubviewToFront:roundRect];
// [self.view addSubview:roundRect]; // This didn't work either
// [self.view bringSubviewToFront:roundRect]; // so is commented out
...
}
The reason why you do not see the RoundedRect is that you are calling a wrong initializer: this line
RoundedRect *roundRect= [[RoundedRect alloc] init];
does not invoke the initWithFrame: initializer that does all the work initializing your RoundedRect view. You need to change the call to
RoundedRect *roundRect= [[RoundedRect alloc] initWithFrame:CGRectMake(...)];
and put the desired coordinates of the frame in place of the ... above.
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];
}