replace layout manager of uitextview - ios7

NSTextContainer on Mac OS X has a method replaceLayoutManager: to replace the NSLayoutManager of NSTextView with a subclass of NSLayoutManager.
Unfortunately iOS doesn't have such a function.
I tried a combination of these lines of code, but it keeps crashing.
THLayoutManager *layoutManager = [[THLayoutManager alloc] init];
[layoutManager addTextContainer:[self textContainer]];
// [[self textStorage] removeLayoutManager:[self layoutManager]];
//[[self textStorage] addLayoutManager:layoutManager];
[[self textContainer] setLayoutManager:layoutManager];
What is the correct procedure to replace the NSLayoutManager of an UITextview?

Since iOS9, NSTextContainer has the same method as macOS. So now you can replace the layout manager on your storyboard UITextView with your own subclass:
textView.textContainer.replaceLayoutManager(MyLayoutManager())

Have a look at the WWDC2013 Intro To Text Kit video and sample code where they show how to do it.
https://developer.apple.com/downloads/index.action?name=WWDC%202013
https://developer.apple.com/wwdc/videos/
Below is an extract from the code
-(void)viewDidLoad
{
[super viewDidLoad];
// our auto layout views use a design spec that calls for
// 8 pts on each side except the bottom
// since we scroll at the top here, only inset the sides
CGRect newTextViewRect = CGRectInset(self.view.bounds, 8., 0.);
self.textStorage = [[TKDInteractiveTextColoringTextStorage alloc] init];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(newTextViewRect.size.width, CGFLOAT_MAX)];
container.widthTracksTextView = YES;
[layoutManager addTextContainer:container];
[_textStorage addLayoutManager:layoutManager];
UITextView *newTextView = [[UITextView alloc] initWithFrame:newTextViewRect textContainer:container];
newTextView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
newTextView.scrollEnabled = YES;
newTextView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
[self.view addSubview:newTextView];
self.textView = newTextView;
self.textStorage.tokens = #{ #"Alice" : #{ NSForegroundColorAttributeName : [UIColor redColor] },
#"Rabbit" : #{ NSForegroundColorAttributeName : [UIColor orangeColor] },
TKDDefaultTokenName : #{ NSForegroundColorAttributeName : [UIColor blackColor] } };
}

Related

objective-c adding UILabel to center

hi i'm begginer in objective-c and i want to learn how i can make UILabel in center of screen
this is my code:
XXRootViewController.h
#interface XXRootViewController : UIViewController{
UILabel *title; } #end
XXRootViewController.m
#import "XXRootViewController.h"
#implementation XXRootViewController {
NSMutableArray *_objects;
}
- (void)loadView {
[super loadView];
self.view = [[[UIView alloc]
initWithFrame:[[UIScreen mainScreen] applicationFrame]]
autorelease];
self.view.backgroundColor = [UIColor whiteColor];
title = [[UILabel alloc] initWithFrame:CGRectMake(300,200,400,200)];
title.text = #"This is Sasuke's first app :)";
[self.view addSubview:title];
}
#end
Try this code i make some changes in you code
self.view = [[UIView alloc]
initWithFrame:[UIScreen mainScreen].bounds];
self.view.backgroundColor = [UIColor whiteColor];
title = [[UILabel alloc] initWithFrame:CGRectMake(0,0,[UIScreen mainScreen].bounds.size.width - 50,200)];
title.text = #"This is Sasuke's first app :)";
title.textAlignment = NSTextAlignmentCenter;
title.center = self.view.center;
[self.view addSubview:title];
You just need to set frame in center of the screen ...
change your one line code with it -
title = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2 - 200,self.view.frame.size.height/2 - 100,400,200)];
now your label is shown in the center of screen .. This will help you change the frame according to your use...
Has Hardik Thakkar said, the best way would be to use the center method. That way, even if your label would grow, it will always be centred.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(300,200,400,200)];
label.text = #"something";
label.center = self.view.center; (this should always be you superview)
Now, even if your label is bigger than the size you were expecting, it will always be centred

Trying to set `setNextKeyView` on `NSTextField`s in code

