Animating Collection View Cells in iOS - ios6

When my view controller's view appears, I would like all of the cells in its collection view to flip horizontally.
How can this be done? I looked into UIDynamics and didn't find a flip animation. I've got an animation using Core Animation that will flip a view and I don't know how to apply it to the cells.

You can use this method in a subclass of UICollectionViewFlowLayout:
- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath
{
UICollectionViewLayoutAttributes *layoutAttributes = [super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath];
CATransform3D transform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(180.0), 0.0, 1.0, 0.0);
layoutAttributes.transform3D = transform;
return layoutAttributes;
}
What this basically does is grabs the initial layout attributes of your collectionViewCell and has it flipped horizontally. On insertion of cells, flowLayout will do a linear animation from these initial attributes to the original attributes of that cell. This method will get called if you call
- (void)performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion;
and pass in your insertion using
- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths;
into the update block.

Related

Depth issue with infinite grid in opengl 3.3 with glsl

I'm following this article, using sokol_gfx with opengl core 3.3 profile. The grid renders, is transparent, is rendered after other objects in the scene, and blending is enabled.
When the camera is close to objects the grid will render behind them, however, as the camera moves away the grid will render in front of the objects. Also, when the camera is close to objects the grid doesnt render behind them when it should, it penetrates the object a little and then becomes transparent.
Here is an image showing the grid rendering on top of an object it should not, but also rendering behind an object it should. Both of the cubes are above the grid, it should be rendering behind both of them.
Depth
And here is an image showing the grid rendering past where it should. The bottom of the cube is on the same plane as the grid, the grid should stop at the edge of the cube, not go in a little ways and then stop.
Too much grid
Depth calculation from grid fragment shader:
float compute_depth (vec3 position) {
vec4 clip_space_position = frag_projection * frag_view * vec4 (position.xyz, 1.0);
return (clip_space_position.z / clip_space_position.w);
}
The full project is located here
I had the same issue. The problem is that the article is written for Vulkan, which handles the depth differently from OpenGL.
After reading GLSL gl_FragCoord.z Calculation and Setting gl_FragDepth I managed to solve the issue by modifying the fragment shader like this:
float compute_depth (vec3 position) {
vec4 clip_space_position = frag_projection * frag_view * vec4 (position.xyz, 1.0);
return 0.5 + 0.5 * (clip_space_position.z / clip_space_position.w);
}

Resize custom UITableViewCells (SubViews) on Orientation iOS6

# I have a UITableView with custom UITableViewCells. My views are autorotated on orientation as I have implemented the ios6 orientation methods.
# I am not using xib file and drawing all the contents programmatically (imageView,label).
When I rotate my device the tableView and Cells are rotated but cell subviews are not proper in terms of size and position.
# So how to resize the current cells being drawn on the TableView. As the cells are drawn asynchronously and not all at once, how to apply resizing ?
# Do I need to apply AutoResizingMasks or NSLayoutConstraint ? My TabBar and NavigationBar are properly resized but cells are not.
***Plz note: I have not added any block of code, bcoz I simply dnt understand how to proceed as for already drawn cells and those being drawn dynamically after objectForRowAtIndexPath.
I have found the answer. As for orientation in ios6, there are many links for implementing new methods.
Initially my views were not supporting rotation till I found that my tabBarController was a RootViewController for the app so I added (BOOL)shouldAutorotate
{return YES;
} in my subclassed TabBarController class
and in my info.plist added key value pairs for supported interface orientations, this values will be global to the application unless you specify exceptions in current UIViewController via - (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
For implementing rotation in UITableView, I called reloadData(); via using - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self.tableView reloadData];
}
Its not necessary to write a custom UITableViewCell Class, as you can redraw cells in – tableView:cellForRowAtIndexPath: method. As I already had a custom UITableViewCell Class I draw new cells in layoutSubviews(); by getting [[UIApplication sharedApplication] statusBarOrientation] method. If you have any custom UIViews inside the cell you need to redraw the rect to support the landscape mode. Basically I am also supporting ios5 so I am not using AutoLayout via XIB. You can also use autoresizing masks to each subviews as per your layout frames.
reloadData(); is not expensive to memory as you don't call for all the cells # the same time and only the visible cells in the UITableView are redrawn and cells are reused as before.

WPF shape geometry scaling without affecting stroke

