Custom "placeholder" on UITextField being truncated unexpectedly - ios

I'm trying to create a text field with a persistent "placeholder" of sorts by adding a UILabel as a subview of the text field. However, my label keeps being truncated, and I can't figure out why. Any advice is much appreciated!
Here's what I'm currently getting (it's supposed to say "first name":
Here's the code I have:
#import "LabeledTextField.h"
#interface PlaceholderLabel : UILabel
#end
#implementation PlaceholderLabel
-(void)drawTextInRect:(CGRect)rect
{
UIEdgeInsets insets = {0, 10, 0, 0};
return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}
#end
#interface LabeledTextField ()
#property (nonatomic) PlaceholderLabel *placeholderLabel;
#end
#implementation LabeledTextField
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_placeholderLabel = [[PlaceholderLabel alloc] initWithFrame:CGRectMake(10, [self frame].size.height/2, 0, 0)];
[_placeholderLabel setBackgroundColor:UIColorFromRGB(0xdedede)];
[_placeholderLabel setTextColor:UIColorFromRGB(0x787878)];
[_placeholderLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:kTextFieldPlaceholderFontSize]];
[_placeholderLabel setLineBreakMode:NSLineBreakByTruncatingTail];
[_placeholderLabel setNumberOfLines:1];
}
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
[self setLeftView:_placeholderLabel];
}
-(void)drawPlaceholderInRect:(CGRect)rect
{
return;
}
-(void)setPlaceholder:(NSString *)placeholder
{
[_placeholderLabel setText:placeholder];
[_placeholderLabel sizeToFit];
}
-(CGRect)leftViewRectForBounds:(CGRect)bounds
{
CGRect frame = [_placeholderLabel frame];
frame.origin.y = (self.frame.size.height - frame.size.height)/2;
frame.size = [[_placeholderLabel text] sizeWithFont:[UIFont fontWithName:#"HelveticaNeue" size:kTextFieldPlaceholderFontSize]];
return frame;
}
#end

Related

Can't switch to number keyboard iOS

My app won't allow users to switch keyboards to the number/character keyboard.
I don't have anything in my UI Inspector showing over the bottom of the screen.
I am truly stumped as to what could be causing this issue. Whatever it is blocks the number/symbol switcher, the keyboard language (or Emoji) selector, and the speech to text button. The space bar and return key on the same row continue to operate fine.
The affected UITextField's are subclassed, the keyboard works as expected on the other 5 views in which they are contained, but here is their code:
JCTextField.h
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface JCTextField : UITextField
#property (nonatomic, retain) IBInspectable UIColor *underlineColor;
#property (nonatomic) IBInspectable CGFloat underlineWidth;
#property (nonatomic, retain) IBInspectable UIImage *sideImage;
#property (nonatomic) IBInspectable CGFloat internalOffset;
#property (nonatomic) IBInspectable CGFloat borderOffset;
#end
JCTextField.m
#import "JCTextField.h"
#implementation JCTextField
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if(self != nil) {
self.underlineColor = [UIColor blackColor];
self.underlineWidth = 1;
self.internalOffset = 0;
self.borderOffset = 0;
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CALayer *border = [CALayer layer];
border.borderColor = _underlineColor.CGColor;
border.frame = CGRectMake(_borderOffset, self.frame.size.height - _underlineWidth, self.frame.size.width - (_borderOffset * 2), self.frame.size.height);
border.borderWidth = _underlineWidth;
[self.layer addSublayer:border];
self.layer.masksToBounds = YES;
[self setValue:[UIColor lightTextColor] forKeyPath:#"_placeholderLabel.textColor"];
[self setTextColor:[UIColor whiteColor]];
[self setFont:[UIFont fontWithName:#"Montserrat-Regular" size:16.0]];
if (self.sideImage) {
UIImageView *sideImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width - 30, 0, 30, 30)];
sideImageView.contentMode = UIViewContentModeCenter;
sideImageView.image = self.sideImage;
[self addSubview:sideImageView];
}
[self setTintColor:[UIColor whiteColor]];
[self setValue:[UIColor lightGrayColor] forKeyPath:#"_placeholderLabel.textColor"];
}
- (CGRect)textRectForBounds:(CGRect)bounds {
if (self.sideImage) {
UIEdgeInsets insets = UIEdgeInsetsMake(0, _internalOffset, 0, 18);
return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, insets)];
}
UIEdgeInsets insets = UIEdgeInsetsMake(0, _internalOffset, 0, 0);
return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, insets)];
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
if (self.sideImage) {
UIEdgeInsets insets = UIEdgeInsetsMake(0, _internalOffset, 0, 18);
return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, insets)];
}
UIEdgeInsets insets = UIEdgeInsetsMake(0, _internalOffset, 0, 0);
return [super textRectForBounds:UIEdgeInsetsInsetRect(bounds, insets)];
}
#end