I am having difficulties with setting a tab-order for my NSTextFields.
In my AppDelegate I add a NSViewController
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
CustomViewController *vc = [[CustomViewController alloc] init];
[_window.contentView addSubview:vc.view];
[_window setAutorecalculatesKeyViewLoop:NO];
[_window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[view]|" options:0 metrics:nil views:#{#"view":vc.view}]];
[_window.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[view]|" options:0 metrics:nil views:#{#"view":vc.view}]];
}
Then in my NSViewController I add custom NSViews which contain a label and a text field.
- (void)viewDidLoad {
_customView = [[CustomView alloc] initWithLabel:#"Foo"];
[self.view addSubview_customView];
_customView1 = [[CustomView alloc] initWithLabel:#"Bar"];
[self.view addSubview_customView1];
_customView2 = [[CustomView alloc] initWithLabel:#"FooBar"];
[self.view addSubview_customView2];
}
And finally I have the CustomView which implements the label and text field as follows:
- (void)initWithLabel:(NSString *)label {
self = [super initWithFrame:NSZeroRect];
if (self) {
_label = [[NSTextField alloc] initWithFrame:NSZeroRect];
_label.stringValue = label;
_label.font = [NSFont fontWithName:#"HelveticaNeue-Light" size:12.0f];
_label.alignment = NSLeftTextAlignment;
_label.textColor = [NSColor grayColor];
_label.selectable = NO;
_label.editable = NO;
_label.drawsBackground = NO;
_label.bezeled = NO;
[self addSubview:_label];
_textField = [[NSTextField alloc] initWithFrame:NSZeroRect];
_textField.stringValue = #"";
_textField.alignment = NSRightTextAlignment;
_textField.font = [NSFont fontWithName:#"HelveticaNeue-Light" size:32.0f];
[self addSubview:_textField];
}
return self;
}
I do the positioning with NSLayoutConstraints and everything looks fine and works as expected, except when I try to implement setNextKeyView:.
I have tried to do it by using the exposed textField in the viewDidLoad of the view controller like:
...
[_customView.textField setNextKeyView:_customView1.textField];
[_customView1.textField setNextKeyView:_customView3.textField];
[_customView2.textField setNextKeyView:_customView.textField];
...
But that did not work. When pressing tab-key from a NSTextField the current field loses focus, but the next one does not gain it.
I also tried calling [[[self view] window] recalculateKeyViewLoop] afterwards but that didn't help either.
How do I go about doing this?
I also played around with setting NSWindow setAutorecalculatesKeyViewLoop: to YES but that also did not haven an effect.
Thanks
PS: this is pseudo-code to simplify things. If a brace is missing or there is a typo, then that is not my problem. It compiles fine and works too. Just the tabbing is not behaving as expected. ;-)
As #Ken mentioned in his comment try like this:-
if ([_customView1.textField acceptsFirstResponder])
{
[_customView1.window makeFirstResponder:_customView1.textField]
}

Cannot change the Y cordinate of the UILabel programmatically

hi Im programmatically creating an UILabel like this
`
- (UILabel *)titleLabel {
if (!_titleLabel) {
_titleLabel = [[[UILabel alloc] init] initWithFrame:CGRectMake(0.0, _photoView.frame.size.height, _photoView.frame.size.width, 100.0)];
// _titleLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
_titleLabel.backgroundColor =[UIColor clearColor];
_titleLabel.textColor = [UIColor whiteColor];
_titleLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:14];
_titleLabel.textAlignment = NSTextAlignmentRight;
[self addSubview:_titleLabel];
}
return _titleLabel;
}`
this _photoView is an UIImageView I have created already. I want to change the UILabel View Y value. But the problem is when I change this second parameter label y position is not changing. Any one can tell e the reason for this.
And this is how I created the ImageView
`
- (UIImageView *)photoView {
if (!_photoView) {
_photoView = [[UIImageView alloc] init];
_photoView.contentMode = UIViewContentModeScaleAspectFill;
_photoView.clipsToBounds = YES;
_photoView.layer.cornerRadius = 5;
_photoView.clipsToBounds = YES;
[self addSubview:_photoView];
}
return _photoView;
}`
Thanks
In this line , you have used two types init
[[[UILabel alloc] init] initWithFrame:CGRectMake(0.0, _photoView.frame.size.height, _photoView.frame.size.width, 100.0)]
change this line to
[[UILabel alloc] initWithFrame:CGRectMake(0.0, _photoView.frame.size.height, _photoView.frame.size.width, 100.0)]

UITabbarItem BadgeValue Text Color

I have a problem in my App. I set a badge value at one of the tabs in the UITabBar. The Badge value is correctly red and the circle around the badge value is correctly in white. The problem is, that the color of the text is gray (160, 160, 160). It is the same color like the normal state tabbaritem text is, but I set this color nowhere in the app code and I do not know where this color come from.
I searched for that issue in the whole net since weeks but I cannot find any solution. The only answer I found everywhere is, that it is not possible to change the color of the text of the badge value. But if it is not possible, why is it changed in my app?
I hope, that somebody can help me with that issue...
http://www.luventas-webdesign.de/stackoverflow/screenshot_badgevalue.png
Like the color is in my app
http://www.luventas-webdesign.de/stackoverflow/screenshot_like_it_should.png
Like the color should normally be...
Edit 02.11.2012 - Code
Creation of TabBarController:
#import "ExtendedTabBarController.h"
#import "configuration.h"
#implementation ExtendedTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: [UIColor colorWithRed:207.0/255.0 green:70.0/255.0 blue:61.0/255.0 alpha:1], UITextAttributeTextColor, [UIFont fontWithName:#"KievitPro-Regular" size:10.0], UITextAttributeFont, nil] forState:UIControlStateSelected];
[[UITabBarItem appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys: [UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1], UITextAttributeTextColor, [UIFont fontWithName:#"KievitPro-Regular" size:10.0], UITextAttributeFont, nil] forState:UIControlStateNormal];
[self.tabBar sizeToFit];
UIView *tabbarBackgroundColorView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0, self.view.bounds.size.width, 49)];
[tabbarBackgroundColorView setBackgroundColor:[UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1]];
[self.tabBar insertSubview:tabbarBackgroundColorView atIndex:0];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsPortrait(interfaceOrientation); // only portrait orientation
}
/**
* orientation for iOS6
**/
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
#end
Call in AppDelegate:
ExtendedTabBarController *tabBarController = [[ExtendedTabBarController alloc] init];
[self setTabBarController:tabBarController];
[[UITabBar appearance] setBackgroundImage:[UIImage imageNamed:#"menu_bg"]];
// code for initialize View- and NavigationControllers...
self.tabBarController.viewControllers = #[highlightsNavigationController, categoryNavigationController, searchNavigationController, favoritesNavigationController, imprintNavigationController];
self.window.rootViewController = self.tabBarController;
[[UITabBar appearance] setSelectionIndicatorImage:[[UIImage alloc] init]];
Set the badge value:
int viewCount = 0;
NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
NSDictionary * dict = [defs dictionaryRepresentation];
for (id key in dict) {
if([key rangeOfString:#"_highlighted"].location != NSNotFound && [[[dict objectForKey:key] objectAtIndex:0] isEqualToString:#"YES"]) {
viewCount++;
}
}
UITabBarItem *tbi = (UITabBarItem *)[self.tabBarController.tabBar.items objectAtIndex:3];
if(viewCount <= 0) {
tbi.badgeValue = nil;
} else {
tbi.badgeValue = nil;
tbi.badgeValue = [NSString stringWithFormat:#"%d", viewCount];
}
Code for overwritten UILabel:
// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
#interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
- (void)awakeFromNib;
-(id)initWithFrame:(CGRect)frame;
#end
#import "UILabel+VerticalAlign.h"
// -- file: UILabel+VerticalAlign.m
#implementation UILabel (VerticalAlign)
- (void)alignTop {
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<newLinesToPad; i++)
self.text = [self.text stringByAppendingString:#"\n "];
}
- (void)alignBottom {
CGSize fontSize = [self.text sizeWithFont:self.font];
double finalHeight = fontSize.height * self.numberOfLines;
double finalWidth = self.frame.size.width; //expected width of label
CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
int newLinesToPad = (finalHeight - theStringSize.height) / fontSize.height;
for(int i=0; i<newLinesToPad; i++)
self.text = [NSString stringWithFormat:#" \n%#",self.text];
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
-(id)initWithFrame:(CGRect)frame
{
id result = [super initWithFrame:frame];
if (result) {
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
return result;
}
#end
I found a solution for my problem on my own:
I must remove the following lines from the overwritten UILabel:
- (void)awakeFromNib
{
[super awakeFromNib];
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
-(id)initWithFrame:(CGRect)frame
{
id result = [super initWithFrame:frame];
if (result) {
[self setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
}
return result;
}
Maybe someone can explain me, why this lines change the text color of the badge value, before we can close this post?
Instead of setting the default UILabel font using a category, use the UILabel's appearance method to set the font:
[[UILabel appearance] setFont:[UIFont fontWithName:#"KievitPro-Regular" size:12.0]];
When I tested this the text for the badge appeared as the normal white color.

Can not adjust UIPopupController to display images

In my application (code listed below), I use a popover to display a series of colors that the user can choose. These colors are used for the color of the drawing they are completing above. I am trying to modify the popover to work the same way, except for this time I would want to display images (the images are saved in the application's documents folder as png files) instead of blocks of color. Listed below is the working code for the color selector popover. ColorGrid is a UIview which contains an NSArray Colors, as well as two NSUIntegers columnCount and rowCount. I have tried to replace the items in the colors array with UIImages of the png files, as well as UIImageViews but I have not been able to get a successful result (or a compilable one). Listed below is the working code. Could anyone show me how I can change the UIColor items to the images to show them in the grid?
- (IBAction)popoverStrokeColor:(id)sender {
StrokeColorController *scc = [[[StrokeColorController alloc] initWithNibName:#"SelectColorController" bundle:nil] autorelease];
scc.selectedColor = self.strokeColor;
[self doPopoverSelectColorController:scc sender:sender];
}
- (void)doPopoverSelectColorController:(SelectColorController*)scc sender:(id)sender {
[self setupNewPopoverControllerForViewController:scc];
scc.container = self.currentPopover;
self.currentPopover.popoverContentSize = scc.view.frame.size;
scc.colorGrid.columnCount = 2;
scc.colorGrid.rowCount = 3;
scc.colorGrid.colors = [NSArray arrayWithObjects:
//put the following below back in after testing
[UIColor blackColor],
[UIColor blueColor],
[UIColor redColor],
[UIColor greenColor],
[UIColor yellowColor],
[UIColor orangeColor],
//[UIColor purpleColor],
// [UIColor brownColor],
// [UIColor whiteColor],
// [UIColor lightGrayColor],
//[UIColor cyanColor],
//[UIColor magentaColor],
nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(colorSelectionDone:) name:ColorSelectionDone object:scc];
[self.currentPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //displays the popover and anchors it to the button
}
Thanks for your help. I am new to objective-c.
edit - heres the function with my attempt to insert the images instead of the colors
- (void)doPopoverSelectColorController:(SelectColorController*)scc sender:(id)sender {
[self setupNewPopoverControllerForViewController:scc];
scc.container = self.currentPopover;
self.currentPopover.popoverContentSize = scc.view.frame.size;
// these have to be set after the view is already loaded (which happened
// a couple of lines ago, thanks to scc.view...
scc.colorGrid.columnCount = 2;
scc.colorGrid.rowCount = 3;
//here we need to get the UIImage items to try to put in the array.
NSArray *pathforsave = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [pathforsave objectAtIndex:0];
//here we need to add the file extension onto the file name before we add the name to the path
//[fileName appendString:#".hmat"];
NSString *strFile = [documentDirectory stringByAppendingPathComponent:#"test.png"];
NSString *strFile1 = [documentDirectory stringByAppendingPathComponent:#"test1.png"];
NSString *strFile2 = [documentDirectory stringByAppendingPathComponent:#"test2.png"];
NSString *strFile3 = [documentDirectory stringByAppendingPathComponent:#"test3.png"];
NSString *strFile4 = [documentDirectory stringByAppendingPathComponent:#"test4.png"];
NSString *strFile5 = [documentDirectory stringByAppendingPathComponent:#"test5.png"];
//now for the Images
UIImage *image = [ UIImage imageWithContentsOfFile: strFile];
UIImage *image1 = [ UIImage imageWithContentsOfFile: strFile1];
UIImage *image2 = [ UIImage imageWithContentsOfFile: strFile2];
UIImage *image3 = [ UIImage imageWithContentsOfFile: strFile3];
UIImage *image4 = [ UIImage imageWithContentsOfFile: strFile4];
UIImage *image5 = [ UIImage imageWithContentsOfFile: strFile5];
UIImageView *imageview = [[[UIImageView alloc] initWithImage:image] autorelease];
[self.view addSubview:imageview];
UIImageView *imageview1 = [[[UIImageView alloc] initWithImage:image1] autorelease];
[self.view addSubview:imageview1];
UIImageView *imageview2 = [[[UIImageView alloc] initWithImage:image2] autorelease];
[self.view addSubview:imageview2];
UIImageView *imageview3 = [[[UIImageView alloc] initWithImage:image3] autorelease];
[self.view addSubview:imageview3];
UIImageView *imageview4 = [[[UIImageView alloc] initWithImage:image4] autorelease];
[self.view addSubview:imageview4];
UIImageView *imageview5 = [[[UIImageView alloc] initWithImage:image5] autorelease];
[self.view addSubview:imageview5];
imageview.image = image;
imageview1.image = image1;
imageview2.image = image2;
imageview3.image = image3;
imageview4.image = image4;
imageview5.image = image5;
scc.colorGrid.colors = [NSArray arrayWithObjects:
// When attempting to add the images like this - get the error identified expected
// after the e in image, at the end bracket. Putting a * does nothing to change the error
[image],
// When adding one of the Imageviews, i get the same error as above
//below is how I attempted to add it
[imageView],
//
nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(colorSelectionDone:) name:ColorSelectionDone object:scc];
[self.currentPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; //displays the popover and anchors it to the button
}
Remove your square brackets around image and/or imageView :
scc.colorGrid.colors = [NSArray arrayWithObjects:
// Not : [image] but
image,
// or
imageView,
// Not : [imageView],
nil];