Redraw a table after animating it moving - ios6

I have an app that changes the contents of a table view cell when the user taps a button in that cell. If the cell is partially visible at the bottom of the screen, I have an animation move the table view up to display the entire cell (then move it back when done). On iOS 7, everything is fine. But on iOS 6, the shifted cell consists only of what was visible before the shift; anything that was 'hidden' behind the tab bar is blank white. I've tried calling [self.view setNeedsDisplay], and even [self.view performSelector: #selector(setNeedsDisplay) withObject: nil afterDelay: 0.5], but it still doesn't redraw correctly.
I overrode -drawRect: in the table view cell class, calling [super drawRect: rect] and set a breakpoint there, and that runs before the animation happens.
How can I get the redraw to take place after the animation?
In the custom UITableViewController:
- (void) shiftTable: (CGFloat) distance
{
[UIView beginAnimations: #"TableShift" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: 0.35];
self.view.frame = CGRectOffset(self.view.frame, 0, distance);
[UIView commitAnimations];
}

I figured out the issue:
Shifting the view via an animation like that doesn't reveal any more data. The line where it clipped the visible data is in the same position relative to the cell, and the cell is in the same position relative to the view. On iOS 7, where it draws the table view behind the translucent tab bar, the data is already there (but obscured), so when it shifts, it reveals that data. In iOS 6, the tab bar is not translucent, so the table view stops at the top edge of the tab bar. When the animation moves the view, it moves the clipped view up.
The solution is to scroll the table view, rather than just move the view:
CGRect cellRect = [self.tableView convertRect: cell.frame toView: self.tableView.superview];
CGRect tableRect = self.tableView.frame;
if (cellRect.origin.y < tableRect.origin.y)
{
[self.tableView scrollToRowAtIndexPath: cell.indexPath
atScrollPosition: UITableViewScrollPositionTop animated: YES];
}
else if (cellRect.origin.y + cellRect.size.height >
tableRect.origin.y + tableRect.size.height)
{
[self.tableView scrollToRowAtIndexPath: cell.indexPath
atScrollPosition: UITableViewScrollPositionBottom animated: YES];
}

Related

X Motif client not applying scrollbars to a RowCol widget as expected

I have a C client for X Motif that is not showing the scrollbars for a Row Col widget as expected. The main window (toplevel) has a form added to it. In the form I add a label gadget as a top attachment to the left side. Then, I add a Quit button as a top attachment to the right side.
Then I add a ScrolledWindow widget and attach it to the form as a bottom attachment to the left side. I specify the height, width and scrollbar policy value as:
sw = XtVaCreateManagedWidget("scrolled_w", xmScrolledWidgetWidgetClass, form,
XmNwidth, 575,
XmNheight, 120,
XmNscrollingPolicy, XmAUTOMATIC,
XmNscrollBarDisplayPolicy, XmAS_NEEDED, NULL);
Inside the sw widget I create a row col widget and add a bunch of buttons
to it. They are displaying fine and going in using the orientation desired.
rowcol = XmCreateRowColumn(sw, "rowcolumn", NULL, 0);
XtVaGetValues(rowcol, XmNforeground, &fg, XmNbackground, &bg,
XmNborderColor, &bord, NULL);
XtVaSetValues(rowcol, XmNpacking, XmPACK_COLUMN,
XmNnumColumns, COLS,
XmNorientation, XmHORIZONTAL,
NULL);
The issue is when I resize the main X window, I "expect" that scrollbars
should be applied to the row col window when the size of the main window is
not letting the entire scrolled window display. But it doesn't. The only
way I can get the scroll bars to show is if I rejig the XmNwidth and XmNheight
values for the creation of the window.
Any idea why this is happening?
thx.
W.

iOS 6 autolayout scrollview not scrolling with two tables

I have a scrollview with two tableviews side by side, and a bottom navigation bar.
Both tableviews should consume the entirety of the view, but scroll together if their content is too large for the screen. The two tableviews show different data of the same dataset.
When the table content is larger than the screen, or I rotate the phone to landscape, then there's no scrolling. There doesn't appear to be any scrolling at all.
I'm trying to stick with autolayout. What am I doing wrong here? The tableviews are sized to be the entire size of the view, and navigation bar is set to be 0 away from the bottom of the view. It sticks correctly, but scrolling doesn't work at all.
What am I supposed to do to get scrolling working?
UITableView is itself a UIScrollView - which means that if its interior content is larger than its size it will scroll. I've had to deal with table views inside scroll views before and I think that turning off scrolling does not force the table view to be the height of its interior content, but instead it clips it to the visible area. To get a table view to fit the interior content, you need to add a height constraint to the table view and drag it into your controller to create an outlet. Then in your controller add something like this (updated to match your constraint outlet names)
-(void) viewWillLayoutSubviews{
[self.tableViewOne layoutIfNeeded];
self.tableViewOneHeightConstraint.constant = self.tableViewOne.contentSize.height;
[self.tableViewTwo layoutIfNeeded];
self.tableViewTwoHeightConstraint.constant = self.tableViewTwo.contentSize.height;
}
Make sure that you have constraints from the bottom of your table views to the scroll view too, so that your main scroll view knows to fit the interior content.

Windows Phone 7 Scoll to Grid's first element

In my WP7 application, I have pager at the end of the page, so people can navigate prev and next.
When I call 2nd page, Grid loads with new items fine but it stays wherever user left the scroll position.
When I was using ListBox element, I achieved this like this;
ListBox1.UpdateLayout();
ListBox1.ScrollIntoView(ListBoxEntries.Items[0]);
but Grid object does not contain ScrollIntoView function. Is there any workaround for this problem?
You can programmatically change the scroll offset of the ScrollViewer like this:
ScrollViewer scroll = myScrollViewer;
Double verticalOffset = 0; //0 for top, otherwise some calculated value.
scroll.ScrollToVerticalOffset(verticalOffset);

UICollectionView reload cells while rotating

so I created my own custom layouts for my UICollectionView. When i rotate from portrait to landscape mode, some of the cells start to reload its content. I thought the layout just changes the positions of every cell not reload the content?
The content should only reload when i call reload Data on the collection view.
Any ideas to what might be going on?
Use invalidateLayout instead of reloadData on rotation, or override shouldInvalidateLayoutForBoundsChange: and return YES in your UICollectionViewLayout subclass.
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
myCollectionView.frame = self.view.bounds;
[myCollectionView.collectionViewLayout invalidateLayout];
}
Not sure if you are aiming for this, but here it goes:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
[self.collectionView reloadData];
}