NSTextAlignmentCenter not work with custom text field

I was subclassing UITextField to make my custom text field.
I used self.textAlignment = NSTextAlignmentCenter; to set the text alignment, but when I began editing, the cursor's initial position was left rather than exactly the center. Hoever, when I entered something, the text was in the center position.
textRectForBounds: and editingRectForBounds: all return the same CGRect value.
Here is the code:
#interface MyTextfield () <UITextFieldDelegate>
#end
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.delegate = self;
self.textAlignment = NSTextAlignmentCenter;
}
return self;
}
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 20.5, 4.5);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 20.5, 4.5);
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
// Do some animation
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
// Do some animation
}
What's the problem? How can I fix it?
first of all create one UITextField class.
CustomTextfield.h
#import <UIKit/UIKit.h>
#interface CustomTextfield : UITextField
#end
CustomTextfield.m
#import "CustomTextfield.h"
#interface CustomTextfield () <UITextFieldDelegate>
#end
#implementation CustomTextfield
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.textAlignment = NSTextAlignmentCenter;
self.font = [UIFont systemFontOfSize:15];
self.placeholder = #"Test";
self.autocorrectionType = UITextAutocorrectionTypeNo;
self.keyboardType = UIKeyboardTypeDefault;
self.returnKeyType = UIReturnKeyDone;
self.textAlignment = NSTextAlignmentCenter;
self.clearButtonMode = UITextFieldViewModeWhileEditing;
self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.borderStyle=UITextBorderStyleRoundedRect;
}
return self;
}
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 20.5, 4.5);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return CGRectInset(bounds, 20.5, 4.5);
}
Now use CustomTextfield class to your view controller like this.
-(void)viewDidLoad{
UITextField *txtEmailfield = [[CustomTextfield alloc] initWithFrame:CGRectMake(10, 200, 300, 40)];
txtEmailfield.delegate = self;
[self.view addSubview:txtEmailfield];
}
Note : In this view controller please add this in #interface yourviewcontroller name () <UITextFieldDelegate>

Creating a receipt style UIView