I am wondering if someone has managed to override the default behaviour of the WPF shape rendering when applying a scaletransform to the shape. The default behaviour transforms the entire shape drawing, including strokes, but I would like to only scale the geometry. The difficulty is that my shapes reside in a visual hierarchy with render transforms applied on different levels (sort of like a 2D scene graph but a WPF visual tree), this I cannot change(!). I have read in different places that it might be possible to create a custom shape to cancel out the transform for the render transform and put it on the geometry instead. At the moment I have something like:
public sealed class MyPath : Shape
{
// This class has a Data property of type Geometry just like the normal Path class
protected override Geometry DefiningGeometry
{
get
{
Geometry data = Data;
if (data == null)
{
data = Geometry.Empty;
}
return data;
}
}
protected override void OnRender(DrawingContext drawingContext)
{
Transform tr = RenderedGeometry.Transform;
Geometry geomToDraw = RenderedGeometry.Clone();
geomToDraw.Transform = new MatrixTransform(tr.Value * tr.Value);
Matrix trInv = tr.Value; trInv.Invert();
drawingContext.PushTransform(new MatrixTransform(trInv));
drawingContext.DrawGeometry(Brushes.Transparent, new Pen() { Brush = Brushes.Black, Thickness = 1 }, geomToDraw);
}
}
As is clearly evident, I am quite new to this and the above code is probably completely messed up. I was trying to transfer the matrix to the geometry without changing the final resulting geometry transform, hence the tr.Value*tr.Value and trInv. But it does not work as I want it to. I know this transfer transform technique works in theory because I tried it out with constant transforms (testing to set Geometry.Transform to scale x with 4 and pushing a transform to scale x with 0.25 worked fine but the resulting shape drawing did not seem to apply stretch=fill, which I rely upon). So there must be something that I am missing with the render transforms.
The test scenario that is not working is this:
I apply a render scale transform with scaleX=4 and scaleY=1 in xaml.
The built-in Path class scales the entire drawing so that strokes 4 times wider in the x direction than in the y direction.
I want MyPath to scale the geometry only, not the strokes. <- THIS IS NOT WORKING!
What happens is: The geometry gets scaled correctly, the strokes get scaled by 4 in the x direction and by slightly less than 4 in the y direction. What is wrong? I have a feeling that I should not be working solely with RenderedGeometry.Transform but what should I use instead? I need to incorporate the render transform and the stretch=fill on the shape. My render transforms hierarchy may contain a mix of scales, rotations and translations so the solution must be general enough to handle any transform, not just axis-aligned scaling.
Note: I know it is bad to create the geometry in OnRender but I want to get it working before spending time cleaning it up.
By the way, I read this post:
Invariant stroke thickness of Path regardless of the scale
The problem as stated before is that I do have to take render transforms into consideration and I am not sure of how to adapt that solution to work with them.
If I understand the question correctly you want to cancel out the effect of the render transformation on the pen but not on the geometry.
This could be accomplished by getting the transformation of the control relative to the item from which you want to cancel the transform an using its inverse to cancel out the effect on the pen. (so for example if you have the hierarchy P1/P2/P3/UrShape, and P1,P2,P3 all have transforms on them and you want all of them to not affect your pen, you will need to obtain the transform of P1 relative to UrShape). Then you could reapply the transform to just your shape.
var brush = new SolidColorBrush(Colors.Red);
var pen = new Pen(brush, 5);
//Instead of the direct parent you could walk up the visual tree to the root from where you want to cancel the transform
var rootTransform = (MatrixTransform)this.TransformToAncestor((Visual)this.Parent);
var inverserRootTransform = (MatrixTransform)rootTransform.Inverse;
//We cancel out the transformation from the parent
drawingContext.PushTransform(inverserRootTransform);
var renderGeometry = this.Geometry.Clone();
// We apply the parent transform to the shape only, and group it with the original transform that was present on the shape
// we do this to honor any transformation that was set on the shape.
renderGeometry.Transform = new TransformGroup()
{
Children =
{
rootTransform,
this.Geometry.Transform
}
};
//We draw the shape, the pen size will have the correct size since we canceled out the transform from the parent
// but the shape now has the transformation directly on it.
drawingContext.DrawGeometry(brush, pen, renderGeometry);
drawingContext.Pop();

Replacing the default UICollectionViewCell deletion animation