ExtJS 4.0.7 scrollTo() scrolls but doesn't move scroll bar slider?

I have a tree panel and am trying to do an animated scroll to certain locations. I'm doing something like this:
myTreePanel.getView().getEl().scrollTo('top', yCoord, true /*animate*/);
The view scrolls to the correct location, but the "slider" in the scroll bar doesn't move. Any ideas why?
Some additional info: if I do the following instead, the scrollbar slider moves correctly (but of course scroll() doesn't support animation--I'd prefer to use .scrollTo() so the user can see the scrolling):
myTreePanel.getView().getEl().scroll('down', yDiff);
Thanks for any help/advice!
#MoleculeMan's suggestion of disabling the custom scrollbars (which ExtJS uses in 4.0.x but not in 4.1) does work. After doing this you can call myTreePanel.getView().getEl().scrollTo('top', yCoord, true) and everything works as expected: scrolling is animated and the scrollbar moves. The only problem is that it seems to break the ability for the view to scroll if you use the up/down arrow keys to move through the tree.
It's not very elegant, but the work-around I'm going to use is this:
// Animated scroll of tree view
myTreePanel.getView().getEl().scrollTo('top', yCoord, true);
// Wait 300ms then sync the scroll bar with the tree view
setTimeout(function() {
myTreePanel.setScrollTop(yCoord);
}, 300);
This has the cosmetic disadvantage of the scroll bar "jumping" into place instead of smoothly moving with the animation, but the benefit of not breaking the up/down key scrolling. Also, because it doesn't involve changing config params or overriding the tree view's style, I'm assuming it will still work once we upgrade to ExtJS 4.1 (i.e., the timer call to setScrollTop() will be unnecessary but shouldn't break anything).
Note that calling setScrollTop() moves the scrollbar, but also causes the view to "jump" to that position. You therefore need to ensure that the timer doesn't fire until after the animation finishes. I'm actually using some custom code to poll every 10ms and see if the destination row is visible, then calling setScrollTop(), instead of using a timer that always waits for some hard-coded amount of time:
var scrollToRowNum = 5;
var scrollToEl = getElementForNode(myTreePanel.getRootNode().childNodes[scrollToRowNum]);
var yCoord = scrollToEl.getOffsetsTo(scrollToEl.parent())[1];
// Animated scroll of tree view
myTreePanel.getView().getEl().scrollTo('top', yCoord, true);
// Check every 10ms to see if animation is done, then sync scrollbar
var timerId = setInterval(function() {
if( myTreePanel.isTreeElementWithinVisibleArea(scrollToEl) ) {
clearInterval(timerId);
myTreePanel.setScrollTop(yCoord);
}
}, 10);
The isTreeElementWithinVisibleArea() function just checks to see if element's current Y coordinate (absolute) is between the top and bottom of the tree view box.
Not surprising. They use their own scrollbar. The correct code would be:
myTreePanel.verticalScroller.setScrollTop(yCoord);
However, it doesn't support animation either. So I recommend to get rid of custom scrollbar as I've described here and use your original code.

Resources