I am attempting to create a view to show a list of items and prices using two UILabels in a UIView.
In my UIViewController I call my subview LineItemView and pass data, and return the UIView to the main view that will hold the subviews.
Though my view is returning empty. The strings are null.
ViewController.m
#import "LineItemView.h"
//...
#property (weak, nonatomic) IBOutlet UIView *viewCharges;
//...
- (void)viewDidLoad {
[super viewDidLoad];
[self loadData];
}
- (void) loadData {
//Here we will fill in the viewCharges view
LineItemView * view = [[LineItemView alloc]init];
view.linePrice = #"1.00";
view.lineItem = #"Something";
[self.viewCharges addSubview:view];
}
LineItemView.h
#interface LineItemView : UIView {
UILabel * lblLineItem, *lblLinePrice;
}
#property (nonatomic,strong) NSString* lineItem;
#property (nonatomic,strong) NSString* linePrice;
LineItemView.m
#define LABEL_MINIMUM_HEIGHT 32
#define VERTICAL_MARGIN 5
#define HORIZONTAL_MARGIN 10
#implementation LineItemView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self createUI];
[self updateData];
NSLog(#"\n\n\n Line Item: %# Price: %# \n\n\n", self.lineItem, self.linePrice);
}
return self;
}
-(void) createUI {
lblLineItem = [[UILabel alloc] initWithFrame:CGRectZero];
lblLineItem.backgroundColor = [UIColor greenColor];
[self addSubview:lblLineItem];
lblLinePrice = [[UILabel alloc] initWithFrame:CGRectZero];
lblLinePrice.backgroundColor = [UIColor yellowColor];
[self addSubview:lblLinePrice];
}
- (void) updateLayout {
lblLineItem.frame = CGRectMake(HORIZONTAL_MARGIN, VERTICAL_MARGIN, 300, 35);
lblLinePrice.frame = CGRectMake(lblLineItem.frame.origin.x + lblLineItem.frame.size.width + HORIZONTAL_MARGIN, VERTICAL_MARGIN, 80, 35);
}
- (void) updateData {
lblLineItem.text = self.lineItem;
lblLinePrice.text = [NSString stringWithFormat:#"%0.2f", [self.linePrice floatValue]];
}
- (void) layoutSubviews {
[super layoutSubviews];
[self updateLayout];
}
What am I doing wrong?
If I want to continue calling LineItemView, how do I ensure that it is added below the previous one and ensure the viewCharges size is readjusted to fit all the subviews?
Solution using setters:
#implementation LineItemView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self createUI];
}
return self;
}
-(void) createUI {
lblLineItem = [[UILabel alloc] initWithFrame:CGRectZero];
lblLineItem.backgroundColor = [UIColor greenColor];
[self addSubview:lblLineItem];
lblLinePrice = [[UILabel alloc] initWithFrame:CGRectZero];
lblLinePrice.backgroundColor = [UIColor yellowColor];
[self addSubview:lblLinePrice];
}
- (void) updateLayout {
lblLineItem.frame = CGRectMake(HORIZONTAL_MARGIN, VERTICAL_MARGIN, 300, 35);
lblLinePrice.frame = CGRectMake(lblLineItem.frame.origin.x + lblLineItem.frame.size.width + HORIZONTAL_MARGIN, VERTICAL_MARGIN, 80, 35);
}
- (void) layoutSubviews {
[super layoutSubviews];
[self updateLayout];
}
- (void)setLineItem:(NSSTring *)lineItem {
_lineItem = lineItem;
lblLineItem.text = self.lineItem;
}
- (void)setLinePrice:(NSNumber *)linePrice {
_linePrice = linePrice;
lblLinePrice.text = [NSString stringWithFormat:#"%0.2f", [self.linePrice floatValue]];
}

Adding Subview to UICollectionViewCell Subclass?

I seem to be having trouble adding a subview to a view within my UICollectionViewCell subclass.
I have an abstract UICollectionViewCell subclass titled MessageItem, which looks like this:
I've created a few classes that inherit from this (since they all use the same logic for the header and footer). However I can't seem to add any subviews into MessageItem's blue view from within the child subclasses.
For example one of the child views is called TextItem. I'm trying to add a label to it's parent messageView (the blue view) but it only works if I do it in my UIViewController's cellForItemAtIndexPath:(NSIndexPath *)indexPath method, and not in my custom subclass.
This is how I'm trying to add it in my child subclass:
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//Setup Message Label
[self setupMessageLabel];
}
return self;
}
#pragma mark - Setup Methods
- (void)setupMessageLabel {
NSLog(#"Setting up label");
//Setup Message Label
self.messageLabel = [TTTAttributedLabel new];
self.messageLabel.verticalAlignment = TTTAttributedLabelVerticalAlignmentCenter;
self.messageLabel.textInsets = UIEdgeInsetsMake(8, 8, 8, 8);
self.messageLabel.numberOfLines = 0;
[self.messageContentView addSubview:self.messageLabel];
[self.messageContentView autoPinEdgesToSuperviewEdges];
//Update Label Color
self.messageLabel.backgroundColor = FlatRed;
}
Note: I'm not using storyboard or xibs. Could that be the problem?
Update
This is what my MessageItem class is implemented:
MessageItem.h
#import <UIKit/UIKit.h>
#class Message;
#interface MessageItem : UICollectionViewCell
#property (nonatomic, strong) Message *message;
#property (nonatomic, strong) UIView *messageContentView;
#end
MessageItem.m
#interface MessageItem ()
#property (nonatomic, strong) TTTAttributedLabel *headerLabel;
#property (nonatomic, strong) TTTAttributedLabel *footerLabel;
#end
#implementation MessageItem
#synthesize message = _message;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//Setup Main View
[self setupMainView];
}
return self;
}
#pragma mark - Setup Methods
- (void)setupMainView {
//Setup Header
[self setupHeaderLabel];
//Setup Message
[self setupMessageView];
//Setup Footer View
[self setupFooterLabel];
}
- (void)setupHeaderLabel {
//Setup Header Label
self.headerLabel = [[TTTAttributedLabel alloc] initForAutoLayout];
self.headerLabel.font = [UIFont fontWithName:#"Lato-Bold" size:12.0];
self.headerLabel.textColor = FlatGray;
self.headerLabel.textAlignment = NSTextAlignmentCenter;
self.headerLabel.verticalAlignment = TTTAttributedLabelVerticalAlignmentCenter;
self.headerLabel.textInsets = UIEdgeInsetsMake(0, 8, 0, 8);
self.headerLabel.backgroundColor = FlatPurple;
[self.contentView addSubview:self.headerLabel];
[self.headerLabel autoSetDimension:ALDimensionHeight toSize:20.0];
[self.headerLabel autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero excludingEdge:ALEdgeBottom];
}
- (void)setupMessageView {
//Setup Message View
self.messageContentView = [UIView new];
self.messageContentView.backgroundColor = [UIColor blueColor];
[self.contentView addSubview:self.messageContentView];
[self.messageContentView autoSetDimension:ALDimensionHeight toSize:30 relation:NSLayoutRelationGreaterThanOrEqual];
[self.messageContentView autoPinEdgeToSuperviewEdge:ALEdgeLeading];
[self.messageContentView autoPinEdgeToSuperviewEdge:ALEdgeTrailing];
[self.messageContentView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.headerLabel];
}
- (void)setupFooterLabel {
//Setup Footer Label
self.footerLabel = [[TTTAttributedLabel alloc] initForAutoLayout];
self.footerLabel.font = [UIFont fontWithName:#"Lato-Bold" size:10.0];
self.footerLabel.textColor = FlatGray;
self.footerLabel.backgroundColor = FlatGreen;
self.footerLabel.textAlignment = NSTextAlignmentLeft;
self.footerLabel.textInsets = UIEdgeInsetsMake(0, 8, 0, 8);
[self.contentView addSubview:self.footerLabel];
[self.footerLabel autoSetDimension:ALDimensionHeight toSize:10.0];
[self.footerLabel autoPinEdgeToSuperviewEdge:ALEdgeLeading];
[self.footerLabel autoPinEdgeToSuperviewEdge:ALEdgeTrailing];
[self.footerLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[self.footerLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.messageContentView];
}
TextItem.m
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//Setup Message Label
[self setupMessageLabel];
}
return self;
}
#pragma mark - Setup Methods
- (void)setupMessageLabel {
//Setup Message Label
self.messageLabel = [[TTTAttributedLabel alloc] initWithFrame:CGRectMake(0, 0, 320, 100)];
self.messageLabel.verticalAlignment = TTTAttributedLabelVerticalAlignmentCenter;
self.messageLabel.textInsets = UIEdgeInsetsMake(8, 8, 8, 8);
self.messageLabel.numberOfLines = 0;
[self.messageContentView addSubview:self.messageLabel];
//Update Label Color
self.messageLabel.backgroundColor = FlatRed;
}
#pragma mark - Setter Methods
- (void)setMessageText:(NSString *)text {
//Incoming Text Message
NSMutableAttributedString *textString = [[NSMutableAttributedString alloc] initWithString:text];
[textString addAttribute:NSForegroundColorAttributeName value:[UIColor darkGrayColor] range:NSMakeRange(0, textString.length)];
[textString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:16 weight:UIFontWeightLight] range:NSMakeRange(0, textString.length)];
//Set Paragraph Style
NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
paragraphStyle.minimumLineHeight = 20;
paragraphStyle.maximumLineHeight = 20;
[textString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, textString.length)];
//Update Message Label
[self.messageLabel setText:textString];
NSLog(#"Set Message Label Text");
}
- (void)setMessage:(Message *)message {
//Super
[super setMessage:message];
//Update Message Text
[self setMessageText:message.text];
}
This is what my collectionView looks like:
I would at least expect the color of the messageLabel to reflect the change in TextItem, but it doesn't.
Have you implement initWithCoder?
- (id)initWithCoder:(NSCoder*)aDecoder
{
if(self = [super initWithCoder:aDecoder]) {
// Do something
}
return self;
}
I don't have all your code, but you code looks good to me. Maybe the problem was how you init the TextItem.
Here is a demo using your code, it works fine to me. https://www.dropbox.com/s/7qp9ayqnyacf57j/CustomCellView.zip?dl=0

