Make Image Wrap Around Screen Edge? - iPhone Obj-C - iphone

I couldn't figure out a quick, concise way to explain what I'm trying to accomplish (which has made it difficult to find an answer searching Google), so I'll just try to elaborate more here. What I am trying to accomplish is moving a UIImageView to the top edge of the iPhone's screen and then keep moving it up, but once the image passes the top edge, have it appear at the bottom of the screen, as it continues moving through.
I've been using the basic [UIView commitAnimations] commands for the basic moving of objects in my application, so it'd be nice if this could be accomplished using using that (though it doesn't have to).

You don't need to mess around with scroll views or switch to cocos2d to implement simple animations. All you need to do is create 2 CALayer objects and then assign layer.contents to the same image.
CALayer *layer1 = [CALayer layer]
CALayer *layer2 = [CALayer layer]
UIImage *image = [UIImage imageNamed:#"whatever.png"];
layer1.contents = (id) image.CGImage;
layer2.contents = (id) image.CGImage;
Then use a normal animation to update the position of the two frames as described this Apple QA doc. You just need to determine the height of the window and then make sure that the start and end Y points of the 2 CALayers are always 1 height of difference. So, when layer1 animates to Y = -1 that means that layer2 would be at Height-1. Only when both layers are partially exposed would you see then both, that is how you get this effect to work and seem to be only 1 layer.

I think you could do this with a UIScrollView... here's something I wrote on cyclic scroll views a while ago.
I would begin by making the content size be the height of the window with the image view at one edge. As the image scrolls off the visible area the next page is coming into view with another image that looks the same but is not. I think this could save you a lot of frame calculations, nested animation blocks and other confusions. You could certainly do it with discrete views but I think it could be reinventing the wheel.

The best way to implement this is to create a CCNode subclass that will contain first and second sprite and will swap them if required. In this way all your logic will be very simple. You will just work with one CCNode (subclass) and will not think about swaping sprites - it will be done automatically by your class
#interface MyNode : CCNode
{
CCSprite *sprite1;
CCSprite *sprite2;
CCSprite *currentSprite;
bool isChanging; //indicates that now two sprites are visible
}
#end

Related

Hide / reveal UIImage based on finger path?

I hope that makes sense. I'll try to explain it.
I have a UIImageView on screen, and am wondering how I can take the area after "drawing" on it with a finger, and remove that section from the UImage, or, create a separate UIImage from the selection.
I'm not looking for code (unless you have it =] ), just an idea of how to go about doing it. If you have tips, I'd be very grateful, thanks.
If I understand your question,
I think I would add a transparent UIView as a subview over the top of the UIImageView. And draw on that. Then you can remove/hide the subview when your done.
you need to create a UIGestureRecognizer with target and a action like -imageIsPressed, in this -imagePressed method you can call something to make the image disappear. I would suggest placing the UIImage into a UIImageView and calling imageview.hidden = YES; to hide the image, and set it back to "NO" once its not held by the finger.
You'd need to implement something that captures the area the user 'selected' (maybe be creating a CGPath. Then you create a CALayer of the size of the imageView. In it you create, draw and fill the captured path with some arbitrary color while leaving the rest transparent. Finally you apply your generated CALayer as a mask to the UIImageView:
imageView.layer.mask = maskLayer;
Hope that gets you started.
For more info on how to draw that custom CALayer pls refer to Quartz Programming Guide
So basically you want to implement freehand erasing of an image? You will need to use core graphics and the various CGContext methods (with blend mode set to clear) to achieve this. There are two approaches, but both start with drawing your image as the first part of drawRect, and then
1) Store your strokes in an array, and stroke all of them over top of the image.
2) Stroke one stroke over the image and then store the resulting image into a UIImage. Use this UIImage as the next image that you draw in drawRect. This one is difficult for undo/redo functionality.
I recently implemented this myself and made the source available here. Basically I used the same methods described here with this change when setting up the graphics context:
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);

Iphone sdk, Rounded UIImageView FRAME corners, not just masking it

