Resizable UIImage where outside stretches and inside is kept the same - ios

I'm trying to create a "grip" for a vertical bar in my app, to show the user that they can swipe on the view. I'd like to just use a small version of the image, which has the grip and 1 px above and below it which is the background for the rest of the bar. So:
ssss ssss
gggg becomes ssss
ssss gggg
ssss
ssss
The method resizableImageWithCapInsets: allows you to tell iOS not adjust the outside edge, but is there a way to tell it to not adjust the interior and stretch with the exterior?
I've tried specifying a oversized cap inset, UIEdgeInsetsMake(29.0f, 0.0f, 29.0f, 0.0f) and that resulted in the grip being at the top of the image's frame, but otherwise is the correct stretching behavior I'm looking for. I just need to have the grip part centered in the frame.
Full code for those interested (this results in the grip being repeated across the whole length):
gripBar = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"grip"] resizableImageWithCapInsets:UIEdgeInsetsMake(1.0f, 0.0f, 1.0f, 0.0f)]];
gripBar.frame = CGRectMake(0, 0, gripWidth, fullHeight);
[view gripBar];
Update: working code based on chosen answer
#implementation GripBar
- (id)init {
self = [super init];
if (self) {
UIImageView *bar = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"gripback"] resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 0.0f, 1.0f, 0.0f)]];
bar.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self addSubview:bar];
UIImageView *grip = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"grip"]];
grip.contentMode = UIViewContentModeCenter;
grip.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self addSubview:grip];
}
return self;
}
#end

The easiest way to do this is probably to make your grip part be a (small-height, but full-width) subview of a larger bar view whose background stretches or tiles. You can keep the grip part centered in your larger view by, for example, autoresize masks.

Related

Dynamically Add and Center UIImages in UIView

I am trying to think through this fun "problem".
I have a UIView (288x36) that will hold up to 8 UIImages (36x36).
Any number (up to 8) can be placed in the UIView.
I want the "collection" of these images to be centered in the UIView.
If there is only 1 image, then it's center will be in the center of the UIView. If 2, then the max width of the image will be in the center of the UIView and the 2nd images starting point will also be in the center, etc etc.
Has anyone dealt with this before? Any code examples.
I am not very advanced but trying to learn.
Suppose your UIView is called view and your array of images is imageArray:
float remainingSpace = view.bounds.size.width - imageArray.count*36; //This is the space to remaining
float spaceOnLeft = remainingSpace/2.0; //Just the space to the left of the images
for (UIImage *image in images) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(spaceOnLeft, 0, 36, 36)];
imageView.image = image;
[view addSubview:imageView];
spaceOnLeft += 36.0; // so the next image is spaced 36 points to the right
}

Constrain UIScrollView panning?

UIScrollView has a built-in behavior "directionLockEnabled".
When enabled, panning will attempt to lock to either the horizontal or vertical directions. But when the user aggressively attempts to scroll diagonally - it still allows diagonal scrolling.
I'd like to remove the ability to diagonally scroll.
Many thanks in advance.
EDIT:
I've tried putting a UIScrollView inside another (each with dimensions so as to constrain the movement) but the pan recognizers seemed to conflict - only one worked.
I've looked at TTScrollView to see if it could be modified for the job - but it does not seem to be working properly out of the box (freezing after first gesture.)
I've tried adding a second action (listener) to UIScrollView.panGestureRecognizer to call setTranslation:inView with a constrained value. This resulted in erratic jumping.
And several other avenues probably not worth mentioning.
EDIT2:
Odrakir's solution works. Code looks like:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIImage* image = [UIImage imageNamed:#"Sofia"];
UIImageView* imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(0, 0, 1024 * 2, 768 * 2);
UIScrollView* scrollView1 = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 1024*2, 768)];
scrollView1.contentSize = CGSizeMake(1024*2, 768*2);
[scrollView1 addSubview:imageView];
UIScrollView* scrollView2 = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
scrollView2.contentSize = CGSizeMake(1024*2, 768);
[scrollView2 addSubview:scrollView1];
[self.view addSubview:scrollView2];
}
I never tried that, but I have an app that has a horizontal ScrollView, and inside it there are multiple views, each of them with their own vertical ScrollView.
It's kind of like a magazine, with different articles and each article has a number of pages.
Both ScrollViews work and the user can't scroll diagonally. You can try that.
The display hierarchy is Horizontal ScrollView-> View ->Vertical ScrollView

