I need to figure out how to program something like this:
The text expands as the user clicks the down button and fold back to the short version after clicking up. Are there any libraries I could study? I am a beginner in programming and just need advice on how to approach this task, what guides to study and so on.
All you have to do is initially set the UILabel to have a numberOfLines of lets say 7 and line break mode to be .byTruncatingTail.
Then on button click simply change the numberOfLines to 0 and line break mode to be .byWordWrapping. Then when you wish to hide the text, just press the button and set the UILabel to its initial values.
To solve this issue read about AutoLayout. This is small example how it is possible to do.
This is coding part. This class contain IBOutlet for the height of the UITextView and button action.
class ViewController: UIViewController {
let defaultHeight = 128
let expectedHeight = 600
var state: Bool = false
#IBOutlet weak var height: NSLayoutConstraint!
#IBAction func showAction(_ sender: Any) {
UIView.animate(withDuration: 0.3, animations: {
self.state = !self.state
self.height.constant = CGFloat(self.state ? self.expectedHeight: self.defaultHeight)
self.view.layoutIfNeeded()
})
}
}
This is from storyboard.
You can set an height constraint for your UILabel, and on the tap button event change the constraint constant to the contentsize of your label.
After your can animate it with
UIView.animate(duration)
Related
I am making a function that the height of a UIView increases and decreases when a button is pressed.
When the height of the UIView was reduced, the value created a layout in the storyboard, When the height of the UIView is increased, the value will be the height of the UITextView.
The picture above is before the UIView is stretched. Press the button at the bottom of the photo to stretch the UIView
The picture above is after the UIView is stretched. If you press the button at the bottom of the picture above, the UIView will shrink again.
The first thing I am curious about is the code to make the height of the UIView increase.
#IBOutlet weak var bookInfoView: UIView!
#IBOutlet weak var bookInfoVieweBtn: UIButton!
#IBOutlet weak var bookInfoTextView: UITextView!
#IBAction func bookInfoViewBtnTapped(_ sender: Any) {
print("##bookInfoViewBtnTapped!")
let f = bookInfoView.frame
let textView = bookInfoTextView.frame
bookInfoView.frame = CGRect(x: f.origin.x, y: f.origin.y, width: f.width, height: textView.height)
}
If you press the button using the code above, it does nothing. What should I do?
1.Set some default value for the height of your the view your are trying to expand. Then if you are using StoryBoard make an IBOutlet to your ViewConroller, and remove the weak reference (that's because we are going to deactivate the height anchor and if it is weak and you deactivate it, the ARC will dealocate it. If your are going for it programatically just store the height anchor in a local variable. So it should like something like this:
#IBOutlet var yourViewHeightAnchor: NSLayoutConstraint!
2. Add a target to your button or if your using StoryBoard or Xib drag a IBAction to you ViewController. When the button is clicked, your only job is to deactive/active the height anchor. ( The activation will serve for collapse)
#IBAction func expandClicked(_ sender: Any) {
yourViewHeightAnchor.isActive.toggle()
}
If you wish to use some animation for expanding/collapsing, your expandClicked function should look something like this:
#IBAction func expandClicked(_ sender: Any) {
UIView.animate(withDuration: 0.6, animations: {
self.yourViewHeightAnchor.isActive.toggle()
self.view.layoutIfNeeded()
})
}
Follow below steps:-
Define height constraint in your storyboard.
create IBOutlet of height constraint
Then on button press, increase/decresse your height of textview like:-
textViewHeightConstant.constant = someValue
I'm adding accessibility support for my app and there is a scenario where I'm changing the height constraint of a TextView to 0 and 44.
I'm disabling the accessibility when the height is 0 and vice versa. But on doing so, when the height becomes 44, and even though the accessibility is ON for the UITextView; the accessibility cursor is never pointing the UITextView unless until I switch off & on the Accessibility.
Disabling/enabling the accessibility, hiding the accessibility elements
textView.accessibilityElementsHidden = true
textView.disableAccessibility()
I tried and implemented your use case in a blank project as follows:
Button H 0 leads to a zero textview height and disables the textview accessibility while Button H 44 leads to a 44 textview height and enables the textview accessibility.
The corresponding code (Swift 5.0, iOS 12) is defined hereunder:
class SOFViewController: UIViewController {
#IBOutlet weak var myTextView: UITextView!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
// Action for "BUTTON H O"
#IBAction func heightIsZero(_ sender: UIButton) {
heightConstraint.constant = 0
myTextView.isAccessibilityElement = false
}
// Action for "BUTTON H 44"
#IBAction func heightIsNotZero(_ sender: UIButton) {
heightConstraint.constant = 44
myTextView.isAccessibilityElement = true
}
}
The final result with the VoiceOver gestures is displayed hereafter:
Double tap the Button H 0 to disable the textview accessibility and set its height to 0.
Select the next element to check if the focus is still possible on the textview despite its zero height.
Double tap the Button H 44 to enable the textview accessibility and set its height to 44.
Select the previous element to check if the textview can be focused.
The focus is made on the textview without turning VoiceOver on/off.
Following this rationale, you can notice that VoiceOver is working properly on changing height constraint for a textview in iOS.
I have three UITextField aligned in a container used to choose a date.
At first only the month textfield is shown in the container and takes the full width, then when the user chose the month, the day textfield appear and they both take half of the container.
The text alignement in these textfields is centered.
My problem is that when I animate their size, the text doesn't animate and jumps directly to the final position while the width of the textfields animate correctly.
Step 1 : The TextField Before Animation
Step 2 : The TexField width is animating but the text is already in the final position
Step 3 : The TexField Finished Animating
My code used to animate the constraint :
monthTextfieldTrailingConstraint.priority = currentDateSelectionType == .month ? UILayoutPriorityDefaultHigh : UILayoutPriorityDefaultLow
dayTextfieldTrailingConstraint.priority = currentDateSelectionType == .day ? UILayoutPriorityDefaultHigh : UILayoutPriorityDefaultLow
yearTextfieldTrailingConstraint.priority = currentDateSelectionType == .year ? UILayoutPriorityDefaultHigh : UILayoutPriorityDefaultLow
UIView.animate(withDuration: nextStepAnimationDuration) {
self.layoutIfNeeded()
}
I had almost the exact same question. Please see my question and its answer for reference: UITextField text jumps when animating width constraint
Solution Demo
The solution is to embed your textfields within another view (e.g. another UITextField or a UIView). In the gif below, I put a textfield within a textfield. Note that helloWorldTextField has a blue border to show its location within the second textfield behind it.
Instructions
For each field (month, day), make two textfields, e.g. monthTextField and monthBorderTextField.
Remove monthTextField's border and background color. Keep borderTextField's border and background color.
Center monthTextField within borderTextField.
Animate the width of borderTextField as needed.
Github link and Code
Here is the link to my project on Github: https://github.com/starkindustries/ConstraintAnimationTest
Here is the code for my test project for my MyViewController class. Everything else is setup in the storyboard which can be viewed on Github at the link above.
class MyViewController: UIViewController {
// Hello World TextField Border var
#IBOutlet weak var borderTextFieldWidth: NSLayoutConstraint!
// Button Vars
#IBOutlet weak var myButton: UIButton!
var grow: Bool = false
func animateGrowShrinkTextFields(grow: Bool, duration: TimeInterval) {
if grow {
UIView.animate(withDuration: duration, animations: {
self.borderTextFieldWidth.constant = 330
self.view.layoutIfNeeded()
}, completion: { (finished: Bool) in
print("Grow animation complete!")
})
} else {
UIView.animate(withDuration: duration, animations: {
self.borderTextFieldWidth.constant = 115
self.view.layoutIfNeeded()
}, completion: { (finished: Bool) in
print("Shrink animation complete!")
})
}
}
#IBAction func toggle(){
let duration: TimeInterval = 1.0
grow = !grow
let title = grow ? "Shrink" : "Grow"
myButton.setTitle(title, for: UIControlState.normal)
animateGrowShrinkTextFields(grow: grow, duration: duration)
}
}
Notes and References
What led me to this solution was #JimmyJames's comment: "You are just animating the UITextField width, but the content inside is not animated."
I researched how to animate font changes and came across this question: Is there a way to animate changing a UILabel's textAlignment?
In that question #CSmith mentioned that "you can animate the FRAME, not the textAlignment" https://stackoverflow.com/a/19251634/2179970
The accepted answer in that question suggests to use a UILabel within another frame. https://stackoverflow.com/a/19251735/2179970
I'm trying to make a very simple login page. Everything is fine, until I started doing some animations.
When I click login button, I move the logo 100px to the top, then I show the inputs.
That worked correctly, but when I click the textfield to edit it, the image (logo) returns to its original position!
My code:
#IBAction func LoginClick(sender: AnyObject) {
UIView.animateWithDuration(2, animations: {
var center = self.logoImage.center
center.y -= 100
self.logoImage.center = center
self.usernameInput.hidden=false
self.passwordInput.hidden=false
self.usernameLine.hidden=false
self.passwordLine.hidden=false
self.slidesImg.hidden=true
})
}
Auto Layout is running and placing your logo back to where the constraints say it should be. Instead of modifying the frame by changing the center, you should create an IBOutlet to the vertical space constraint and then update the constant property to move your logo up.
To create the IBOutlet, first click on the vertical bar that represents the vertical constraint in the Storyboard. Then control-click on the constraint and drag to your viewController code. Give it a name like topSpace.
You'll need to call layoutIfNeeded() to animate the constraint change:
#IBOutlet weak var topSpace: NSLayoutConstraint!
#IBAction func LoginClick(sender: AnyObject) {
topSpace.constant -= 100
UIView.animateWithDuration(2, animations: {
self.logoImage.layoutIfNeeded()
self.usernameInput.hidden=false
self.passwordInput.hidden=false
self.usernameLine.hidden=false
self.passwordLine.hidden=false
self.slidesImg.hidden=true
})
}
I want to move my UIImageView when a certain button is clicked. I have this code:
#IBOutlet weak var counter: UILabel!
#IBOutlet weak var indexCrow: UIImageView!
var crow = 0
#IBAction func plusButton(sender: UIButton) { // Plus Button
indexCrow.frame = CGRect(x: indexCrow.frame.origin.x + 20, y: indexCrow.frame.origin.y, width: indexCrow.frame.size.width, height: indexCrow.frame.size.height)
crow++
counter.text = String(crow)
}
If I remove the line counter.text = String(crow), my image view moves correctly, but my label does not update. If I write counter.text = String(crow) my label updates, but my image view does not move.
What I do wrong?
AutoLayout is running when you update the label and placing your image back to where it started. You have several options to deal with this. Choose one:
Turn off AutoLayout. Most don't choose this option because they want their layouts to work on multiple devices.
Create your imageView programmatically instead of in Interface Builder. If you do this, it won't be subject to AutoLayout and you can move it freely.
Place your imageView using AutoLayout constraints. Add IBOutlets to those constraints and update the constant values in code instead of modifying the frame.
When plusButton is called, store the new frame for your imageView in a property in your ViewController, and then put that frame in place in an override of viewDidLayoutSubviews which happens after AutoLayout runs.