Update - I now believe this is due to me calling [view.details scrollRangeToVisible:NSMakeRange(0, 1)]; too early--meaning before the constrains have been applied and layouts recalculated.
I figured this much out by calling the scrollRangeToVisible after the view was shown and after I took some action on the cell. (This would guarantee that all layout changes were complete before I made that call.)
Thus, what I need to know now is Where should I make this call? such that it occurs after the layouts?
Original Post
I've tried many solutions, but none of them seem to work.
I have a UITextView as a subview to a UIView -- a container for the text view plus a few other items. When a user clicks on a cell in a tableView, I pop up the UIView container to show more details--the full text.
Configuring the view, I set the textView.text value to my long string, I update the font, I set the color, and I show the container view. Unfortunately, it shows the text at the bottom of the textview rather than at the top.
I've tried the following solutions, to no avail--each one results in the same behavior as above: it still shows the text at the bottom of the textview.
Attempt 1: scrollRangeToVisible
[self.textView scrollRangeToVisible:NSMakeRange(0,1)];
Attempt 2: contentOffset (tried each of the following, but none work)
[self.textView setContentOffset:
CGPointMake(0, -self.textView.contentInset.top) animated:YES];
[self.textView setContentOffset:CGPointMake(self.textView.contentOffset.x, 0)
animated:YES];
[self.textView setContentOffset:CGPointMake(0, self.textView.contentSize.height-textView.frame.size.height) animated:YES];
Am I fishing with those last items? Yes. I've run out of ideas. I've checked the values of contentOffset.y and contentInset.y -- both are zero.
I create the UITextView in a subclass of UIView called PrayerPopupView. Here's the process:
In my main UIViewController where the table exists, a user touches a cell. Based on this action...
I create an instance of PrayerPopupView in this view controller
In the creation of this view, the UITextView is created
The textView.text value is set.
I call `[self.details scrollRangeToVisible:NSMakeRange(0, 1)];
I use a custom class (KLCPopup) to add the view to the UIWindow but I also tested by adding my PrayerPopupView directly as a subview of the view controller rather than using KLCPopup, just in case it mattered. Both yield the same result of text not scrolled to the top correctly.
Since adding the scrollRangeToVisible didn't work in the custom view itself, I also added it in the UIViewController before showing the PrayerPopupView ([prayerPopupView.detailsTextView scrollRangeToVisible:NSMakeRange(0, 1)];), and still the same result.
Here's a screenshot of the view:
Here's a screenshot of the view properties in the debugger:
This shows the view hierarchy in the debugger:
Related
I am having trouble getting a uilabelview to always display on two lines. When the page first loads, the text only uses one line and is truncated. Once you load another view controller on top of it--for example an edit VC and then cancel the second VC, the label does flow to two lines which is what I want. However, I cannot get it to do first time.
Can anyone suggest what is issue? What could be different between the VC at first and then after you have shown and canceled another VC on top of it.
The label is created in storyboard. It is reference in code in viewwillappear as follows:
_myLabel.numberOfLines = 0;
NSString *nameToDisplay = _myItem.name;
[_myLabel sizeToFit];
[_myLabel setNeedsDisplay];
I have a few UIButtons inside UITableViewCells, and all of them are missing default tap animation, however if I long press - animation works. I've found some solutions, like setting type to .system, showsTouchOnHighlight = true, but none of them have helped. What is the problem here?
It's not a "problem" - it's by design.
When you have an object such as a button in a table view or scroll view or collection view, and you "touch" it, the system needs to know whether you are tapping the button or if you want to touch-and-drag to scroll the view that contains the button.
So, the table view (really, the "scroll view part" of the table view), waits to see if you drag your finger or not before it performs any actions.
If you want the button to respond immediately to a touch, you need to set
delaysContentTouches = false
on the containing scroll view(s).
If you search for uibutton inside uitableviewcell delaysContentTouches you should find plenty of discussion on this topic, and various approaches to change the default behavior.
For this problem you can add extension to UIButton and override some methods.
You can check my answer here
Problem
I'm trying too make a custom search text field, added to a UITableViewController, always stick to the top of the page.
Like this:
Everything works fine, but when I tap the search text field to becomeFirstResponder the tableView strangely scrolls down.
I have discovered that this only happens when I manually setts the contentInset for the UITableView. (So that the tableview section headers don't hides behind the search view)
How I have built it
Layers:
TableView
UIView (as UITableView.tableViewHeaderView)
UIView (to update the frame when the user scrolling the tableView)
UITextField (for search input)
Code for fixing the search view frame when user scrolls:
var rect = frame
rect.origin.y = scrollView.contentOffset.y + 64
frame = rect
I may be doing everything stupid, but I would like to have the view stick to the top, because the user will use search more than other apps. Any ideas?
My app requires iOS 8 so I have not been available to test this on iOS 7. I can make a screen recording if that helps.
UPDATE
I've created an example project with the same objects I'm using in my main project.
https://www.dropbox.com/s/qdlx0milebbuf3p/Search%20bug%20Example.zip?dl=0
It's a UIKit bug. To fix this I've created a subclass for UITableView to NEVER change the content offset when isScrollEnabled is NO.
.h
#interface CUISearchTableView : UITableView
#end
.m
#import "CUISearchTableView.h"
#implementation CUISearchTableView
- (void)setContentOffset:(CGPoint)contentOffset {
if (self.isScrollEnabled) {
[super setContentOffset:contentOffset];
}
}
#end
I'm not sure you need to do all that. If you'd just use a UIViewController and add a UITableView to that, then you could place the UISearchView anywhere ( i.e., the top of the view ). You just need to make sure that the UISearchView is the top-most view ( bring subview to front ).
I get that you're using a UITableViewController, but if you want to use your own search view instead of the TableViewController+Search then this is your best bet. The only thing that would be necessary is adding the top content offset ( which you're already doing ). you could then just delete the CUISearchTableView.
Does this make sense or am I missing something?
I normally post source code and examples of UI but I think its more related to an iOS7 change and I cant see it being a code bug (yet). I would have to post so much code and UI that it would be counter productive. So here is my best non-visual description:
Since upgrading a project to iOS7 I am finding that if I put call to change a UILabel or calling setText of a UIButton in a ViewDidAppear or ViewWillAppear it puts the new text right on top of the old text.
Since developing for iOS I have never had to do anything different. If I do this:
lblMyHours.text = #"12";
It shouldnt just throw that on top of my existing label.
This especially happens inside of a UITableView where I have created an iVar for a UILabel thats in a UITableViewCell. If a user makes an adjustment to a value after clicking on a cell (it takes them to a detail screen to edit), when I pop back I have it recalculate in ViewDidAppear. In that recalculating I am resetting a label like the above. But it doesnt clear out the old.
You might be adding a new label every time you return a new cell.
You should just replace the text of the current label instead.
There are two way to achieve this, one you are already doing and as #Guilherme rightly pointed out. The other way is to create a custom tableview cell and put the UILabel property in there. As for the viewDidAppear scenario, you can create a uilabel in ther .h file (in the #interface declaration) and then initialize it in ViewDidLoad method and simple use in ViewDidAppear method without having to declare it again.
I would suggest that you follow the way I described for ViewDidAppear issue, and for the UITableView issue, search for UILabels in subview of the cell everytime cellForRowAtIndex method is called and remove it from the subview, something like this before adding a new label
for(UIView *view in cell.subviews)
{
if([view isKindOfClass:[UILabel class]])
{
[view removeFromSuperview];
}
}
Hope this helps.
I'm currently building a app using UIPageViewController. It is working as I expected until it reaches last page which contains numbers of UITextField.
But when I tapped one of instances of UITextField, it suddenly jumps to the previous page without any reason instead of showing a keyboard. When I scroll through to the last page and tap a text field again, it works well without any problem.
It is also fine when it shows last page immediately by tapping the navigation button that links to the last page and that is attached to the UIPageViewController instance.
This problem happens only when I scroll through pages from first to the last, and it happens only once at the first try.
I suspected low memory issues, so I set breakpoints in -didReceiveMemoryWarning method of both UIPageViewController instance and the last page view controller. But they were never called.
The second try is that I added a breakpoint in the last page view controller's -willMoveToParentViewController: method and set its condition to parent == nil(when it's removed from parent view controller, which is the UIPageViewController instance in question)
When I run the app, the breakpoint's call stack says that the method is called by UIPageViewController's -_flushViewController:animated:.
I don't know why this -flushViewController:animated: is called. If I can figure out the cause, it will help me with fixing the problem.
Is there anybody who can help me?
I'm not sure what it is in your code that does this, but one probable approach in debugging this is to try and catch the UITextField's UIKeyboardWillShowNotification event to check if it's firing properly.
Also try to set a breakpoint at your page's viewWillAppear event to inspect if all of the UITextFields have been instantiated properly -- I would suspect that at the point where you tapped the first text field not all of them have instantiated yet, meaning that the object receiving the tap action will be your UIPageViewController instead of the UITextField.
I found the answer here:
Cannot Impliment UITextview inside a UIPageViewController
Credit goes entirely to him.
I can confirm that it works. Here is what I did in my view controller:
//TextField
UIScrollView *textFieldScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
textField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, width, height)];
[textField setText:#""];
[textField setBackgroundColor:[UIColor whiteColor]];
[textField.layer setCornerRadius:5.0f];
[textField setDelegate:self];
[textFieldScrollView addSubview:textField];
[_someView addSubview:textFieldScroll];
Works like a charm. Let me know if you have any more questions.