I have UITextView where user types a text. When the keyboard is shown, I add inputView with UIlabel on it. I want this UIlabel to hold character length of the text. It seems very easy task, but unfortunatelly it does not update this word counter UILabel when user change text..
this is how I load the inputView
_textView.inputView = [self inputAccessoryView];
in inputAccessoryView I simply add UILabel as a subview. When keyboard is show, UILabel is also show with inputView. I track changes on
- (void)textViewDidChange:(UITextView *)textView
unfortunatelly the UILabel is never updated (redrawn). When I log in to console its value, the value is correct, so its updating, but the UIlabel is never redrawn and holds the default value.
Can anyone help me with this?
did you
_textView.delegate = self;
?
I know it was 5 years ago, but it might help others, who like me stumble upon your question.
I use a UIToolbar as my inputAccessoryView (in my case it has a label, a flexible separator and a button).
On textFieldEditingChanged event I rebuild part of the toolbar like this
#IBAction func textFieldEditingChanged(_ sender: UITextField) {
//get a reference to the toolbar
let toolBar = sender.inputAccessoryView as! UIToolbar
//create a new label and set size + other properties
toolbarLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 40, height: 22))
toolbarLabel.text = mySpecificCalculatedString(sender.text!)
toolbarLabel.font = defaultFont(17)
toolbarLabel.adjustsFontSizeToFitWidth = true
let width = toolbarLabel.textRect(forBounds: CGRect(x: 0, y: 0, width: maxWidthForLabel, height: 0), limitedToNumberOfLines: 1).size.width
toolbarLabel.frame = CGRect(x: 0, y: 0, width: width, height: 22)
toolbarLabel.textColor = .black
toolbarLabel.tag = 666
//rebuild the specific tolbar item
let customView = UIBarButtonItem(customView: toolbarLabel)
toolBar.items![0] = customView
}
Note: simply changing the text of the label did not work for me either, I had to reinitialize it.
Hope it helps.
Related
I need to create custom button class, reuse it 4 times and I also need to override its text and image name. My next problem is how to set its frame somehow dynamically (now it is static), because I need this 4 buttons in grid 2x2.
I'm trying to create button exactly like this: https://imgur.com/a/dNhUGhc.
I have coded this but it is static and in ViewController I can't edit (override) these labels and image name. And if I tried to reuse this class I would have them in the same spot, because frame settings is exactly the same.
I'm subclassing UIButton. If something more suitable exists just let me know.
Code for adding label
// city label
let cityRect = CGRect(x: 0, y: 20, width: buttonWidth, height: 25)
let cityLabel = UILabel(frame: cityRect)
cityLabel.text = "Label"
cityLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
cityLabel.textAlignment = .center
addSubview(cityLabel)
Code for adding image
// image
let imageView = UIImageView(image: UIImage(named: "something"))
imageView.frame = CGRect(x: 0, y: 60, width: 40, height: 40)
imageView.center.x = self.center.x - 20
addSubview(imageView)
Can you guys help me? Thanks
It looks like what you need to do is use an IBOutlet. Basically, an IBOutlet will give you a reference within your code (custom UIView or UIViewController subclass) to the button that you've setup in xib or storyboard. Then you can make any changes or adjustments that you want to it at runtime.
Check this out to learn more about IBOutlets and how to set them up in your project.
In my swift app I've a collection view and I want to creare a stretchable header view like this in table view: https://medium.com/if-let-swift-programming/how-to-create-a-stretchable-tableviewheader-in-ios-ee9ed049aba3
You already answered your question yourself with that article link, unless I miss something.
I will copy & paste for you and others that may have the same question, if it helps, because it even ships with a github link (kudos to Abhimuralidharan # Medium):
Create a tableview with the basic datasource and delegate methods which are required to simply load the table with some data.
Set the tableview’s contentInset property:
tableView.contentInset = UIEdgeInsetsMake(300, 0, 0, 0)
Here, I set the top value as 300 which is a calculated number which I will set as the initial normal height for the header imageview. Now, that we set the contentInset , the tableview’s frame will start at (0,0) and the first cell will start at (0,300).
Now, create an imageview with height 300 and add it to the current View above the tableview.
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300)
imageView.image = UIImage.init(named: “poster”)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
Then, add the following code in the scrollview delegate method scrollViewDidScroll which gets called every time the tableview is scrolled.
func scrollViewDidScroll (_ scrollView: UIScrollView) {
let y = 300 — (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height)
}
Compile and run the code. Full source code is available in github.
I’m working on a iOS-App based on Xcode’s “Master-Detail Template” and want to use custom colors for some of the UI elements.
However, I couldn’t find out how to change the right separator of the UINavigationBar:
I’ve already tried to change the backgroundColor of UINavigationBar, UINavigationItem and its titleView but without success.
Would be great if someone has a clue.
EDIT:
I’ve just noted that viewed in vertical mode, it’s the whole separator that I want to ink?
A slight modification of this answer gives you
extension UINavigationBar {
func setRightBorderColor(color: UIColor, width: CGFloat) {
let rightBorderRect = CGRect(x: frame.width, y: 0, width: width, height: frame.height)
let rightBorderView = UIView(frame: rightBorderRect)
rightBorderView.backgroundColor = color
addSubview(rightBorderView)
}
}
I'm trying to implement a notification bar which should appear below the UINavigationBar. The problem is that when the notification appears the cells in the UITableView are not pushed down and are therefore hidden behind the notification like this:
My code looks as follows:
#IBOutlet var notificationView: UIView!
let navBar = self.navigationController?.navigationBar
let navBarHeight = navBar?.frame.height
let notificationFrame = notificationView.frame
let nSetX = notificationFrame.origin.x
let nSetY = CGFloat(navBarHeight!)
let nSetWidth = self.view.frame.width
let nSetHight = notificationFrame.height
notificationView.frame = CGRect(x: nSetX, y: nSetY, width: nSetWidth, height: nSetHight)
self.navigationController?.navigationBar.addSubview(notificationView)
There are a few solutions for your problem, but maybe the easiest one for you could be adding a content offset on the top, like this:
self.tableView.contentInset = UIEdgeInsetsMake(newBar.height, 0, 0, 0)
Another solution as #h44f33z suggested is adding a constraint between the new bar and the tableView, so it would be similar to this (in visual format):
"V:|-0-[newBar(\(newBar.height))]-0-[tableView]-0-|"
I have a UIButton built in Interface Builder that has a default label. In Xcode, I'm changing the label text dynamically like so:
myButton.titleLabel.text = #"this is the new label";
However, when the text updates, the new string is being clipped down to the same size as the original string and ends up looking like:
this...label
Anyone know why this is happening?
You should use setTitle:forState: to change the title of a UIButton. If you change the title yourself, the button has no indication that it needs to resize the label – you'd end up having to do something like this:
myButton.titleLabel.text = #"this is the new label";
[myButton setNeedsLayout];
but I'm not even sure that would work in all cases. Methods like setTitle:forState: are provided so that you can provide titles for multiple states without having to update the button manually, and so that the button knows that it needs to be laid out with a new title.
Try using the button's setTitle method (rather than setting the title directly on the label). It should force the title label to be resized.
Objective C:
[myButton setTitle:#"This is the text" forState:UIControlStateNormal];
Or in Swift:
myButton.setTitle("This is the text", for: .normal)
An alternative solution is to let the UIButton's inner UILabel to shrink the font size, as UILabels can do :
button.titlelabel.minimumFontSize = 8.0; // or some more adequate size
self.buttonWithLongTitle.titleLabel.adjustsFontSizeToFitWidth = YES;
Call sizeToFit on your button. This will resize the button to fit the text.
If that didn't work you can always determine the string size and adjust the button frame width. In that case you are sure it will fit.
// Calculate the size
CGSize buttonSize = [#"My text.." sizeWithFont:[UIFont systemFontOfSize:15.0]
constrainedToSize:someSize lineBreakMode:UILineBreakModeWordWrap];
// Do whatever you want with the "buttonSize", you can for example adjust your button's frame width
Solution in Swift 4.2
yourButton.titleLabel?.minimumScaleFactor = 0.5 //set whatever you want here to scale
yourButton.titleLabel?.adjustsFontSizeToFitWidth = true
Solution for Objective C
[yourButton.titleLabel setMinimumScaleFactor:0.5];
[yourButton.titleLabel setAdjustsFontSizeToFitWidth:YES];
This worked for me while setting my button up programmatically with all other constraints.
yourButton.widthAnchor.constraint(equalToConstant: yourButton.intrinsicContentSize.width).isActive = true
You can also add "padding" like so
yourButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
Use Autoresizing mask if not selected.
None of the solutions above worked for me. What did was sublclassing UIButton and re-setting the frame of the titleLabel:
Context: My font was Josefin Sans and it does clipping the top part of "Ñ". I can imagine it could happen with any other text using a different font.
open class Button: UIButton {
open override func layoutSubviews() {
super.layoutSubviews()
guard let titleLabel = titleLabel else {
return
}
// Play around to get these numbers
let heightToAdd: CGFloat = 15
let widthToAdd: CGFloat = 100
titleLabel.frame = CGRect(
origin: CGPoint(
x: titleLabel.frame.origin.x - widthToAdd / 2,
y: titleLabel.frame.origin.y - heightToAdd / 2),
size: CGSize(
width: titleLabel.frame.width + widthToAdd,
height: titleLabel.frame.height + heightToAdd
)
);
}
}
Play around with the values widthToAdd and heightToAdd or make them injectable when setting a new title.
It is not a superb solution, but it was the only think that worked for me.