UITextView autoscroll to last line - iphone

When writing in a UITextView more text than can fit entirely inside it, the text will scroll up and the cursor will often place itself one or two lines above the view's bottom line. This is a bit frustrating as I want my application to make good use of the entire height of the text view.
Basically what I want is to configure the UITextView to write up to it's lowest part and not use it just for scrolling.
I've seen some similar questions here, here and here. However I've not seen a proper solution yet.
Thanks

I've a slightly different implementation (I want to disable scrolling), but I also had to stop the cursor jumping out of my UITextView. To do this, I implemented a null scrollRectToVisible in my UITextView subclass. Like this:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
{
// do nothing. This fixes the cursor jumping above the field defect.
}

excellent solution is in subclass UITextView add lines
-(void) setContentOffset:(CGPoint)contentOffset {
[self setContentInset:UIEdgeInsetsZero];
[super setContentOffset:contentOffset];
}
It's work!

use this
NSRange myRange=NSMakeRange(outPutTextView.text.length, 0);
[outPutTextView scrollRangeToVisible:myRange];

if I understand right, you can use
[textView setScrollEnabled:NO];
to disable scrolling. what about not to type when the cursor reached the lower margin... maybe it is not good solution but you can add some threshold value(maximum characters in the [textView text]) and return NO in
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
delegate method of UITextView if [[textView text] length] > maxCharacters.

I find seem the property 'contentOffset' also can be use ...

I've got the last line by setframe :
You can setframe to about a line height
When you are editing, in - (BOOL)textView:shouldChangeTextInRange:replacementText:,use scrollRangeToVisible:,the argument is selectedRange
When you end edit, setframe to the original size

Related

UITextField cursor back movement

I want to prevent cursor back movement in UITextField. or I need to prevent entering text between two characters which is already entered.
How can I do this?
There is no property or method to prevent the user from using the magnifying glass on a particular text field. You can try to block all the characters inside the string:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if(range.location < textField.text.length) return NO; else return YES;
}
After some research, I found this question: Disable Magnifying Glass in UITextField. The author of the accepted answer says there's a way to do it:
You can also set userInteractionEnabled to NO so that the user can't
tap the field. Call becomeFirstResponder manually so that the field
gets focus since the user can't tap to focus.
But, as I found out, it doesn't work, since setUserInteractionEnabled:NO prevents the text field from becoming the first responder. After the second research I found another question: Show UITextField keyboard on firstResponder even when userInteractionEnabled = NO. MaxGabriel user claims he found the way to do it:
What I do is add that hidden text field to the view, and call
becomeFirstResponder on it. The user has no idea this text field
exists. In the delegate callback from the text field, I take the text
the user typed in and add it to a UITextView (though you could add the
text to whatever you wanted, like a UITextField like in your
question). I turn off userInteractionEnabled for the visible text
view. This creates the effect you desire.
Stack Overflow is a huge database, a little bit of research before asking a question may help you in the future.
For stopping entering text in UiTextField, you should use uitextfield delegate method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Set tag for a textfield
if(textField.tag==10)
{
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength < [textField.text length]) ? NO : YES;
}
}
Modify the logic as per your requirement.
For preventing entering text between two characters Use NSRange and textfield text of range is less than textfield text length then return No then text will not be entered in UITextField
You cannot prohibit caret moving, but you can use UITextFieldDelegate's method textField:shouldChangeCharactersInRange:replacementString: for testing if text was typed inside already typed string, if it's not then change text in textfield manually and move caret to the end with the help of selectedTextRange property of UITextInput protocol.

Assign Some Text to particular line in UITextView Programmatically

I create an instance of UITextView programmatically. I want to assign some text to particular line in UITextView programmatically. Here is my code to create UITextView.
UITextView *textView =[[UITextView alloc]init];
textView.frame=CGRectMake(0,0,282,210);
[textView setReturnKeyType:UIReturnKeyDone];
[self.view addSubview:textView];
For example I want to add some text to particular line (at the end of line 5).
Programmatically, how is it possible to do this?
UITextView *textView =[[UITextView alloc]init];
textView.frame=CGRectMake(0,0,282,210);
textView.text = #"xxxxxx";
...
You can't edit lines directly in the text view because the number of lines depends on the content size and the size of the font.
Check this question as a reference:
How to Read Number of lines in UITextView
You could do some calculation to determine where to insert the text, but I'm nor sure if that's the best way to go around. There is probably a better way to accomplish what you are trying to do.
you can use the following:
NSString *str=yourTextview.text;
[str stringByAppendingString:yourNewString];
Then add it to textview
yourTextView.text=str;
check it and let me know if any clarification you need

How I update a scroll view?

