I am deveoping an ebook app for ipad/iphone which loads epub file. I would like to know how to highlight a text with a background color and make notes similar to iBook or Kindle in UIWebView and NOT UIView. I am able to drag select the text by long tapping. But I can only see "copy" option. I would like to add highlight and add note to that menu. How to hightlight the text with a background color?... My document is loaded in UIWebView.
Thank you.
What you need to do is add the note and highlight options to your shared menu. In your viewcontroller viewdidload (or anytime after your view has been added). The following adds two menu items with two selector methods to your menu.
UIMenuItem *customMenuItem1 = [[UIMenuItem alloc] initWithTitle:#"Highlight" action:#selector(doHighlight:)];
UIMenuItem *customMenuItem2 = [[UIMenuItem alloc] initWithTitle:#"Note" action:#selector(doNote:)];
//[myArray addObject:customMenuItem2];
NSMutableArray *myArray = [[NSMutableArray alloc]initWithObjects:customMenuItem1,customMenuItem2, nil ] ;
[UIMenuController sharedMenuController].menuItems = myArray;
You may also want to use a bit of javascript to determine the rect that holds your selection, then overlay a translucent uiview over the text.
So, within your doNote method, load up javascript and run it, see the below javascript for an example of what you may want to do.
NSString *rectString = [webView stringByEvaluatingJavaScriptFromString:rectStringText];
The following will get a rect around the text, though it will inherently be larger than your text: if you've highlighted at char 10 on line 2 through char 50 on line 5, it will return a rect that highlights char 0 line 2 through endline line 5.
function selectEl(x,y){
document.designMode = "on";
var el = document.elementFromPoint(x, y);
var rect = el.getBoundingClientRect();
var vx = rect.left;
var width = rect.right - vx;
var height = rect.bottom - rect.top;
var vy = rect.top;
var range = document.createRange();
range.selectNodeContents(el);
var sel = document.getSelection();
sel.removeAllRanges();
sel.addRange(range);
document.designMode = "off";
rectString = '{{'+vx+','+vy+'},{'+width+','+height+'}}';
}
So, now that you have a rectangle string, you can create a CRect from the string returned and uiview to overlay within your webview. [Note, you will have to figure out how to deal with zooming and saving this data for your next load]
Related
This one has been killing me for some time. I have a subclassed NSTextField with:
- (void)drawRect:(NSRect)dirtyRect {
if ([(SFIDisk *)self.cell.representedObject label]) {
// Calculate text width to draw label color around the text.
CGFloat textWidth = self.attributedStringValue.size.width + kSFIDiskViewTitleTextFieldCellMarginForTextSize;
CGFloat textStartX = dirtyRect.origin.x + ((dirtyRect.size.width - textWidth) * .5);
// Draw label background.
[SFIStyleKit drawDiskLabelWithFrame:NSMakeRect(textStartX, dirtyRect.origin.y, textWidth, dirtyRect.size.height)];
}
// Calculate text width to draw label color around the text.
CGFloat textStartY = dirtyRect.origin.y + ((dirtyRect.size.height - self.attributedStringValue.size.height) * .5);
CGFloat textWidth = self.attributedStringValue.size.width;
CGFloat textStartX = dirtyRect.origin.x + ((dirtyRect.size.width - textWidth) * .5);
// Due to the icon in attribtued string, center drawing for string needs to be manually done.
if (!self.currentEditor) {
// Since drawing happens in CALayer and it cannot support font smoothing, this feature needs to be turned off in order to work.
// https://stackoverflow.com/questions/715750/ugly-looking-text-when-drawing-nsattributedstring-in-cgcontext
CGContextSetShouldSmoothFonts((CGContextRef)[[NSGraphicsContext currentContext] graphicsPort], NO);
[self.attributedStringValue drawAtPoint:NSMakePoint(textStartX, textStartY)];
}
}
This seems to works perfect in the UI:
But when editing the NSTextView draws the string a bit heavier:
After editing all goes back to a thinner string:
Goal is to have both looking the same, so am assuming something is wrong in my draw string call since the editor is not manipulated by me.
I cannot figure this out for the life of me. Any ideas?
EDIT:
Did some extra tests by manually setting font for both NSTextField and its corresponding currentEditor when editing.
For every weight set for the font, currentEditor always displays the next weight level.
By finding this out i did a workaround but a proper answer to this is still needed.
Work around code
if ([(SFIDisk *)self.cell.representedObject label]) {
....
self.currentEditor.font = [NSFont systemFontOfSize:13 weight:NSFontWeightLight];
}
While you're editing, you'll be looking at the field editor, which is a NSTextView, rather than your NSTextField. Therefore, your override of -drawRect won't come into play until editing ends and the field editor is hidden again.
I am able to successfully change the color of PageControl/page indicator on UIPageViewController for the first page only. My use case requires each page to be a different color, requiring the PageControl/page indicator to match color with a page. I tried changing color based on the page index but it doesn't work.
Anyone know how to fix this?
- (PageContentViewController *)viewControllerAtIndex:(NSUInteger)index
{
if ([tutorialItems count] == 0) {
return nil;
}
// Create a new view controller and pass suitable data.
PageContentViewController *pageContentViewController
= [self.storyboard instantiateViewControllerWithIdentifier:#"PageContentViewController"];
TutorialItem *tutorialItem = [tutorialItems objectAtIndex:index];
pageContentViewController.imageFile = tutorialItem.tutorialImageFileName;
pageContentViewController.titleText = tutorialItem.tutorialTitle;
pageContentViewController.tutorialText = tutorialItem.tutorialText;
int red = tutorialItem.tutorialRedKey;
int green = tutorialItem.tutorialGreenKey;
int blue = tutorialItem.tutorialBlueKey;
pageContentViewController.pageIndex = index;
tutorialBackgroundColor = [UIColor colorWithRed:red/255.0f green:green/255.0f blue:blue/255.0f alpha:1.0f];
pageContentViewController.tutorialBackgroundColor = tutorialBackgroundColor;
UIPageControl *pageControl = [UIPageControl appearance];
pageControl.pageIndicatorTintColor = [UIColor blackColor];
pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
pageControl.backgroundColor = [UIColor clearColor];
pageContentViewController.pageControllerColor = tutorialBackgroundColor;
return pageContentViewController;
}
appearance proxy attributes only get set when a component is first added to the window. Changing an appearance attribute will not change it for already visible components. If you want to change the color of a component that is already on the screen, you will need to reference it and change the color on it directly, or remove it from the view hierarchy and re-add it.
You can read the documentation here
Relevant quote:
iOS applies appearance changes when a view enters a window, it doesn’t
change the appearance of a view that’s already in a window. To change
the appearance of a view that’s currently in a window, remove the view
from the view hierarchy and then put it back.
I am working on a game and i need to implement the top bar, holding the details like score and other stuff.
My top bar should have the following (left to right):
- a 50x50 icon that changes according to level, but it's the same size
- a label with some text that changes according to level
- ... other elements
The problem is that when the label text changes, the label sometimes is too far from the icon and other times is over the icon (depending on the text length)
I thought I understood positioning, but apparently i didn't..
//create array for level text label
levelTextArray = [[NSArray alloc] initWithObjects:#"\"Uuu! Bubbles!\"",#"\"Noob\"",#"\"I’m getting it..\"",#"\"This is easy\"",#"\"Wha?\"",#"\"It’s ooon now!\"",#"\"Come on..\"",#"\"Dude…\"",#"\"You’re pushing it..\"",#"\"I’ll show you!!\"",#"\"AAAAAAA!!!\"",#"\"Holy Bubbles… \"",#"\"Ninja mode on!\"",#"\"I’m on fire!!\"",#"\"The wheel's spinning, but the hamsters dead. \"", nil];
//add level text label
levelTextLabel = [[SKLabelNode alloc] init];
levelTextLabel.text = levelTextArray[0];
levelTextLabel.position = CGPointMake(60, CGRectGetMidY(scoreImage.frame)+5);
levelTextLabel.fontColor = [UIColor colorWithRed:0/255.0f green:1/255.0f blue:0/255.0f alpha:1.0f];
levelTextLabel.fontName = #"Noteworthy-Light";
levelTextLabel.fontSize = 14.0;
[self addChild:levelTextLabel];
scoreImage is the icon in this case. Also..for the image to appear completely in the view I position it like this:
scoreImage = [[ SKSpriteNode alloc] initWithImageNamed:levelText];
scoreImage.name = #"LevelImage";
scoreImage.size = CGSizeMake(50, 50);
scoreImage.position = CGPointMake(0+scoreImage.size.width/2, CGRectGetMaxY(self.frame)-scoreImage.size.height/2);
I have the feeling that I'm doing something wrong here.
Any help is appreciated.
P.S. The label text as well as the icon image is changed according to level in -(void)update:(CFTimeInterval)currentTime {
Try setting the horizontalAlignmentMode of the SKLabelNode:
levelTextLabel.horizontalAlignmentMode = SKLabelHorizontalAlignmentModeLeft;
The default is SKLabelHorizontalAlignmentModeCenter.
I want to show a string with more words in a label.
Here is my code in the viewDidLoad:
startLabel.lineBreakMode = NSLineBreakByWordWrapping;
startLabel.numberOfLines = 0;
startLabel.text = string;
I also connected the label to the interface builder and synthesized it in my viewController.
But when the string is too long just the words who totally fit in the label get displayed and the rest gets cut off.
What am I doing wrong here?
Can anyone quickly help me? I've been playing with this for hours and don't understand why this isn't working?
I'm trying to update highlighted text in a selected label (which is referenced in an array of UILabels previously defined).
This method is called by a receiving IBAction from a UISlider in the view interface.
However, when I retrieve the selected UILabel object from the array and set its HIGHLIGHTED property, there's no corresponding reaction on the view interface. I'm under the impression that its supposed to automatically redraw the view with text highlighted using the code below.
PS: My connections seem to all be correct the Interface Builder (i.e., IBOutlet UILabels are properly mapped/connected and the UISlider which triggers this method is connected through IBAction).
Am I missing something?
- (IBAction) changeHighlightedLabel: (id)sender
{
// Setup
UILabel *selectedLabel = [[UILabel alloc] init];
selectedLabel.highlightedTextColor = [UIColor greenColor];
// Interpret slider value and round to integer
UISlider *temp = sender;
float unroundedTempValue = [temp value];
float roundedTempValue = roundf(unroundedTempValue);
// Select the UILabel object from the UI Label array based on slider valuer
selectedLabel = [uiLabelArray objectAtIndex:roundedTempValue];
// Highlight the selected label
selectedLabel.highlighted = YES;
}
I've also tried substituting...
selectedCountryLabel = [[uiCountryLabelArray objectAtIndex:roundedTempValue] isHighlighted];
... for the last line. Still doesn't work.
Any feedback or help please? Thanks.
You are creating a UILabel and setting highlightedTextColor property to that first and then you are overwriting that with a UILabel from array. Since you are not setting any highlightedTextColor this time, the highlighted property will not work on label.
Change it as follows.
- (IBAction) changeHighlightedLabel: (id)sender
{
// Interpret slider value and round to integer
UISlider *temp = sender;
float unroundedTempValue = [temp value];
float roundedTempValue = roundf(unroundedTempValue);
// Select the UILabel object from the UI Label array based on slider valuer
selectedLabel = [uiLabelArray objectAtIndex:roundedTempValue];
// Highlight the selected label
selectedLabel.highlightedTextColor = [UIColor greenColor];
selectedLabel.highlighted = YES;
}