i am building a app in which if a UIImageView hits another something happens, i am using the CGRectIntersetsRect statement, i would like to make it as accurate as i can, at the moment i have about 8 UIImageViews inside this one UIImageView and i am detecting if something hits them 8 little views, i have decided that this is not a very accurate way to go about it. The problem is that the UIImageView the other UIImageView's are in, Its a Oval, so it is complicated, i have tryed masking it, using the
image.layer.radius 10.0 or whatever the code is.
but this doesnt actually transform the whole frame, is there any way to actually transform the whole frame so when a UIImageView hits the Oval shape then something happens?
if so could someone explain it to me.
Thanks
Harry
this is really simple indeed. As a View, UIImageView has a layer and a layer has cornerRadius properties:
imageView.layer.cornerRadius = 5.0;
imageView.layer.masksToBounds = YES;
eBuildy, iPhone specialists
A UIImageView's frame is a CGRect, a CGRect is a rectangle and a rectangle has no rounded properties.

Creating a custom animation with CGLayers?

Basically, I want to animate a shrinking circle. I've already done this by drawing progressively smaller circles onto CGLayer's, and then using
if(index < 30){
[self performSelector:#selector(showNextLayer) withObject:nil afterDelay:(NSTimeInterval)0.02];
index++;
}
in my showNextLayer method. This works for my simple goal, but in general is this a more or less sensible way to draw a custom animation?
Apple has a lot of documentation on animation -enough to confuse me-, but as far as I -finally- understand:
The animation services provided by UIView is good for animating some basic view properties, view transitions etc.,
those provided by classes that inherit from CAAnimation, are good for animating properties like color change, 3d transformations etc.
UIViewImage is good for animating custom bitmap images (and it is not a good idea to create bitmap images when you can just draw circles into a CGLayer instead).
It seems to me that displaying the contents of a sequence of CGLayer 's would also be supported, am I missing something?
Thanks in advance for any clarification..

CATiledLayer blanking tiles before drawing contents

All,
I'm having trouble getting behavior that I want from CATiledLayer. Is there a way that I can trigger the tiles to redraw without having the side-effect that their areas are cleared to white first? I've already subclassed CATiledLayer to set fadeDuration to return 0.
To be more specific, here are the details of what I'm seeing and what I'm trying to achieve:
I have a UIScrollView with a big content size...~12000x800. Its content view is a UIView backed by a CATiledLayer.
The UIView is rendered with a lot of custom-drawn lines
Everything works fine, but the contents of the UIView sometimes change. When that happens, I'd like to redraw the tiles as seamlessly as possible. When I use setNeedsDisplay on the view, the tiles redraw but they are first cleared to white and there's a fraction-of-a-second delay before the new content is drawn. I've already subclassed CATiledLayer so that fadeDuration is set to 0.
The behavior that I want seems like it should be possible...when you zoom in on the scrollview and the content gets redrawn at a higher resolution, there's no blanking before the redraw; the new content is drawn right on top of the old one. That's what I'm looking for.
Thanks; I appreciate your ideas.
Update:
Just to follow up - I realized that the tiles weren't being cleared to white before the redraw, they're being taken out entirely; the white that I was seeing is the color of the view that's beneath my CATiledLayer-backed view.
As a quick hack/fix, I put a UIImageView beneath the UIScrollView, and before triggering a redraw of the CATiledLayer-backed view I render its visible section into the UIImageView and let it show. This smooths out the redraw significantly.
If anyone has a better solution, like keeping the redraw-targeted tiles from going away before being redrawn in the first place, I'd still love to hear it.
I've found that if you set levelsOfDetailBias and levelsOfDetail both to the same value (2 in my case), then it only redraws the tiles that are touched by my setNeedsDisplayInRect: call, as you'd hope.
However if the levelsOfDetail is different to LODB, then any calls to setNeedsDisplayInRect: redraw all the tiles.
You could add another layer (possibly a CATiledLayer) behind the existing tiled layer. (Sort of a double-buffered solution.) You would call setNeedsDisplay: on the second layer from a timer that fires after a few seconds to ensure that that layer doesn't redraw at the same time as the front layer.
Another potential option is to use the same delegate to draw content to a bitmap context and swap the bitmap into the backing store once the content is refreshed. This should produce a flicker-free result. That being said, I can't tell you how this might be done, and one nice thing about CATiledLayers is they automatically generate tiles when you zoom and pregenerate tiles when you pan once zoomed in.
I would like to see how you implement your application. I have been looking for weeks to find an example that uses a combination of UIScrollView and a CATiledLayer-back view with a lot of custom drawn lines. Apple has some great sample code - but it all involves images rather than line art, so no help for me.
Having read through these answers without a solution, I discovered that tiling a page was the dominant background task.
Preparing my lo-res placeholder image on a high priority queue solved this issue - the images now appear while the tiling is occurring. Caching the placeholder images further improves their appearance - they appear before the tiling begins.
With newer devices, the tiling it so fast, these tricks might not matter. A sample PDF consisting of large scanned images (e.g. a scanned book) tiles the slowest in my experience, and makes for good test data.
I had the same problem with iPad.
The solution was more simple than I thought and far more simple than using UIImageView to render display before redrawing... :
Just don't set any background color for the Layer!
I had CATiledLayer set in a similar way:
layer = [[CATiledLayer alloc] init];
layer.masksToBounds = YES;
layer.contentsGravity = kCAGravityLeft;
//layer.backgroundColor = [[UIColor whiteColor] CGColor];
layer.tileSize = CGSizeMake(1004.0, 1004.0);
layer.levelsOfDetail = 16;
layer.levelsOfDetailBias = 8;
Note that I have commented out the line setting layer's background color to white.
After that the white blank before redraw problem disappeared!
Let me know if anyone has tried that.

Change the z-order of subviews on the iPhone

I'm developing a game. I'm using about 150 UIImageView to hold the graphics. I'm simulating a 3D enviroment, so i would like to change the z-order (how close is an object to the camera).
I know there exists :
[superWindow exchangeSubviewAtIndex:i withSubviewAtIndex:j];
But for some reason it's not working, some of the subviews disappear an re-appear.
Now I just remove all subviews and add it again in the correct z-order, this is ok with 50 subviews (on a 2G iphone) but with 120 it takes half a second so the gameplay sucks (I dont have and 3GS so i didn't try there).
I'm using so many subviews because each one is a square, then i colored it, resize it and move it somewhere in the screen. I'm holding the subviews under a NSMutableArray...
The iPhone documentation often warns about multiple UIViews nested, as it has a large performance hit after a certain point. If you start getting into issues one option is to render your UIViews into an image and using that to lower the number of on-screen views, but if you're simulating 3D that probably isn't going to help much since your composite view would need re-rendering too often.
The iPhone has full support for OpenGL ES, which allows for a real 3D environment. Take a look at some of the samples and/or a good book on the topic and you'll find that it's much easier to simply use OpenGL.
Z-order is an artifact of where your view appears in your superview's list of subviews. The last subview added to the superview is "on top".
So, to move a view to the be "on top", you remove it from its superview, then re-add it -- making it the last one and, therefore, on top.
Here, a view moves himself to the top of the z-order.
// move to the to in the z-order
UIView* superview = [self superview];
[self retain];
[self removeFromSuperview];
[superview addSubview:self];
[self release];
Note the [self retain] to prevent your dealloc if your superview is the only reference to you.
If you don't want to take the plunge to OpenGL ES, as Timothy suggests, you might want to look at replacing the UIViews with CALayers and placing them within a CATransformLayer. CATransformLayer is new in iPhone OS 3.0, and it lets you do a true 3-D layout of the CALayers. You can then set the zPosition property on your CALayers to locate them in the Z plane of the CATransformLayer. For more on 3-D layout of CALayers, I direct you to this article.
You can even add a nice perspective effect on the overall CATransformLayer by setting the m34 element in the CATransform3D applied to that layer.
Changing from UIViews to CALayers is pretty straightforward, because their structures have much in common.
Consider using a 2D game library like Cocos2D. I'm pretty sure that supports Z-ordering, and the performance will be vastly better than using UIViews.
I know this is old, but you can change the z order with bringSubViewToFront.
See this answer: How to set iPhone UI View z index?