I have been having this problem with a few of my UITextViews on my most recent project. All I have done is added a UITextView onto a ViewController and added some constraints to it. When I run my program and attempted to type in the UITextView it begins to bounce out of control. For instance, when I type the first character, the view will slide down and out of the screen. Then when I type the next few characters the textview will bounce back up to where I can see what I typed. Then I type a few more, and once again it bounces out of the screen. Has anyone else experienced this?
Also, sometimes the text will start in the middle of the UITextView.
Try add this code to textViewDidChange: method
func textViewDidChange(textView: UITextView) {
if textView.text?.characters.count ?? 0 > 0 {
let range = NSMakeRange(textView.text!.characters.count - 1, 1)
textView.scrollRangeToVisible(range);
}
}
It helped me.
Related
In my app, I show the title of an audio track in a UILabel. Based on the length of the name string, it can overflow the label (...) and not be visible.
To improve this, I'd like to have the label scroll horizontally (this is called a marquee animation elsewhere); however, I want it to only animate when the text overflows the view (so if a title is short, it would not scroll horizontally) and show the whole name.
In my view, I run:
override func viewDidLoad() {
episodeTitle.text = testName
// scroll episode name test
UIView.animate(withDuration: 12.0, delay: 1, options: ([.curveLinear, .repeat]), animations: {() -> Void in
self.episodeTitle.center = CGPoint(x: 0 - self.episodeTitle.bounds.size.width / 2, y: self.episodeTitle.center.y)
}, completion: { _ in })
}
#IBOutlet var episodeTitle: UILabel!
When I run this, it either cuts off the portion outside the view (if Line Break is set to truncate or scrolls both lines if I change Lines to 2 and set it to wrap).
Is there a way to handle this programmatically to animate the entire text string without cutting it off?
Note: I did see other questions related to marquee behavior but have not found a solution that does not require a 3P Pod to handle overflow text, hence the new question.
Can't you, instead of this, animate removing the head of the displayed text and appending on the last piece of text. i.e . instead of animating the label moving use a timer to add one character (and remove one) on each tick of the timer? You will then be guaranteed not to cut off any of the text.
So heres my issue, the 4 orange rectangles you see on the gif are a single vertical UICollectionView = orangeCollectionView.
The Green and Purple "card" views are part of another UICollectionView = overlayCollectionView.
overlayCollectionView has 3 cells, one of which is just a blank UICollectionViewCell, the other 2 are the cards.
When the overlayCollectionView is showing the blank UICollectionViewCell, I want to be able to scroll the orangeCollectionView.
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
guard let superr = superview else { return true}
for view in superr.subviews {
if view.isKind(of: OrangeCollectionView.self) {
view.point(inside: point, with: event)
return false
}
}
return true
}
This allows me to scroll the orangeCollectionView HOWEVER this doesn't actually work to fix my issue. I need to be able to scroll left and right to show the cards, however this blocks all touches becuase the point always falls on the OrangeCollectionView.
How can I check to see if they are scrolling left/right to show the cards? Otherwise if they are on the blank cell, scroll the orangeViewController up and down.
Had this issue as well... Didn't find a nice way to do it, but this works.
First, you need to access the scroll view delegate method scrollViewDidScroll(). There you call:
if scrollView == overlayScrollView {
if scrollView.contentOffset.x == self.view.frame.width { // don't know which coordinate you need
self.overlayScrollView.alpa = 0
}
}
After that, you add a blank view onto of the orange collection view. The view's alpha is 0 (I think, maybe the color is just clear; try it out if it works).
In the code, you then add a UISwipeGestureRecognizer to the view you just created and and detect whether there's a swipe to the left or to the right.
By detecting the direction of that swipe, you can simply change the contentOffset.x axis of your overlayScrollView to 0 or self.view.frame.width * 2.
Sorry I can't provide my working sample code, I'm answering from my mobile. It's not the proper solution, but when I made a food app for a big client it worked perfectly and no one ever complained :)
I am going through the Stanford Winter 2015 Swift/iOS course and while doing the assignments I run into a behavior I'd like to change.
I use Autolayout as described in the videos (making the display pin to leading and trailing view edges) and the Calculator app "Display" UILabel is fine with an initial value of 0 and whenever the value used to set it (a String) is non-nil and non "".
If it is either nil or "", the entire UILabel disappears. What I am trying to do is to "clear" the display whenever there is no value to display or an incorrect calculation resulted in nil.
Any tips on who to deal with this in general? "Clearing" a UILabel without changing it's on-screen dimensions?
Edit (thanks Rob)
The UILabel has the following constraints
1. Option-click drag-left to containing UIView, selected "leading" something (on commute to work can't check yet for exact wording.
2. Same method as (1) except that the drag is to the right edge and selecting "trailing"
3. Option click-drag up to top of view, select "vertical" menu option.
4. Same as (3) except that drag is to a UIButton underneath the UILabel on the GUI.
With those settings, the label when it contains a number is always visible and (if understand, will color it to verify) stretches across the screen even if the text doesn't.
The layout looks correct in profile and landscape as long as content of UILabel is not empty. If empty, it seems to "shrink to fit" so much that the buttons below get moved up towards the top.
I'm a C++ dev since mid 90s but I have little UI experience and no more than a couple weeks experience in iOS/Swift development.
Thanks!
You can always give the UILabel a min width and min height or constraints that holds the left and right side of the label. That should keep the label from changing it's dimensions to zero.
Use a custom UILabel class assigned in Interface Builder >> Identity inspector >> Custom Class >> Class to override UILabel intrinsic content size.
No need to create any superfluous auto-layout constraints.
Swift:
class UILabelNonCompressible: UILabel
{
private static let NonCompressibleInvisibleContent = " "
override var intrinsicContentSize: CGSize
{
if /* zero-width */ text == nil ? true : text!.isEmpty
{
// prefer mirror-and-calculate over modify-calculate-restore due to KVO
let doppelganger = createCopy()
// calculate for any non-zero -height content
doppelganger.text = UILabelNonCompressible.NonCompressibleInvisibleContent
// override
return doppelganger.intrinsicContentSize
}
else
{
return super.intrinsicContentSize
}
}
}
You will also need "How do copy for UILabel?":
extension UILabel
{
func createCopy() -> UILabel
{
let archivedData = NSKeyedArchiver.archivedData(withRootObject: self)
return NSKeyedUnarchiver.unarchiveObject(with: archivedData) as! UILabel
}
}
Check out the gif below, as you see the textview is normal. When I press the return button the top text gets clipped, when I enter a letter or press return again its fixed. After that the next return also clips the text. There is also unnecessary space created at the bottom.
Here is the code I use under UITextViewDelegate:
func textViewDidChange(textView: UITextView) {
textView.h = textView.contentHeight
contentTextContainer.h = textView.contentHeight + 20 //Unnecessary but..
}
I have a UITextView that has a fixed width and height. I pre-populate the entire textfield with blanks.
I would like to insert a character with the push of a button that will erase the last blank character, insert my string character and then place the cursor at the beginning of the newly inserted string. I am trying to achieve inserting special fonts right to left and bottom to top.
It is working with the first button push and on the second button push the new value is inserted in the correct position to the left, however, the cursor will not move to the left after the second button push, it remains to the right after the second string insert.
Here is my code...
-(IBAction)chartP:(id)sender {
NSRange currentRange = myChart.selectedRange;
if (currentRange.length == 0) {
currentRange.location--;
currentRange.length++;
}
myChart.text = [myChart.text stringByReplacingCharactersInRange:currentRange
withString:[NSString string]];
currentRange.length = 0;
myChart.selectedRange = currentRange;
myChart.text = [myChart.text stringByAppendingString:#"p"];
myChart.selectedRange = NSMakeRange(myChart.selectedRange.location -1, 0);
}
Can someone assist me with what I am missing here to continually increment to the left with my string inserts?
How about flipping the text area:
myChart.transform = CGAffineTransformMakeScale(-1,-1);
It sounds like you are trying to implement right-to-left text direction by faking it. Why not do the real thing?
Here's a question that covers the topic:
Change the UITextView Text Direction
If you need bottom-to-top entry, and you have the ability to use a custom font, perhaps you can apply a transformation to the UITextView and y-flip it. Look at the transform property of UIView. (Things like the text selection loupe may break, but it's worth a try.)