I need to know the length of a the output in an UIWebView (in whatever units).
Is this possible? Internally IOS must know this to control the scrolling but I can't seem to find it.
If by length, you mean the height of the content, you can use one of the following in the webViewDidFinishLoad:delegate method:
CGFloat height01 = [[[webView subviews] lastObject] contentSize].height;
CGFloat height02 = [webView sizeThatFits:CGSizeZero].height;
CGFloat height03 = [[webView stringByEvaluatingJavaScriptFromString:#"document.height"] floatValue];
They should return the same value.
Related
I want to create a color picker. So I thought using NSReadPixel would be a good approach to receive the pixels’ color. So what I basically did was this:
class CustomWindowController: NSWindowController {
override func mouseMoved(with event: NSEvent) {
let mouseLocation = NSEvent.mouseLocation()
let pickedColor = NSReadPixel(mouseLocation)
}
}
But pickedColor always returns nil. Even if I try to "readPixel" with a fixed point (for testing purposes) it still returns nil. What am I missing?
EDIT #1
I’ve followed the NSBitmapImageRep / colorAt approach from the answers and noticed that the resulting NSColor seems to be a bit different (in most cases brighter) that it should be (take a look at the screenshot). Do I have to consider colorSpaces or so? (and how?)
EDIT #2
Got it work - bitmap.colorSpaceName = NSDeviceRGBColorSpace does the trick.
It really doesn't work. I use this code for getting pixel color
NSPoint _point = [NSEvent mouseLocation];
CGFloat x = floor(_point.x);
CGFloat y = [NSScreen mainScreen].frame.size.height - floor(_point.y);
//it needs because AppKit and CoreGraphics use different coordinat systems
CGWindowID windowID = (CGWindowID)[self windowNumber];
CGImageRef pixel = CGWindowListCreateImage(CGRectMake(x, y, 1, 1), kCGWindowListOptionOnScreenBelowWindow, windowID, kCGWindowImageNominalResolution);
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:pixel];
CGImageRelease(pixel);
NSColor *color = [bitmap colorAtX:0 y:0];
I am trying to update the height of the NSTextField w.r.t the length of the string but if the string is light the last portion gets cut off.This is my code.
self.solutionTextView.frame = CGRectMake(self.solutionTextView.frame.origin.x, self.solutionTextView.frame.origin.y, self.solutionTextView.frame.size.width + 25 ,self.solutionTextView.frame.size.height + 25);
//self.solutionTextView.sizeToFit()
What am i doing wrong?
If the NSTextField is allowed to wrap the string, the following steps are the standard (or usual? or one of more possible?) ways to determine the wanted height of the field. Assume the width of the field is given:
NSRect frame = [textField frame];
Now make it very high:
NSRect constraintBounds = frame;
constraintBounds.size.height = 10000.0;
[textField setFrame: constraintBounds];
and set the string:
[textField setStringValue:theString];
Ask now for the natural size:
NSSize naturalSize =
[[textField cell] cellSizeForBounds:constraintBounds];
And you are done:
frame.size = naturalSize;
[textField setFrame:frame];
I'm building an UITextView with text and images (Subclassing NSTextstorage for displaying my content)
I'm having textcontent with images URLs.
So my problem is that i need download all the images if they're not cached.
So i want to first insert a placeholder image, download the image and then replace the placeholder image by the downloaded one.
Here's how i do my stuff.
First, i'm formatting my text with images url by replacing all urls with this tag :
[IMG]url[/IMG]
Then i'm using a regex to get all these tags.
I'm testing if there's a cached image or not. If not, i extract all the urls, download them and cache them.
I've created an NSObject class ImageCachingManager and declared a delegate method called when an image has been downloaded :
#protocol ImageCachingManagerDelegate <NSObject>
- (void)managerDidCacheImage:(UIImage *)image forUrl:(NSString *)url;
#end
Like this, I tough that I could use the url of the image got by the delegate method to search the matching url in my NSTextstorage attributedString and replace the current NSTextattachement image by the downloaded one.
But I don't know how to do that...
Thanks for help !
I'm working on something very similar to this at the moment and think this might help. The code is very much alpha but hopefully it will get you to the next step - I'll step through:
Overall Cycle
1. Find you image tags in the full text piece using Reg Ex or XPath - personally i find Hppl to be more powerful but if your content is well structured and reliable, regex is probably fine.
https://github.com/topfunky/hpple
Reduce the space of this match to 1 character and store that range - A textAttachment occupies only 1 character of space within a textview so it's best to reduce this to 1 otherwise when you replace your first match of characters in a range with the first textattachment the next range marker becomes out of date which will lead to issues. Depending on how much processing you need to do this text input during init, this is an important step, i have to do a lot of processing on the text and the ranges change during this parsing so I created an array of special characters that I know is never going to be in the inputs and push these single characters into the reserved space, at the same time i store this special character and the src of the image in an array of a very simple NSObject subclass that stores the SpecialChar, ImgSrc plus has space for the NSRange but i basically find the special character later in the process again because it has been moved about since this point and then set the nsrange at the very end of processing - this may not be necessary in your case but the principle is the same; You need a custom object with NsRange (which will become a text attachment) and the imgSource.
Loop through this array to add placeholder imageAttachments to your attributed string. You can do this by adding a transparent image or a 'loading' image. You could also check your cache for existing images during this point and skipping the placeholder if it exists in cache.
Using your delegate, when the image is successfully downloaded, you need to replace the current attachment with your new one. By replacing the placeholder in the range you've already stored in your object. Create a placeholder attributedString with the NSTextAttachment and then replace that range as below.
Some sample code:
Steps 1 & 2:
specialCharsArray = [[NSArray alloc]initWithObjects:#"Û", #"±", #"¥", #"å", #"æ", #"Æ", #"Ç", #"Ø", #"õ", nil];
//using Hppl
NSString *allImagesXpathQueryString = #"//img/#src";
NSArray *imageArray = [bodyTextParser searchWithXPathQuery:allImagesXpathQueryString];
//
imageRanges = [[NSMutableArray alloc] init];
if([imageArray count]){
for (TFHppleElement *element in imageArray) {
int i = 0;
NSString *imgSource = [[[element children] objectAtIndex:0] content];
NSString *replacementString = [specialCharsArray objectAtIndex:i];
UIImage *srcUIImage = [UIImage imageNamed:imgSource];
[srcUIImage setAccessibilityIdentifier:imgSource]; //only needed if you need to reference the image filename later as it's lost in a UIImage if stored directly
//imagePlacement is NSObject subclass to store the range, replacement and image as above
imagePlacement *foundImage = [[imagePlacement alloc]init] ;
[foundImage initWithSrc:srcUIImage replacement:replacementString];
[imageRanges addObject:foundImage];
i++;
}
Step 3:
-(void)insertImages{
if ([imageRanges count]) {
[self setScrollEnabled:NO]; //seems buggy with scrolling on
int i = 0; //used to track the array placement for tag
for(imagePlacement *myImagePlacement in imageRanges){
// creates a text attachment with an image
NSMutableAttributedString *placeholderAttString = [[NSMutableAttributedString alloc]initWithAttributedString:self.attributedText];
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
//scales image down to ration of width of view - you probably don't need this
CGSize scaleToView = imagePlacement.imgSrc.size;
scaleToView.width = self.frame.size.width;
scaleToView.height = (self.frame.size.width/imagePlacement.imgSrc.size.width)*imagePlacement.imgSrc.size.height;
attachment.image = [self imageWithColor:[UIColor clearColor] andSize:scaleToView];
NSMutableAttributedString *imageAttrString = [[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy];
[self setAttributedText:placeholderAttString];
i++;
}
}
[self setScrollEnabled:YES];
}
- (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize) size {
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
I use the following method to display the labels for my plot:
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index{
...
CPTTextLayer *label=[[CPTTextLayer alloc] initWithText:stringValue style:textStyle];
}
which for every index should return the label
I know that it's possible to move label up or down using:
plot.labelOffset=10;
The question is: how can i move the label a bit to the right?
I tried to use
label.paddingLeft=50.0f;
but it doesn't work.
Adding padding as in your example does work, but maybe not in the way you expect. Scatter and bar plots will center the label above each data point (with a positive offset). The padding makes the whole label wider so when centered, the test appears off to the side. It's hard to control, especially if the label texts are different lengths.
There is an outstanding issue to address this (issue 266). No guarantees when it will be fixed, but it is something we're looking at.
I ran into the same problem and came up with a different solution.
What I decided to do was to create the label using the CPTAxisLabel method initWithContentLayer:
CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:labelStr style:axisTextStyle];
CGSize textSize = [textLayer sizeThatFits];
// Calculate the padding needed to center the label under the plot record.
textLayer.paddingLeft = barCenterLeftOffset - textSize.width/2.0;
CPTAxisLabel *label = [[CPTAxisLabel alloc] initWithContentLayer:textLayer];
Here barCenterLeftOffset is the offset of the center of the plot record.
I wrote an article about this:
http://finalize.com/2014/09/18/horizontal-label-positioning-in-core-plot-and-other-miscellaneous-topics/
A demo project I created that uses this solution can be found at:
https://github.com/scottcarter/algorithms
You can subclass CPTTextLayer and include an offset.
#interface WPTextLayer : CPTTextLayer
#property (nonatomic) CGPoint offset;
#end
#implementation WPTextLayer
-(void)setPosition:(CGPoint)position
{
CGPoint p = CGPointMake(position.x + self.offset.x, position.y + self.offset.y);
[super setPosition:p];
}
Then Use:
WPTextLayer *tLayer = [[WPTextLayer alloc] initWithText:#"blah" style:textStyle];
tLayer.offset = CGPointMake(3, -3);
return tLayer;
There may be consequences of this that I'm not aware of, but it seems to be working so far.
I'm using route-me in my project. Library is quite good. Adding markers, drawing polygone work fine. How about placing single image as overlay in given location (latitude, longitude)? This funcionality is missing I think. Has anyone done placing the image overlay without overloading the tiles source?
I've found the solution...
CLLocationCoordinate2D lcA = CLLocationCoordinate2DMake(oSector.f_overlay_lat_min,oSector.f_overlay_long_min);
CLLocationCoordinate2D lcB = CLLocationCoordinate2DMake(oSector.f_overlay_lat_max,oSector.f_overlay_long_max);
CGPoint cgA = [mvMap latLongToPixel:lcA];
CGPoint cgB = [mvMap latLongToPixel:lcB];
float fLatMin = MIN(cgA.x,cgB.x);
float fLongMin = MIN(cgA.y,cgB.y);
float fWidth = sqrt((cgA.x - cgB.x)*(cgA.x - cgB.x));
float fHeight = sqrt((cgA.y - cgB.y)*(cgA.y - cgB.y));
RMMapLayer *mlLayer = [[RMMapLayer alloc] init];
mlLayer.contents = (id) oSector.im_overlay.CGImage;
mlLayer.frame = CGRectMake(fLatMin,fLongMin,fWidth,fHeight);
[[mvMap.contents overlay] addSublayer:mlLayer];
the mvMap is IBOutlet RMMapView *mvMap somewhere in your h file
the oSector.im_overlay.CGImage can be
UIImage *i = [UIImage imageNamed:<something>];
lmLayer.contents = i.CGImage
Why not just use an RMMarker? You can apply any image you want to it and place it as needed. Even make it draggable if you want to:
UIImage *imgLocation = [UIImage imageWithContentsOfFile :
[[NSBundle mainBundle] pathForResource:#"location_ind"
ofType:#"png"]];
markerCurrentLocation = [[RMMarker alloc] initWithUIImage:imgLocation];
// make sure it is always above everything else.
markerCurrentLocation.zPosition = -1.0;
[mapView.markerManager addMarker:markerCurrentLocation
AtLatLong:startingPoint];
Ciao!
-- Randy