I, sorry for my english I'm not very good, I code in objective-c, I try to set text in a uiscrollview and update the content of the scrollview right after. I have a loop and I set the text with the method [uiscrollview setText:] in that loop, but the text is only displayed in the scrollview at the end of the loop...
thanks
Alex
Since when the UIScrollView has a text property?.. Do you mean UITextView?
If the loop is in main thread then the UI will probably be updated only after completing the method (with the loop inside) - just like you write. Possible solution might be to execute the method with the loop in the background thread (e.g. [self performSelectorInBackground:#selector(updateScrollViewInLoop) withObject:nil];) and inside the loop update the scroll view in the main thread ([uiscrollview performSelectorOnMainThread:#selector(setText:) withObject:text waitUntilDone:YES];).
You might also add [uiscrollview setNeedsDisplay]; line right after updating the text. I'm not sure it will help because of the second point above and, in addition, I think that this line is called in the background anyway once you change the content of the scroll view...
You first need to build your string, then call set text. Set text first clears the existing text. Also, I am assuming you mean UITextView (a subclass of UIScrollView) as it has a 'text' property. Try:
NSString *text = [NSString string];
for (NSString *line in lines)
{
text = [text stringByAppendingString:line];
}
[self.textScrollView setText:text];

A word-wrapping text field with an image background on the iPhone?

Does anyone know how to create a text field that has a UIImage background and does word-wrapping?
It appears that word-wrapping is not available on UITextField, while a background image is not available for UITextView! Also, it should change the size of the control or at least alert that the number of lines changed so that a delegate could change its size..
An example of such control is the input field for messages in the SMS application.
Edit: the code should also get the text field to always show the text being edited. Apparently, when UITextView changes size while editing it somehow loses focus on the current text.
Thanks ahead!
Aviad.
Word-wrapping is not available on UITextField because UITextField only supports single-line text.
Use a UITextView. Make textView.backgroundColor = [UIColor clearColor]. Add the UIImage first, then the UITextView on top of it. Make sure the sizes are correct, and you should be fine.
As for changing the size of the UITextView, in your UITextViewDelegate, do something like this:
- (void)textViewDidChange:(UITextView *)textView
{
NSString *s = textView.text;
CGSize testSize = CGSizeMake(textView.frame.size.width, NSIntegerMax);
CGSize neededSize = [s sizeWithFont: textView.font constrainedToSize: testSize lineBreakMode: UILineBreakModeWordWrap]; // or UILineBreakModeCharacterWrap?
if (neededSize.height > testSize.height)
{
// grow textView
textView.frame = CGRectMake(textView.frame.origin.x, textView.frame.origin.y, neededSize.width, neededSize.height);
// then adjust the image size -- something like this
imageView.frame = textView.frame
}
}
Eventually I wrote my own code, which worked to some degree with a lot of workarounds (changing the focus for example, resizing when removing all the text again, etc). If anyone's interested, I'll post the code.
In other news, just today I saw in a different question around here something called IFVerticallyExpandingTextField. The name was promising, the code is here, and I'll give it a look. Anyone with a similar problem, you might want to see this too.
My mistake, I didn't read it carefully enough: IFVerticallyExpandingTextField is for the Mac, not the iPhone.

How to make a custom drawn UITableViewCell resize properly?

For performance reasons, I draw the strings for my UITableViewCell in a custom view that overrides its drawRect method to draw strings directly in the view rectangle using NSString:drawInRect. This is similar to Apple's TableViewSuite Example 5-CustomTableViewCell.
However, when I invoke setEditing on the cell to bring up the delete button, the view ends up with a squeezed appearance after the animation completes. To demonstrate this, invoke setEditing:YES on the CustomTableViewCell example mentioned above and observe the distortion. Is there any way around this or should I just revert back to using UILabels for my text?
I had a similar problem with a UIView inside a UITableViewCell. I solved it by changing the UIView's contentMode to UIViewContentModeLeft. (I wrote it up here, with screenshots.)
I had this problem too, and in my case I fixed it by handling the 2 states in my drawRect method, one while editting, the other while not. In other words I accounted for the size of the delete button, and got my UI to repaint the cell differently. I'm not sure if it's the most efficient way to go, but here is the code that I used to force a repaint:
-(void)_refreshTableAndCells{
//refresh the table
[myCustomTableView reloadData];
//refresh all the visible cells
for (UITableViewCell *cell in myCustomTableView.visibleCells){
LocationCellView *locationCell = [cell.contentView.subviews objectAtIndex:0];
[locationCell setNeedsDisplay];
}
}
I'm an Objective-C n00b though, so I'd be more than happy for someone to suggest a better way than this.
I usually just modify the x and width values (or whatever else) of whatever I want to be different when editing or not. UITableView automatically calls layoutSubviews when you begin editing, so you don't have to loop through your cells and do it yourself.
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat editingPadding = 5.0;
self.textLabel = CGRectMake((self.editing ? self.textLabel.frame.origin.x + editingPadding : self.textLabel.frame.origin.x), self.textLabel.origin.y, (self.editing ? self.textLabel.frame.size.width - editingPadding : self.textLabel.frame.size.width), self.textLabel.frame.size.height);
}
Try setting the contentMode of your own custom view (which resides inside the cell's contentView) to UIViewContentModeLeft. The "squeezing" is due to the fact that the default contentMode is UIViewContentModeScaleToFill.