Resized UITableView's cells' frames are not updated
I have a UITableView that I resize when the keyboard shows.
// MonoTouch code
// Resize the table so it's not hidden by the keyboard
var keyboardFrame = UIKeyboard.BoundsFromNotification(notification);
var tableFrame = myTable.Frame;
tableFrame.Height = theView.Frame.Height - keyboardFrame.Height;
myTable.Frame = tableFrame;
// Bring the current cell back in view
this.InvokeOnMainThread(()=>{
if(currentCell != null) myTable.ScrollRectToVisible(currentCell.Cell.Frame, true);
});
However, when I try to perform an action on that cell that is sensitive to that cell's current position on the screen (such as attaching a UIPopoverController), I find that the frame of that cell is showing the original loca开发者_运维百科tion prior to the table resize and scrolling.
I've tried the following all yielding the same results of the frame still pointing to the old location (a lot of these were experimenting to see if they did anything not knowing what would work and what wouldn't):
- Using SetNeedsLayout on the cell, the subviews of the table, the table.
- Using LayoutIfNeeded on the cell, the subviews of the table, the table and the view containing the table
- Multiple combinations of SetNeedsLayout and LayoutIfNeeded
- Spawning a new thread, sleeping on that thread for a ridiculous amount of time (to allow time for the UI to perform a redraw/update/whatever) and then looking at the Frame
- Spawning a new thread, sleeping for that ridiculous amount of time and then calling the different layout functions
I'm not certain if it's the resize or the scrolling that is where the breakdown is happening.
When you scroll the table using a gesture, the cell frames seem to be updated properly because I can always show a popover view in the correct location relative to that cell I'm attaching it to. So I don't understand why resizing the table and scrolling it programmatically wouldn't do the same.
Does anyone know how to force a UITableView to update it's cells' frames without doing a ReloadData (ReloadData causes many unwanted effects in this case)?
This is behavior is expected. The UITableView inherits from UIScrollView. The UIScrollView, apart from its frame, has another property, ContentSize. The two are separate. While the frame represents the position and size in relation to its parent view, the ContentSize defines the area of the content of the scroll view, so that the object will "know" by what amount to scroll each time.
Changing the frame or bounds of the UITableView, or any view for that matter, does not necessarily change the frame(s) of its subviews. This behavior depends on the superview's ContentMode property.
Anyway, the table cell's frames do not change, because they are relevant to the ContentSize property. Since it is working correctly before resizing the table view, I can only assume that the ContentSize and Frame of the table view match at that point. After resizing the table view, the ContentSize remains intact so you have inconsistency between the two values.
Instead, you should use either the ConvertRectToView or ConvertRectFromView methods to get the rectangle of the cell in relation to the tableview's frame.
精彩评论