How do I get a UITextView to wrap its text around a UIImage like in this image?
The image size is not necessarily previously known.
IOS 7 and above:
UIBezierPath * imgRect = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 100, 100)];
self.textView.textContainer.exclusionPaths = #[imgRect];
Swift (credit to Bart van Kuik):
let exclusionPath = UIBezierPath(rect: CGRectMake(0, 0, 100, 100))
self.textView.textContainer.exclusionPaths = [exclusionPath]
Gil's answer in Swift:
let exclusionPath = UIBezierPath(rect: CGRectMake(0, 0, 100, 100))
self.textView.textContainer.exclusionPaths = [exclusionPath]
If somebody has a better solution, please bring it on, but i usually had to revert to html to do this kind of trick.
You could use two textViews and one imageView to achieve this programmatically, but i'll be a couple of LOC to write. You would have to figure out the size of the image, set the first table view to fit nicely next to, than figure out where the string is longer than visible, cut it off an go on on the next textView.
The same could be achieved by a simple local UIWebView
Related
I am notes.app like app. I am setting UITextView's contentInset as
myTextView.contentInset = UIEdgeInsetsMake(0, 25, 0, -25);
myTextView.contentSize = CGSizeMake(295, myTextView.contentSize.height);
but that does not seems to work as I expected. Two characters are hidden.
I get this
but if I set
myTextView.contentInset = UIEdgeInsetsMake(0, 25, 0, 0);
myTextView.contentSize = CGSizeMake(295, myTextView.contentSize.height);
I get actual text as
please help.
fibnochi you can use a different approach to do this. I have used this in one of my app and it is working fine
First of all you need to get the size of UItextView which will carry all the data, for this you need to use NSString class delegate function
NSString* str = #"Your Entire string will come here";
CGSize size = [str sizeWithFont:[UIFont systemFontOfSize:17.0] constrainedToSize:CGSize(295, any large digit for maximum height say 10000) lineBreakMode:UILineBreakModeWordWrap];
textView.contentSize = size;
Will this solve your problem or not. Please let me know
Can you please try the below?
myTextView.contentInset = UIEdgeInsetsMake(0, 25, 0, 25);
myTextView.contentSize = CGSizeMake(295, myTextView.contentSize.height);
Apple's discussions
here.
"
Edge inset values are applied to a rectangle to shrink or expand the area represented by that rectangle. Typically, edge insets are used during view layout to modify the view’s frame. Positive values cause the frame to be inset (or shrunk) by the specified amount. Negative values cause the frame to be outset (or expanded) by the specified amount.
"
You can do like UIEdgeInsetsMake(0,25,0,25)
try this code :)
myTextView.contentInset = UIEdgeInsetsMake(0, 25, 0, -25);
myTextView.contentSize = CGSizeMake(270, myTextView.contentSize.height);
May this will help you out :)
I would like to create a UIView which would show a colored circle with a number or character in it. I have seen examples to create a circle, but how would I accomplish this?
I would want to place multiple of these views on the screen and connect them with lines.
Any suggestions?
// Swift, iOS8
var letterLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 100, height: 100))
letterLabel.layer.cornerRadius = 50
letterLabel.textAlignment = NSTextAlignment.Center
letterLabel.layer.borderWidth = 10
letterLabel.layer.backgroundColor = UIColor.blueColor().CGColor
letterLabel.font = UIFont(name: "Hoefler Text", size:75.0)
letterLabel.text = "A"
If you already know how to draw a circle, then you've got half of it solved :) Let's say the circle is drawn in a UIView called circleView.
Now you want to create a UILabel to draw the letter in.
UILabel* circleLabel = [[UILabel alloc] init];
[circleLabel setText:#"letter goes here"];
And now you want to put the label on top of the circleView, so you add it as a subview:
[circleView addSubview:circleLabel];
At this point, depending on the size of circleView and the font size of circleLabel, the label may or may not be in the center of the circle. Use the setFrame function on the circleLabel to adjust its position within the circleView.
I have a UIButton in my iPhone app. I set its size to 100x100.
I have an image that is 400x200 that I wish to display in the button.
The button STILL needs to stay at 100x100... and I want the image to downsize to fit... but
keep the correct aspect ratio.
I thought that's what "Aspect Fit" was used for.
Do I include my image with setImage, or setBackgroundImage?
Do I set AspectFit for the button? or the image? or the background image?
(I need the smaller images to INCREASE in size. While larger images should DESCREASE in size.
Always keeping the button at 100x100.)
I've tried countless combinations of all of the above... and I just can't seem to get
everything to work at the same time:
Don't change the button's size of 100x100.
Don't destroy the image's aspect ratio.
Always increase small images to fit the button.
Always decrease large images to fit the button.
Never clip any of the image edges.
Never require the "put UIButtons over all your UIimages" hack.
Don't require everyone to upgrade to v4.2.1 just to use new framework methods.
I see so many apps, with so many fully-working image-buttons... that I can't believe I can't figure out this very simple, very common thing.
Ugh.
UIButton is broken. That's the short answer. The UIImageViews in its image and backgroundImage properties don't respect UIViewContentMode settings. They're read-only properties, and while the UIImage contents of those UIImageViews can be set through setImage: and setBackgroundImage: methods, the content mode can't be.
The solution is either to provide properly-sized images in your bundle to begin with, or to put a UIImageView down, configure it the way you want it, and then put a clear "custom" UIButton over top of it. That's the hack all those fancy professional apps you've seen have used, I promise. We're all having to do it.
UIImage *img = [UIImage imageNamed:#"yourImageName"];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;
[button setImage:img forState:UIControlStateNormal];
To do this correctly, I would actually programmatically resize and manipulate the image to get the desired aspect ratio. This avoids the need for any view hierarchy hacks, and also reduces any performance hit to a single operation, instead of every redraw.
This (untested) code should help illustrate what I mean:
CGSize imageSize = image.size;
CGFloat currentAspect = imageSize.width / imageSize.height;
// for purposes of illustration
CGFloat targetWidth = 100;
CGFloat targetHeight = 100;
CGFloat targetAspect = targetWidth / targetHeight;
CGFloat newWidth, newHeight;
if (currentAspect > targetAspect) {
// width will end up at 100, height needs to be smaller
newWidth = targetWidth;
newHeight = targetWidth / currentAspect;
} else {
// height will end up at 100, width needs to be smaller
newHeight = targetHeight;
newWidth = targetHeight * currentAspect;
}
size_t bytesPerPixel = 4;
// although the image will be resized to { newWidth, newHeight }, it needs
// to be padded with empty space to provide the aspect fit behavior
//
// use calloc() to clear the data as it's allocated
void *imageData = calloc(targetWidth * targetHeight, bytesPerPixel);
if (!imageData) {
// error out
return;
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
if (!colorSpace) {
// error out
return;
}
CGContextRef context = CGBitmapContextCreate(
imageData,
targetWidth,
targetHeight,
8, // bits per component
targetWidth * bytesPerPixel, // bytes per row
colorSpace,
kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst
);
CGColorSpaceRelease(colorSpace);
// now we have a context to draw the original image into
// in doing so, we want to center it, so prepare the geometry
CGRect drawRect = CGRectMake(
floor((targetWidth - newWidth) / 2),
floor((targetHeight - newHeight) / 2),
round(newWidth),
round(newHeight)
);
CGContextDrawImage(context, drawRect, image.CGImage);
// now that the bitmap context contains the aspect fit image with transparency
// letterboxing, we want to pull out a new image from it
CGImageRef newImage = CGBitmapContextCreateImage(context);
// destroy the temporary context
CGContextRelease(context);
free(imageData);
// and, finally, create a new UIImage
UIImage *newUIImage = [UIImage imageWithCGImage:newImage];
CGImageRelease(newImage);
Let me know if any part of that is unclear.
I think what Dan is trying to say (but without ever saying it) is to do this:
Use a "temp image" to do the resizing for you.
The temp-image needs to be set to ASPECT FIT and HIDDEN.
Make sure your button is set to your desired size, and NOT set to ASPECT FIT.
// Make a frame the same size as your button
CGRect aFrame = CGRectMake(0, 0, myButton.frame.size.width, myButton.frame.size.height);
// Set your temp-image to the size of your button
imgTemp.frame = aFrame;
// Put your image into the temp-image
imgTemp.image = anImage;
// Copy that resized temp-image to your button
[myButton setBackgroundImage:tempImage forState:UIControlStateNormal];
Since none of my attempts have worked....
Maybe I should be asking this instead. When using a UIButton:
When DO I use setImage instead of setBackgroundImage? (Why are there both?)
When DO I use "Aspect Fit" instead of "Center"? (Why do both seem to stretch my images when I expect them to "keep aspect ratio" and "don't resize anything", respective.)
And the big question: Why is such a common thing... such a huge mess?
It would all be solved if I could find a work-around method like: Just use UIImage instead and detect TAPS. (But that seems to be even a LARGER nightmare of code.)
Apple, if you've tried to make my job easier... you have instead made it 400 times more confusing.
Place a imageview over the button, set your image for the imageview and not for button.
All the best.
I would resize the image to 100x100 maintaining the aspect ratio of the content contained in the image. Then set the backgroundImage property of the UIButton to the image.
I faced same issue few days back and resolved it. Please try with this
[_profilePicBtn setImage:profilePic forState:UIControlStateNormal];
_profilePicBtn.imageView.contentMode = UIViewContentModeScaleAspectFit;
I have a UIImageView that displays a bigger image. It appears to be centered, but I would like to move that image inside that UIImageView. I looked at the MoveMe sample from Apple, but I couldn't figure out how they do it. It seems that they don't even have an UIImageView for that. Any ideas?
What you need is something like (e.g. showing the 30% by 30% of the top left corner of the original image):
imageView.layer.contentsRect = CGRectMake(0.0, 0.0, 0.3, 0.3);
Description of "contentsRect":
The rectangle, in the unit coordinate space, that defines the portion of the layer’s contents that should be used.
Original Answer has been superseded by CoreAnimation in iOS4.
So as Gold Thumb says: you can do this by accessing the UIView's CALayer. Specifically its contentRect:
From the Apple Docs: The rectangle, in the unit coordinate space, that defines the portion of the layer’s contents that should be used. Animatable.
Do you want to display the image so that it is contained within the UIImageView? In that case just change the contectMode of UIImageView to UIViewContentModeScaleToFill (if aspect ratio is inconsequential) or UIViewContentModeScaleAspectFit (if you want to maintain the aspect ratio)
In IB, this can be done by setting the Mode in Inspector.
In code, it can be done as
yourImageView.contentMode = UIViewContentModeScaleToFill;
In case you want to display the large image as is inside a UIImageView, the best and easiest way to do this would be to have the image view inside a UIScrollView. That ways you will be able to zoom in and out in the image and also move it around.
Hope that helps.
It doesn't sound like the MoveMe sample does anything like what you want. The PlacardView in it is the same size as the image used. The only size change done to it is a view transform, which doesn't effect the viewport of the image. As I understand it, you have a large picture, and want to show a small viewport into it. There isn't a simple class method to do this, but there is a function that you can use to get the desired results: CGImageCreateWithImageInRect(CGImageRef, CGRect) will help you out.
Here's a short example using it:
CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
[UIImageView setImage:[UIImage imageWithCGImage:imageRef]];
CGImageRelease(imageRef);
Thanks a lot. I have found a pretty simple solution that looks like this:
CGRect frameRect = myImage.frame;
CGPoint rectPoint = frameRect.origin;
CGFloat newXPos = rectPoint.x - 0.5f;
myImage.frame = CGRectMake(newXPos, 0.0f, myImage.frame.size.width, myImage.frame.size.height);
I just move the frame around. It happens that portions of that frame go out of the iPhone's view port, but I hope that this won't matter much. There is a mask over it, so it doesn't look weird. The user doesn't totice how it's done.
You can accomplish the same by:
UIImageView *imgVw=[[UIImageView alloc]initwithFrame:CGRectMake(x,y,height,width)];
imgVw.image=[UIImage imageNamed:#""];
[self.view addSubView imgVw];
imgVw.contentMode = UIViewContentModeScaleToFill;
You can use NSLayoutConstraint to set the position of UIImageView , it can be relative to other elements or with respect to the frame.
Here's an example snippet:
let logo = UIImage(imageLiteralResourceName: "img")
let logoImage = UIImageView(image: logo)
logoImage.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(logoImage)
NSLayoutConstraint.activate([logoImage.topAnchor.constraint(equalTo: view.topAnchor,constant: 30),
logoImage.centerXAnchor.constraint(equalTo: view.centerXAnchor),logoImage.widthAnchor.constraint(equalToConstant: 100),logoImage.heightAnchor.constraint(equalToConstant: 100)
])
This way you can also resize the image easily. The constant parameter represents, how far should a certain anchor be positioned relative to the specified anchor.
Consider this,
logoImage.topAnchor.constraint(equalTo: view.topAnchor,constant: 30)
The above line is setting the top anchor of the instance logoImage to be 30 (constant) below the parent view. A negative value would mean opposite direction.
I' have a lot of png's with different sizes, and i want to load them into a table. I have this code:
charImage.image = [self imageForId:g.charId glyphNr:g.glyphNr];
[charImage sizeToFit];
//charImage.contentMode = UIViewContentModeCenter;
charImage.center = CGPointMake(30, 23);
Everything works fine except that my pngs are blurry. If i don't center them, are extremely sharp. They are all made from curves. I didn't exported them all, so is still a chance to export with a fixed size and the drawings already centered, but i want to know if i'm doing something wrong or incomplete. Why are they blurry?
I think is not possible to upload any photo here..
This will make sure the frame is at integer coordinates:
int centerX = 30;
int centerY = 23;
CGSize size = charImage.frame.size;
charImage.frame = CGRectMake((int)(centerX - size.width / 2),
(int)(centerY - size.height / 2),
size.width, size.height);
The difference between this and
charImage.center = CGPointMake(30, 23);
is that the .center setter could set the origin to a non-integer point when either of the width or height is of the wrong parity. As other people have said here, images and text look blurry when they're at non-integer coordinates.
This happens because the pngs get placed at sub-pixel positions. Using sizeToFit together with UIViewContentModeCenter makes this happen. When you don't use UIViewContentModeCenter, the views are placed at (0.0, 0.0), and hence do not blur.
If you want to avoid blur, first don't use sizeToFit, then use this to center the image:
image.frame = CGRectMake(round(centerX - image.frame.size.width / 2.0),
round(centerY - image.frame.size.height / 2.0),
image.frame.size.width,
image.frame.size.height);
you might use calculated coordinates instead of contentMode:
charImage.frame = CGRectMake(x,y,width,height)