I have 30-40 tabs open, I've found my answer.. but I'm wishing to improve.
The code does work, I am just not sure if it is efficient
The following code shows that I have 2 small images (One using UIImageView, another using UIView) in which I have attached to a UIScrollView, which is attached to a UIView which came with the UIViewController, which is attached to the UIWindow. Pretty basic.
I also have a button attached to the UIViewController to make sure zooming and scrolling worked. (By testing the static location of the button and size)
#interface Wire_TestViewController : UIViewController <UIScrollViewDelegate> {
UIScrollView *scrollview;
}
#end
Implementation:
- (void)test:(UIButton *)sender { }
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { return scrollview; }
- (void)viewDidLoad {
[super viewDidLoad];
scrollview = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
scrollview.delegate = self;
scrollview.contentSize = CGSizeMake( 320*2, 480*2 );
scrollview.minimumZoomScale = .1;
scrollview.maximumZoomScale = 10;
[self.view addSubview:scrollview];
UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(320, 320, 20, 20)];
view.image = [UIImage imageNamed:#"Node.png"];
view.clearsContextBeforeDrawing = NO;
[scrollview addSubview:view];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(10, 10, 100, 30);
button.tag = 51;
[button setTitle:#"new button" forState:(UIControlState)UIControlStateNormal];
[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
UIView *view2 = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 30, 30)];
view2.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"WireActive.png"]];
[scrollview addSubview:view2];
TestSubclass *test = [[TestSubclass alloc] initWithFrame:CGRectMake(100, 100, 50, 50)];
test.userInteractionEnabled = TRUE;
test.image = [UIImage imageNamed:#"Node.png"];
[scrollview addSubview:test];
}
You'll see near the bottom I have a TestSubclass class made.
The code for that is as follows:
#interface TestSubclass : UIImageView { }
#end
#implementation TestSubclass
- (id)init {
[super init];
self.userInteractionEnabled = TRUE;
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
printf("Being touched...\n");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
printf("Touches Ended...\n");
}
#end
The part in which I am happy with is that I have a fully functioning Subclass of UIImageView which works as if it was a UIButton.
BUT! without the 7 backgroundImageViews (and the overhead from each of those), without the 6 labels (and the overhead from each of those), without the 6 UIImageViews ("..."), and lastly the amount of un-needed things that UIButton offers. I only wanted touch capabilities.. efficiently however. (TouchUpInside, Dragging, etc)
But, now during my research (after the extensive testing to accomplish this much), I've come across in documentation and some examples addGestureRecognizer in UIView. It seems sorta-but not entirely efficient for my needs.
I'm looking for advice, I know there are a couple problems in my code (overrided init, but didn't use it in the above code.. didn't release.. probably some subclassing mistakes (new to subClassing (to be honest)). But anything is much appreciated!! And, I hope others are helped as well!
If you want to have full control capabilities, you must subclass UIControl and use your image with in. The image can be an UIImageView subview or can be drawn in the drawRect method of your subclass or set in the CALayer view content.
Note that subclassing UIControl is not the easiest thing to do, but it gives you all "control" feature it seems you are requesting from it and I think is the most efficient or appropriate approach.
Related
Very strange behaviour from UIScrollView. Kindly check the following code
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
UIScrollView *scrView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
scrView.delegate =self;
[scrView setContentSize:CGSizeMake(95000, self.view.bounds.size.height)];
scrView.backgroundColor = [UIColor clearColor];
Testview *test = [[Testview alloc]initWithFrame:CGRectMake(0, 0, scrView.contentSize.width, self.view.bounds.size.height)];
test.backgroundColor = [UIColor greenColor];
[scrView addSubview:test];
[scrView flashScrollIndicators];
[self.view addSubview:scrView];
self.view.backgroundColor = [UIColor clearColor];
}
Testview is a subview of Scrollview.
#implementation Testview
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
}
In Testview class, if I call the method - (void)drawRect:(CGRect)rect, Uiscrollview goes blank and unable to view the scrollview in runtime. But if I comment drawRect method
#implementation Testview
//- (void)drawRect:(CGRect)rect {
//
// [super drawRect:rect];
//}
it works perfect.I am breaking my head to solve this, please help me out to solve this issue. I need drawRect to work if the content size width and subview width are more than 95000.
Your view is too big for ordinary -drawRect:. You should try backing your view with a CATiledLayer which serves this purpose.
Answering to my question. If we use CATiledLayer layer you will able to use -drawRect: of UIVIew irrespective of maximum width subview given to scrollview. But -drawRect: method will be called every time a tile needs to be displayed. This piece of code helped me.
+ (Class) layerClass
{
return [CATiledLayer class];
}
I am facing weird problem. I have a baseViewController which extends with UIViewController.
in My BaseView controller i have a custom HeaderBar (UIImageView) on top of it.
I then made a new ViewController and extends that new ViewController with baseViewController. The headerBar in BaseViewController is appearing on my UIViewController. But now if I add any subview in my NEWViewController over that headerBar then it does not come over that whereas it goes behind the header bar.
Can anybody suggest what to do.
EDITED
Here is my code.
BASEViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
CGFloat xOffset = 0;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
xOffset = 224;
}
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
headerBarView = [self addHeaderBar];
//[self.view addSubview:headerBarView];
[self.view insertSubview:headerBarView belowSubview:self.view];
}
return self;
}
-(UIView *)addHeaderBar{
UIView *header_bar = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320, 50.0)];
//HeaderBar Image
UIImageView *headerBar = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0.0, 320, 50.0)];
[headerBar setImage:[UIImage imageNamed:#"top_bar"]];
[header_bar addSubview:headerBar];
return header_bar;
}
NEWViewController Extended With BaseViewController
//Back Button
back = [UI getActionBarButtonWithName:[NSString stringWithFormat:#"Back"] andCGRect:CGRectMake(7.0, 100.0, 55.0, 31.0) andEdgeInset:UIEdgeInsetsMake(0.0, 9.0, 2.0, 0.0) withBackGround:[UIImage imageNamed:#"back_button"]];
[self.view bringSubviewToFront:back];
+(UIButton *)getActionBarButtonWithName:(NSString *)name andCGRect:(CGRect)rect andEdgeInset:(UIEdgeInsets)edgeInset withBackGround:(UIImage *)background{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = rect;
[button setBackgroundImage:background forState:UIControlStateNormal];
[button setTitleEdgeInsets:edgeInset];
[button setTitle:name forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:13.0]];
[button setUserInteractionEnabled:YES];
return button;
}
if you are having many views, you can also use any one of these -
[self.view insertSubview:<#(UIView *)#> aboveSubview:<#(UIView *)#>]
[self.view insertSubview:<#(UIView *)#> atIndex:<#(NSInteger)#>]
[self.view insertSubview:<#(UIView *)#> belowSubview:<#(UIView *)#>]
hope it will help you.
Try using
[self.view bringSubviewToFront:button];
New UIVIew override your base viewcontroller,you can set frame of new view and then add subview.
Ex. UIView* tempView=[UIView alloc]initWithFrame:CGRectMake(0,44,320,420)];
[self.view addSubView:temView];
On iOS, I created a button programmatically but the event is not firing.
UIButton * anyButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[anyButton addTarget:self action:#selector(handleAnyButton:) forControlEvents:UIControlEventTouchUpInside];
anyButton.frame = CGRectMake(150, 350, 22, 22);
[self addSubview:anyButton];
The code is placed inside a custom view (not custom view controller), but I cannot make it fire the event. The press animation is not showing. The custom view has userInteractionEnabled enabled. I also tried using storyboard to create another button on the same view and that one is working. The button code is done in initWithFrame. Must be some simple error I haven't caught and I have been pounding my head over this one for hours.
EDIT:
The event handler:
-(void) handleAnyButton:(UIButton *)button
{
NSLog(#"handleAnybutton called");
}
EDIT2:
The above button codes is done within a [self setup] of class PKLocationsSelectionView.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setup];
}
return self;
}
And this view was created programmatically within the view controller (PKLocSelectionViewController) responsible for this hierarchy:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat fieldsHeight = 88;
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, fieldsHeight)];
[self.view addSubview:view];
}
It looks like your button frame
anyButton.frame = CGRectMake(150, 350, 22, 22);
is outside of parent bounds
CGFloat fieldsHeight = 88;
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, fieldsHeight)];
Here is the code that works for me:
MyCustomView.m:
#import "MyCustomView.h"
#implementation MyCustomView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 100, 100);
[button addTarget:self action:#selector(greet:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Greet" forState:UIControlStateNormal];
[self addSubview:button];
self.backgroundColor = [UIColor greenColor];
}
return self;
}
-(void) greet:(id) sender
{
NSLog(#"greet!");
}
And here is the ViewController.m:
- (void)viewDidLoad
{
[super viewDidLoad];
MyCustomView *view = [[MyCustomView alloc] init];
view.frame = CGRectMake(0, 0, 100, 100);
[self.view addSubview:view];
}
EDIT2: Could it be the Button is not fully enclosed within the coordinates of the container (PKLocationsSelectionView) view?
The height of the PKLocationsSelectionView is 88 from your code and the position of the button seems to be outside this. I think if the button is not enclosed within the frame of the superview then it won't receive touches.
Try and change your View initialization code in viewDidLoad, to give a static frame and see if it works..
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
CGFloat fieldsHeight = 88;
//See the change in below line.. instead of using self.view.bounds.size.width
// I used a static width.. 320 pixel for the moment..
UIView * view = [[PKLocationsSelectionView alloc] initWithFrame:CGRectMake(0, 0, 320.0, fieldsHeight)];
[self.view addSubview:view];
}
In viewDidLoad view hierarchy of controller will not be drawn completely..So self.view.bounds.size.width may be giving incorrect values.. To access self.view.frame and self.view.bounds, you should atleast wait until viewWillAppear gets called.
Also, your button origin.y is at 350 which in a view which has maximum height of only 88.. Any control outside parent's frame won't receive touches..
Hi, I have a big image and small image over it at a specific location...
I added them all under ScrollView, but it didn't work properly?
I want to zoom in, all together each in its place
Here is my code:
myScrollView.contentSize = CGSizeMake(imageView.frame.size.width, imageView.frame.size.height);
myScrollView.maximumZoomScale = 3.0;
myScrollView.minimumZoomScale = 1.0;
myScrollView.clipsToBounds = YES;
myScrollView.delegate = self;
[myScrollView addSubview:imageView];
thanks
Hi, mackworth; I did it, but if I didn't maximize the image, I can't move the scroll view anywhere, but if I zoomed it, I can see the rest.. I don't know why I tried changing it, but it work. Can you please look at the following code?
- (void)viewDidLoad{
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"ucd.png"];
//creating a view for UCD image
ucdView = [[UIImageView alloc] initWithImage:image];
//setting the frame for the ucdView as the same size of ucd image
[ucdView setFrame:CGRectMake(0, 0, image.size.width, image.size.height)];
//for the red pin to display in specific loc
UIImageView *Health = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"redPin.png"]];
[Health setCenter:CGPointMake(310,135)];
//adding helathView to ucdview
[ucdView addSubview:Health];
//everything for scroll view
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, ucdView.frame.size.width, ucdView.frame.size.height)];
[scrollView setMinimumZoomScale:1.0];
[scrollView setMaximumZoomScale:3.0];
scrollView.clipsToBounds = YES;
[scrollView setContentSize:CGSizeMake(image.size.width, image.size.height)];
[scrollView setDelegate:self];
[scrollView addSubview:ucdView];//adding ucd view to scroll view
[self.view addSubview:scrollView]; // adding scrollview to self.view main view
}
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {//apply zooming for scrollview
return scrollView;
}
Did you implement:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.imageView;
}
Also, you know that by setting the scrollView's contentSize to your imageSize, it can't grow any bigger than that, right? It'll zoom in place, cropping the outer pixels accordingly. As an aside, if that is your plan, why not just set it directly?
myScrollView.contentSize = imageView.frame.size;
=====Further answer, responding to additional source
Well, the main thing I notice is that you need to return the imageView ucdView in viewForZoomingInScrollView, not the scrollView. It looks like you already created ucdView as a property (so that it lives as long as your view does), but just in case...
1) In your .h file:
UIImageView * ucdView;
#property (nonatomic, retain) UIImageView * ucdView;
2) In your .m file;
#synthesize ucdView;
3) change your line:
ucdView = [[UIImageView alloc] initWithImage:image];
to just
self.ucdView = [[UIImageView alloc] initWithImage:image];
4) change the line
return scrollView
to:
return self.ucdView;
5) Add the following to your dealloc routine:
self.ucdView = nil;
Also, did you add <UIScrollViewDelegate> protocol to your ViewController definition (in .h file)?
Finally, you have a leak of scrollview and Health; add [scrollView release]; and [Health release] at end of viewDidLoad
I'm doing an iPhone ap which contains a viewController class (PhotoListViewController). This viewController's view has a subview which contains a button attached as a subview. I'm trying to use the addTarget:action:forControlEvent method to call an instance method of the PhotoListViewController class in order to perform an action when the button is pressed but the method is not being called. Any thoughts on how to make this work?
Here's the pertinent code. I know your first though will be why am I nesting subviews, but this just a distilled version of my program - there are reasons I'm doing the nesting. I know there are probably other ways of setting up the program so I don't have to do this nesting, but my real question is - why does this not work?
/Code/
#implementation PhotoListViewController
- (void)loadView {
[super viewDidLoad];
//load elements into the viewController
//first create the frame
CGRect frameParent = CGRectMake(0, 0, 0, 0);
UIView *viewPerson = [[UIView alloc] initWithFrame:frameParent];
CGRect frameChild = CGRectMake(0, 20, 0, 0);
UIView *newView = [[UIView alloc] initWithFrame:frameChild];
UIButton *btnShow = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnShow.frame = CGRectMake(230, 120, 80, 30);
[btnShow setTitle:#"View!" forState:UIControlStateNormal ];
[btnShow addTarget:self
action:#selector(viewPhoto_click:)
forControlEvents:UIControlEventTouchUpInside];
[newView addSubview:btnShow];
[viewPerson addSubview:newView];
[newView release];
[self setView:viewPerson];
[viewPerson release];
}
- (void)viewPhoto_click:(UIButton*)sender {
NSLog(#"HI");
}
It may not be related, but both viewPerson and newView have a width and height of 0. You may want to give these views a non-null size (the 3rd and 4th arguments of CGRectMake).
action:#selector(viewPhoto_click:)
forControlEvents:UIControlEventTouchUpInside];
May be a copy paste typo but have you tried to remove the : after the viewPhoto_click after the selector?
Also. In most examples the event Handler look like this.
- (void) viewPhoto_click: (id)sender
Not sure if it makes any difference though