uitableview.backgroundView image dimension is compressing/distorting

I'm building an iphone app.
I have a tableview and i set a background image like so:
UIImageView * bg = [[UIImageView alloc] initWithImage:somebackgroundimage];
CGRect framebg = bg.frame;
framebg.origin.y = -64;
framebg.origin.x = 0;
framebg.size.width = 320;
framebg.size.height = 480;
[bg setFrame:framebg];
[_tblview setBackgroundView:bg];
no matter what framebg.size.width or framebg.size.height I set, the image always appears distorted or compressed with a size of maybe 320 width and 400 height. It is almost as if the app will forcefully resize the image to fit between the top navigation bar and my bottom tab bar.
How do I force tableview background image to be of 320px width by 480px height?
Also it seems the origin.y and origin.x aren't being respected either.
I know this question is a bit old, but I thought i would share what I was able to use to get around a similar issue (using setContentMode for the image view):
UIImageView *bg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
[bg setContentMode:UIViewContentModeScaleAspectFit];
self.tableView.backgroundView = bg;
Hope this helps.

Shadow in separate view from UIImage for dynamic adjustments

I would like to obtain this effect (http://stackoverflow.com/questions/7023271/how-to-adjust-drop-shadow-dynamically-during-an-uiimageview-rotation) but from a more complex image than just a red square ! If the link ever gets broken, it's a about how to adjust drop shadow dynamically during an UIImageView rotation.
So I tried implementing something but I just can't get the shadow in a separate layer... Here is my code, very simple, but doesn't work:
// here is my code
- (void)viewDidLoad {
[super viewDidLoad];
testView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"handNoShadow.png"]];
testViewShadow = [[UIView alloc] initWithFrame:testView.frame];
testViewShadow.layer.shadowPath = [[testView layer] shadowPath];
testViewShadow.layer.shadowOpacity = 1.0;
testViewShadow.layer.shadowOffset = CGSizeMake(10, 10);
testViewShadow.layer.shadowRadius = 5.0;
[self.view addSubview:testViewShadow];
[self.view addSubview:testView];
}
PS: i did #import
I do get an image but no shadow... =(
Any lead, help, code, link... is welcome !
Thanks
possible cause:
your testViewShadow.clipToBounds property is set to YES (should be NO)
your testViewShadow do the drawing of the shadow correctly but another UIView is on top and mask it. Check your Z order. Either the order in Storyboard/Nib file (or the order you added the subviews programmatically). Last in the list (or last one added) is on top. For my app I had to put the UIView that need a shadow last so that no other view mask it.

Center [UIColor colorWithPatternImage]?

I couldn't find anything on how you can center the 'image' when you use (maybe you can't):
[self setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"background"]]];
Setting my [self setContentMode:UIContentModeCenter]; doesnt help.
Do I have to manually draw the image (either in drawRect or set the content of the CALayer? Which one if preferable?
I think you're on the wrong path here: you create a UIColor from a pattern (pattern already implies this is a repeating image). All in all- you can't have your pattern not repeat and centered.
If you just want simple image as background of your UIView, just add it as a subview and center it.
UIImage* img = [UIImage imageNamed:#"yourfile.png"];
UIImageView* imgView = [[UIImageView alloc]initWithImage: img];
[yourUIView addSubview: imgView];
imgView.center = CGPointMake(yourUIView.frame.size.width/2, yourUIView.frame.size.height/2);
Now - add more subviews to your "yourUIView" view and they'll show on top of the image - thus the image becoming the background.
So... no need to draw anything yourself.

Resources