I have a collection view whose layout is managed by a UICollectionViewFlowLayout instance. I have a long press gesture recognizer attached to the collection view whose job is to detect if a long press occured within the bounds of one of the cells in the collection view and if so, delete that cell after changing the cell's transform animatedly.
This is the relevant part of the action performed by the gesture recognizer:
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:2.0 animations:^{
cell.layer.transform = CATransform3DMakeScale(1.0, 0.0, 1.0); // an example animation - squish the cell vertically
} completion:^(BOOL fin) {
//[cell.layer removeAllAnimations];
[self.model.numb3rs removeObjectAtIndex:[indexPath row]]; // update model
[self.collectionView deleteItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]]; // delete item
}];
The problem is that the deletion method seems to perform its own property change/animation on the cell which doesn't gel well with my animation. For instance, in the effect I'm trying to achieve here, once the cell is completely squished vertically, I'd like it not to show itself in the view again, but the deleteItemsAtIndexPaths: call causes the cell's "ghost" to show up and then fade out as the method performs its own transform and opacity animation.
Am I approaching it completely wrong? Possibly the collection view architecture offers a better way to do what I want, rather than explicitly animating the cell and then deleting it like I'm trying?
I'm hoping I might be able to get a quick answer here rather than have to dig into the documentation too deep.
I asked this question on the Apple Developer Forums, and was informed of the
-finalLayoutAttributesForDisappearingItemAtIndexPath:
method which is part of the UICollectionViewLayout class.
Anyway, by subclassing UICollectionViewFlowLayout and overriding this method, I was able to modify the attributes of the cell I was deleting - in particular, the transform.
One thing to note is that this method gets called not only for the cell being deleted but also for cells being shifted from their position during the relayout. But it's simple enough to write code to keep track of the cell being deleted and only modified its attributes.

Animate ListBoxItem from one ListBox to another ListBox

I would like to create a visual effect when an item in a listbox is double clicked. So far I have drag and drop functionality where the item is visually attached to the mouse and can be moved to a drop target. From that functionality I am able to animate the item using the same logic of getting the item container, however I am not able to leave the items control. Is there any way to remove the item from the ListBox and visually animate it to another location? Basically the main list box is a hand of cards. When a card is double-clicked I want it to visually move from the hand listbox to a discard listbox. As of now, the logic for moving the item from one collection to another is no problem, however I would really like an animated visual representation of this event. Any ideas or references on how to do something like this would be appreciated.
Thanks,
Brandon
Further Details on what I have attempted:
There are some concepts that I do not yet have a strong grasp of yet, which has led me to run face first into this wall. I have a method that I pass in(some may be unnecessary) the ListBox as an ItemsControl, a FrameworkElement that is the listbox item, and the data object associated with the ListBox item. What I attempted to do was FindVisualChild of the ListBoxItem that is a canvas. I can do that. In my mind I was wanting to somehow clone the canvas either as a canvas or as a bitmap, add it to the children of the child of the page in the same location, remove the ListBoxItem from the ListBox, and animate the clone to the discard pile. When the animation completes the clone will be removed or hidden, and as that object is added to the discard pile collection it will effectively take the replace the clone.
My problem with this, is that I feel like there really is a simpler way of doing this using the adorner layer or something. I also, don't know how I would position the clone at the exact same position in the element further up the visual tree. I am going to keep working on it and researching other approaches, and I will just hope that someone will share some insight on this.
Here's some code I worked up to draw a visual to a bitmap. You may be able to adapt this to your needs, and draw the bitmap by adorning the UIElement that represents a common ancestor of the two list views. Note the use of FrameworkElement.TransformToAncestor to get the coordinates of a nested element in terms of an ancestor element.
public static BitmapSource CreateBitmapFromElement(FrameworkElement element, Double dpiX, Double dpiY)
{
Size elementSize = new Size(element.ActualWidth, element.ActualHeight);
Visual root = GetAdornerDecoratorAncestor(element);
Rect elementBounds = element.TransformToAncestor(root).TransformBounds(new Rect(elementSize));
RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)(elementBounds.Size.Width * dpiX / 96.0),
(Int32)(elementBounds.Size.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(root);
vb.ViewboxUnits = BrushMappingMode.Absolute;
vb.Stretch = Stretch.None;
vb.Viewbox = elementBounds;
dc.DrawRectangle(vb, null, new Rect(new Point(), elementBounds.Size));
}
rtb.Render(dv);
return rtb;
}
public static Visual GetAdornerDecoratorAncestor(DependencyObject obj)
{
while(obj != null && !(obj is AdornerDecorator))
{
obj = VisualTreeHelper.GetParent(obj);
}
return obj as AdornerDecorator;
}
OK, you could try taking a Visual element and setting it's background to a visualbrush of your ListItem and animate that to the other list box. You can wait for the storyboard completed event to actually do the switch. If this were me, I would animate from one box only to the edge of the other. If the switch happens fast enough it should look pretty seamless to the user. Finding the exact position of where the item is supposed to go into the list box would be pretty complex based on any sorting/filtering rules you have.
If the two listboxes are always in the same position, you could try animating the double-clicked item to a predetermined spot, let's say half-way between the old list and the new list. Then execute the code to move the item to the new list, but use a style that immediately starts an animation on that item starting it from that predetermined location and animating to its location in the new list. You'd probably have to tweak the initial offset of the new item at runtime based on where it's inserted in the list.

Resources