Label in collection view cell won't show up

I'm trying yo have a label and image show up in collection view cells, but only the image will here's my code
The header File
#import <UIKit/UIKit.h>
#import "ComicMetadata.h"
#interface ComicCell : UICollectionViewCell
#property (nonatomic, retain) UIImageView *page;
#property (nonatomic, retain) UILabel *name;
#end
The Body
#import "ComicCell.h"
#implementation ComicCell
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self){
self.page = [[UIImageView alloc] init];
self.name = [[UILabel alloc] initWithFrame:self.bounds];
self.autoresizesSubviews = YES;
self.name.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.name.font = [UIFont systemFontOfSize:13];
self.name.textAlignment = NSTextAlignmentLeft;
[self.contentView addSubview:self.page];
[self.contentView addSubview:self.name];
self.name.text = #"Test";
}
return self;
}
- (void)layoutSubviews{
[super layoutSubviews];
//self.page.frame = self.contentView.bounds;
self.page.frame = CGRectMake(0, 0, 234, 312);
}
What am I doing wrong? extra text because Stackoverflow doesn't like the code to text ratio
When ComicCell init with frame, the bounds does not init exactly, you must set frame for the label again in layoutSubviews.
- (void)layoutSubviews{
[super layoutSubviews];
self.page.frame = CGRectMake(0, 0, 234, 312);
self.name.frame = CGRectMake(0, 0, 234, 312);
}

Resources