I want to have a pointer to an UIImage view so that I don't have to repeat a lot of my code. I need to choose the image based on which button it is but then at the end I apply the same code to whatever digit. oneDigit, twoDigit, and threeDigit are all #property(nonatomic, retain) in the header file. I want imageView to be able to point to one of these UIImageViews. Right now the UIImageViews are not being removed with removeFromSuperview because imageView is not pointing to the objects but creating its own object..
Currently when a button is pressed a Image is added. I want the previous image removed and the new image drawn according to what button was pressed. The code works how I want if I replace imageView with oneDigit, but that would require me to add more code for each variable.
See simplified example below:
- (void)viewDidLoad
{ ...
UIImageView *oneDigit;
UIImageView *twoDigit;
UIImageView *threeDigit;
}
-(IBAction)pressButton:(id)sender {
UIImage *image;
UIImageView *imageView;
UIButton *btn = (UIButton*)sender;
int value = [btn.titleLabel.text intValue];
switch (value) {
case 10:
case 15:
case 20:
[twoDigit removeFromSuperview]; //Remove old image from screen
imageView = twoDigit; //Update imageView pointer for current case
image = [UIImage imageNamed:#"twoDigit.png"];
break;
case 1:
case 2:
case 3:
case 4:
case 5:
[oneDigit removeFromSuperview];
imageView = oneDigit;
image = [UIImage imageNamed:#"oneDigit.png"];
break;
case 100:
case 200:
case 300:
[threeDigit removeFromSuperview];
imageView = threeDigit;
image = [UIImage imageNamed:#"threeDigit.png"];
break;
default:
break;
}
CGPoint point = btn.frame.origin;
CGFloat xposition = point.x - ((image.size.width - btn.frame.size.width) /2);
CGFloat yposition = point.y - ((image.size.height - btn.frame.size.height) /2);
imageView = [ [ UIImageView alloc ] initWithFrame:CGRectMake(xposition, yposition, image.size.width, image.size.height) ];
imageView.image = image;
imageView.contentMode = UIViewContentModeCenter;
[self.view addSubview:imageView];
}
Assuming that oneDigit, twoDigit and threeDigit are UIImageViews, you can just do something similar to
imageView = oneDigit;
Since both are pointers, setting imageView to oneDigit will simply point imageView to the location of oneDigit. When you set it to the new image, don't autorelease it first, because if it's set to threeDigit for example, it will autorelease threeDigit too.
Also, you don't need to set the image property of imageView manually after setting imageView to the new image, because it's essentially referencing the exact same UIImageView with the same image; it's just under a different name.
Related
I have a view, embedded into a container that it itself inside a UIScrollView.
This view contains a text aligned to its edges as well as a button, again aligned to edges.
When launching the controller view, inside viewDidLayoutSubviews, I get the actual real height of the screen, then I call the view to be resized this way :
- (void)viewDidLayoutSubviews {
[self log:#"ViewDidLayoutSubviews"];
//::.. change scroll height according to main view ..::
float mainHeight = _subMainView.frame.size.height;
float scrollHeight = mainHeight - _scrollView.frame.origin.y;
_scrollView.frame = CGRectMake(_scrollView.frame.origin.x, _scrollView.frame.origin.y, _scrollView.frame.size.width, scrollHeight);
//::.. find buttons in child ..::
UIViewController *child = [self.childViewControllers lastObject];
//::.. Get only block views ::..
NSArray *blockViews = [myTools getAllSubviewsFromView:child.view ofClass:[UIView class] byTagFrom:1000 toTag:1010];
[self resizeViews:blockViews intoFrame:_scrollView.frame withVerticalPadding:16.0f andTopMargin:(31.0f+16.0f) andBottomMargin:0.0f andLeftMargin:16.0f andRightMargin:16.0f];
NSArray *buttons = [myTools getAllSubviewsFromView:child.view ofClass:[UIButton class]];
[self resizeViews:buttons intoFrame:_scrollView.frame withVerticalPadding:16.0f andTopMargin:(31.0f+16.0f) andBottomMargin:0.0f andLeftMargin:16.0f andRightMargin:16.0f];
for (UIButton *button in buttons) {
[button invalidateIntrinsicContentSize];
}
}
And here is the resize code in question :
+ (void)resizeViews:(NSArray *)views intoFrame:(CGRect)parentFrame withVerticalPadding:(float)verticalPadding andTopMargin:(float)topMargin andBottomMargin:(float)bottomMargin andLeftMargin:(float)leftMargin andRightMargin:(float)rightMargin {
float blockHeight = ((parentFrame.size.height - topMargin - bottomMargin) / views.count);
blockHeight -= verticalPadding;
float origin = topMargin;
for (UIView *aView in views) {
[aView layoutIfNeeded];
for (NSLayoutConstraint *constraint in aView.constraints) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = blockHeight;
break;
}
}
origin += blockHeight + verticalPadding;
[aView setNeedsUpdateConstraints];
[aView layoutIfNeeded];
}
}
The visual result is good because both views and there content (the buttons) are correctly resized (the button is aligned centered vertically and horizontally so it is easy to show the good alignment).
However, the first button has is whole area touchable where the second one, under it, can be touched only on its upper height, before its middle...
Can't understand how it is possible that a button, who's size is good, become untouchable on its whole part ?
Any help ? :)
Thanks a lot.
I've developed method which make from rect UIImage to rounded. The problem is that it decrease performance if do that operation for 10 different images in a row. Images have resolution 120x120
- (UIImage *)roundedImage:(UIImage*)anOriginalImage radius:(CGFloat)aRadius
{
UIImage *result = nil;
if (anOriginalImage != nil) {
UIGraphicsBeginImageContextWithOptions(anOriginalImage.size, NO, 0);
[[UIBezierPath bezierPathWithRoundedRect:(CGRect){CGPointZero, anOriginalImage.size}
cornerRadius:aRadius] addClip];
[anOriginalImage drawInRect:(CGRect){CGPointZero, anOriginalImage.size}];
result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return result;
}
How to fix that?
Import the QuartzCore framework to get access to the .cornerRadius property of your UIView or UIImageView.
#import <QuartzCore/QuartzCore.h>
Also manually add it to your project's Frameworks folder.
Add this method to your view controller or wherever you need it:
-(void)setRoundedView:(UIImageView *)roundedView toDiameter:(float)newSize;
{
CGPoint saveCenter = roundedView.center;
CGRect newFrame = CGRectMake(roundedView.frame.origin.x, roundedView.frame.origin.y, newSize, newSize);
roundedView.frame = newFrame;
roundedView.layer.cornerRadius = newSize / 2.0;
roundedView.center = saveCenter;
}
To use it, just pass it a UIImageView and a diameter. This example assumes you have a UIImageView named "circ" added as a subview to your view. It should have a backgroundColor set so you can see it.
[self setRoundedView:circ toDiameter:100.0];
This just handles UIImageViews but you can generalize it to any UIView.
Hi there I have a table cell which contains amongst other things a UIImageView. I want to make this UIImageView have a rounded corner. Here's the code that I have (relevant snippets):
UIImageView* image;
image = (UIImageView*)[cell viewWithTag:0]; // get the UIImageView from the nib
image.image = [UIImage imageWithData:imageData]; // imagedata contains the image
image.layer.cornerRadius = 10.0;
image.layer.masksToBounds = YES;
image.clipsToBounds = YES;
When I do this, the entire UITableViewCell gets the rounded corners, instead of the UIImageView (see attached image).
Can someone tell me why the rounded corners are applied to the table cell rather than the uiImageView?
http://i.stack.imgur.com/CnkyQ.png
(UIImageView*)[cell viewWithTag:0];
In cell subviews you have only UITableViewCellContentView with tag == 0.
You can manually add the UIImageView to cell.
The problem should be the ...Tag:0:
image = (UIImageView*)[cell viewWithTag:0]; // get the UIImageView from the nib
If you are using a non-custom UITableViewCell replace that line with:
image = (UIImageView*)[cell imageView];
Else, replace the tag number.
.m:
-(void)accelerometer:(UIAccelerometer *)accelerometer
didAccelerate:(UIAcceleration *)acceleration
{
if(CGRectIntersectsRect(ball.bounds , fang.bounds))
{
UIImage *image = [UIImage imageNamed:#"guy.png"];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[self.view addSubView:imageview];
[imageview release];
}
NSLog(#"x : %g", acceleration.x);
NSLog(#"y : %g", acceleration.y);
NSLog(#"z : %g", acceleration.z);
delta.y = acceleration.y * 60;
delta.x = acceleration.x * 60;
ball.center = CGPointMake(ball.center.x + delta.x, ball.center.y + delta.y);
// Right
if(ball.center.x < 0) {
ball.center = CGPointMake(320, ball.center.y);
}
// Left
if(ball.center.x > 320) {
ball.center = CGPointMake(0, ball.center.y);
}
// Top
if(ball.center.y < 0) {
ball.center = CGPointMake(ball.center.x, 460);
}
// Bottom
if(ball.center.y > 460) {
ball.center = CGPointMake(ball.center.x, 0);
}
}
.h:
UIImageView *ball;
IBOutlet UIImageView *fang;
MY TROUBLES:
When I open the app, the image #"guy.png" reveals itself without anything touching the fang. I need help. ALSO//""**My accelerometer is SO choppy and barely works with this .m code :
if(CGRectIntersectsRect(ball.bounds , fang.bounds))
{
UIImage *image = [UIImage imageNamed:#"endScreenImage.png"];
UIImageView *imageview = [[UIImageView alloc] initWithImage:image];
[self.view addSubView:imageview];
[imageview release];
}
HELP PLEASE
A few issues:
CGRectIntersectsRect() is returning YES because you're comparing the bounds of your objects, not the frames. The bounds of an object is the rectangle describing how the object sees its own dimensions. It generally has its origin at (0,0), and the size is the size of the view. Since both views have a bounds starting at (0,0), the bounds rectangles do intersect.
What you really want is the frame of the views. The frame of a view represents the space occupied in that view, with respect to its superview. That is:
if (CGRectIntersectsRect(ball.frame, fang.frame)) { // etc. }
The frame represents the location of the view. The bounds represents the location of the content within the view itself. When you're comparing the position of two views, you almost always want to use frame.
As currently written, your code will add a new subview every time there's an intersection, but will never remove the old subview. Since the accelerometer can fire multiple times every second, this can result in a lot of views being added to the view hierarchy. That could significantly impact performance, and may be why you're seeing such poor performance. I would recommend instead creating a single UIImageView as an instance variable, and then use the hidden property to control whether it's visible or not.
Thus, I'd recommend you modify your code as follows:
if (CGRectIntersectsRect(ball.frame, fang.frame)) {
guyView.hidden = NO;
}
else {
guyView.hidden = YES;
}
I am struggeling with my UIScrollview to get it to zoom-in the underlying UIImageView. In my view controller I set
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return myImageView;
}
In the viewDidLoad method I try to set the zoomScale to 2 as follows (note the UIImageView and Image is set in Interface Builder):
- (void)viewDidLoad {
[super viewDidLoad];
myScrollView.contentSize = CGSizeMake(myImageView.frame.size.width, myImageView.frame.size.height);
myScrollView.contentOffset = CGPointMake(941.0, 990.0);
myScrollView.minimumZoomScale = 0.1;
myScrollView.maximumZoomScale = 10.0;
myScrollView.zoomScale = 0.7;
myScrollView.clipsToBounds = YES;
myScrollView.delegate = self;
NSLog(#"zoomScale: %.1f, minZoolScale: %.3f", myScrollView.zoomScale, myScrollView.minimumZoomScale);
}
I tried a few variations of this, but the NSLog always shows a zoomScale of 1.0.
Any ideas where I screw this one up?
I finally got this to work. what caused the problem was the delegate call being at the end. I now moved it up and .... here we go.
New code looks like this:
- (void)viewDidLoad {
[super viewDidLoad];
myScrollView.delegate = self;
myScrollView.contentSize = CGSizeMake(myImageView.frame.size.width, myImageView.frame.size.height);
myScrollView.contentOffset = CGPointMake(941.0, 990.0);
myScrollView.minimumZoomScale = 0.1;
myScrollView.maximumZoomScale = 10.0;
myScrollView.zoomScale = 0.7;
myScrollView.clipsToBounds = YES;
}
Here is another example I made. This one is using an image that is included in the resource folder. Compared to the one you have this one adds the UIImageView to the view as a subview and then changes the zoom to the whole view.
-(void)viewDidLoad{
[super viewDidLoad];
UIImage *image = [UIImage imageNamed:#"random.jpg"];
imageView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imageView];
[(UIScrollView *) self.view setContentSize:[image size]];
[(UIScrollView *) self.view setMaximumZoomScale:2.0];
[(UIScrollView *) self.view setMinimumZoomScale:0.5];
}
I know this is quite late as answers go, but the problem is that your code calls zoomScale before it sets the delegate. You are right the other things in there don't require the delegate, but zoomScale does because it has to be able to call back when the zoom is complete. At least that's how I think it works.
My code must be completely crazy because the scale that I use is completely opposite to what tutorials and others are doing. For me, minScale = 1 which indicates that the image is fully zoomed out and fits the UIImageView that contains it.
Here's my code:
[self.imageView setImage:image];
// Makes the content size the same size as the imageView size.
// Since the image size and the scroll view size should be the same, the scroll view shouldn't scroll, only bounce.
self.scrollView.contentSize = self.imageView.frame.size;
// despite what tutorials say, the scale actually goes from one (image sized to fit screen) to max (image at actual resolution)
CGRect scrollViewFrame = self.scrollView.frame;
CGFloat minScale = 1;
// max is calculated by finding the max ratio factor of the image size to the scroll view size (which will change based on the device)
CGFloat scaleWidth = image.size.width / scrollViewFrame.size.width;
CGFloat scaleHeight = image.size.height / scrollViewFrame.size.height;
self.scrollView.maximumZoomScale = MAX(scaleWidth, scaleHeight);
self.scrollView.minimumZoomScale = minScale;
// ensure we are zoomed out fully
self.scrollView.zoomScale = minScale;
This works as I expect. When I load the image into the UIImageView, it is fully zoomed out. I can then zoom in and then I can pan the image.