Animate from zero height to dynamic destination height in fixed time with react native - react-native-web

This question differs from some similar question in that I want to go from 0 to the height that would be determined by nativeEvent.layout.height - if it wasn't being animated - in duration of say 500ms.
This works on web. On iOS device it gets a smaller than final height from the layout event because the animation is not completed
Right now I'm getting the destination height from the native Event layout and running the animation to the layout height as soon as that happens, this causes multiple animations to occur which brings about the intended height but no longer in 500ms, more like a few seconds.
Animated.timing(
cardHeight[index],
{
toValue: newHeight,
duration: 500,
useNativeDriver: false
}
),
What I'd like to do is use something like scrollHeight or innerHeight of the element which remains the same regardless of what actual height it is but this obviously isn't available on device.

My answer was to put the content whose height to measure using the layout event within a scroll view and then taking the event on the scroll views contents.

Related

SwiftUI Button height on watchOS

On iOS by default if you add the button in SwiftUI its size is equal to the size of the text. Setting the padding to some value expands the size to be bigger than the text by that value.
On watchOS by default the button has the text and background with applied padding. I don't see any way to reduce that padding (to make the button height closer to the height of the text). I have tried with setting padding and frame but it doesn't appear to be helpful - it appears even counter intuitive as increasing the padding reduces the height of the visible button but it keeps the overall size of the button in the layout which still isn't helpful.
Just to note that with storyboards this reduction of height is possible so I would assume that there should be a way in SwiftUI.
Set the button’s buttonStyle(:) to PlainButtonStyle() and you’ll have full control over the padding and frame. The downside is that you no longer get the default button background, so you’ll need to recreate it if you need it.

UIScrollView contentLayoutGuide and zooming centered

The problem to be solved here is how to zoom in a UIScrollView while staying centered. If you don't take some sort of precautions, the default is that as we zoom out, the zoomed view slides up to the top left corner of the scroll view, like this:
So how to prevent this, and keep the zoomed view in the center as we zoom? As you probably know, there are traditional ways of handling this by messing with the scroll view's layout, as described by Josh and Eliza in the brilliant classic WWDC video 104 from 2010. This can be done by using a delegate or by subclassing UIScrollView, and gives the desired result:
Now comes WWDC 2017 video 201 (https://developer.apple.com/videos/play/wwdc2017/201/?time=1496), and there's Eliza making a claim that the new (iOS 11) contentLayoutGuide solves the problem of zooming while staying centered in a new way: she says to center the content view at the center of the content layout guide.
But she doesn't demonstrate. And when I try it for myself, I find it isn't solving the problem. I'm zooming in just fine, but when zooming out, so that the zoom scale is smaller than 1, the content view moves up to the top left, just as it always has.
Has anyone figured out what this claim in the video actually means? How does iOS 11 make it easier to zoom centered than in the past?
EDIT I actually received a sample project from Apple in response to my bug report, which they claimed illustrated how to solve this, and it didn't! So I conclude that even Apple doesn't know what they're talking about here.
The view goes to the top left because the contentSize of the scroll view is not defined. When using the new Auto Layout guides in iOS 11, it's still necessary to define the contentSize.
Add the following constraints:
scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
scrollView.contentLayoutGuide.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor)
This worked for me, when I had a contentView with a fixed width/height and the following additional constraints:
// give the centerView explicit height and width constraints
centerView.widthAnchor.constraint(equalToConstant: 500),
centerView.heightAnchor.constraint(equalToConstant: 500),
// pin the center of the centerView to the center of the scrollView's contentLayoutGuide
centerView.centerXAnchor.constraint(equalTo: scrollView.contentLayoutGuide.centerXAnchor),
centerView.centerYAnchor.constraint(equalTo: scrollView.contentLayoutGuide.centerYAnchor)
This is the solution you are / everybody is looking for. In my case I want to center a view inside a table view scroll view. So if the table view scrolls the custom view will always be in the center of the scroll view content.
// create a view
let v:UIView = UIView(frame:CGRect.zero) // use zero if using constraints
ibTableView.addSubview(v)
ibTableView.bringSubview(toFront:v)
v.translatesAutoresizingMaskIntoConstraints = no
v.backgroundColor = .yellow
v.widthAnchor.constraint(equalToConstant:100).isActive = yes
v.heightAnchor.constraint(equalToConstant:100).isActive = yes
// set scrollview guides
ibTableView.contentLayoutGuide.widthAnchor.constraint(equalTo:ibTableView.frameLayoutGuide.widthAnchor).isActive = yes
ibTableView.contentLayoutGuide.heightAnchor.constraint(equalTo:ibTableView.frameLayoutGuide.heightAnchor).isActive = yes
// anchor view
v.centerXAnchor.constraint(equalTo:ibTableView.contentLayoutGuide.centerXAnchor).isActive = yes
v.centerYAnchor.constraint(equalTo:ibTableView.contentLayoutGuide.centerYAnchor).isActive = yes

tvOS: Rounded corners for image view when focused

I have an image view that will get this awesome tvOS focus effect when the containing view gets focused.
The problem is - it should have rounded corners. Now this is easily done:
imageView.layer.cornerRadius = 5
imageView.layer.masksToBounds = true
I have to set either masksToBounds of the layer or clipsToBounds of the image view to true (which is basically the same), in order to clip the edges of the image - but as soon as I do this, the focus effect won't work any more, because it will get clipped as well.
I had more or less the same problem with buttons, but since the focus effect is much simpler than for the image view (only scaling and shadow), I just implemented it myself, but that is not an option for the image view, with all the effects applied (moving, shimmering, and so on...)
Is there an easier way? Did I miss something? I can't be the only trying to figure out how this works!? :)
I have found out an alternative solution. What one may do is to actually draw the image, clipping out the corners with an alpha channel. The image then gets scaled correctly when focused. That applied to the layer. Then, to have the alpha channel added to the other layers (like the one for the glowing effect) we need to set; "masksFocusEffectToContents = true".
I made an extension for it, based on this answer:
Swift 4.2
extension UIImageView {
func roundedImage(corners: UIRectCorner, radius: CGFloat) {
let rect = CGRect(origin:CGPoint(x: 0, y: 0), size: self.frame.size)
UIGraphicsBeginImageContextWithOptions(self.frame.size, false, 1)
UIBezierPath(
roundedRect: rect,
byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius)
).addClip()
self.draw(rect)
self.image = UIGraphicsGetImageFromCurrentImageContext()!
// Shadows - Change shadowOpacity to value > 0 to enable the shadows
self.layer.shadowOpacity = 0
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 10, height: 15)
self.layer.shadowRadius = 3
// This propagate the transparency to the the overlay layers,
// like the one for the glowing effect.
self.masksFocusEffectToContents = true
}
}
Then to apply the rounded corners call:
myImageView.adjustsImageWhenAncestorFocused = true
myImageView.clipToBounds = false
// masks all corners with a radius of 25 in myImageView
myImageView.roundedImage(corners: UIRectCorner.allCorners, radius: 25)
One can obviously modify roundedImage() to add the parameters to define the shadows at the calling time.
Downsides:
Borders behave like cornerRadius (they get drawn inside the image).
But I think I made it working somewhere, then investigating further I
lost the changes
I am not exactly sure this is the right way to do it. I am quite confident there must be some methods out there doing it in a couple of lines. In tvOS 11 Apple introduced the round badges (animatable and all), shown at WWDC 2017. I just can't find a sample for them.
Otherwise, tvOS 12 (beta for now) introduced the Lockup. I managed to implement them programmatically, as shown in this answer.
https://forums.developer.apple.com/thread/20513
We are also facing this same issue. When you round the corners, you can see the "shine" still has a rectange shape.
I showed the issue to the Dev Evangelists at the Tech Talks in Toronto and they said it's a bug. It's reported and open rdar://23846376
For 2022.
Note that you can just use UICardView on tvOS for the effect.
Simply put the UIImageView inside the card view.
Don't forget to actually turn OFF "adjust on ancestor focus" and "user interaction enabled" on the image view, or else it will "doubly expand" when the card view expands!
There's also a weird issue where you have to add 20 to the height of all card views to make them work neatly with and enclosed image view.

Views get corrupt when NSWindow goes to Full-screen (window's min-size violated by animation)

My main NSWindow contains UI restricted to some size range, otherwise it can get corrupt. I restrict the window to a size-range using
[myWindow setContentsMaxSize:maxSize]
[myWindow setContentsMinSize:minSize]
This works fine for user dragging of the edges or size-box.
When the user presses "fullscreen" button, Lion starts an animation that will
Shrink the window below its current size,
in several steps, increase its size until it reaches the full-screen representation size.
If the window started in its minimal size, this animation will shrink it BELOW the defined minimal size, and will corrupt my UI beyond repair (user needs to relaunch the app). My views are receiving setFrameSize: with unsupported size.
My questions
Can this be considered a Cocoa bug?
Am I doing something wrong in my view hierarchy?
Can I somehow prevent the corruption, without replacing the OS standard animation for full-screen?
Why doesn't the standard animation base on a "snapshot" of the window contents, instead of
live-resizing of the whole view-hierarchy throughout the animation? This is surely not efficient.
Is there a simple way to apply another standard transition that will
be non-destructive for me?
Can someone "spare" a few lines of code that will do a simple linear resizing animation that will NOT go below minimum?
Thanks.!
I've also investigated fullscreen animation behaviour and here is how it works:
It is also based on taking snapshots of window's content, but with some improvements. It takes several snapshots on some control points: 512, 1024, 2048 and so on.
In my case to enter full screen 2560x1440, my 400 pixels wide window took 512 pixels snapshot, then 1024 and then 2560 wide snapshot. I don't know whether this behaviour is default for all cases, but this is the result of my own investigation.
On the issue with setting min/max window size:
Minimal window size set up in Interface Builder works for me, but max constraints not. I'm currently working on it and this documented method should work for you:
Place this code into your window delegate.
static const NSSize kWindowMinSize = {100, 100};
static const NSSize kWindowMaxSize = {100500, 100500};
...
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize
{
frameSize.width = MAX(kWindowMinSize.width, MIN(kWindowMaxSize.width, frameSize.width));
frameSize.height = MAX(kWindowMinSize.height, MIN(kWindowMaxSize.height, frameSize.height));
return frameSize;
}
Hope this will help you!

Fluid layout for android

I'm targeting android but I don't know how to layout the UI so it works for all devices. How do I do this?
I have a TextField with a Button for searching and the search results are displayed below in a TableView below. So I have a table view but the bottom is cut off.
this.searchResults = Ti.UI.createTableView({
top:'70px',
height:'450dp'
});
As you can see from the code above I clearly dont know how to do this. How do you lay things out for android?
You can set top/bottom/left/right values. If you want the table to stop at the bottom edge of the screen, you could set bottom: 0. It's the same for iOS.
If I'm working on Android stuff, and I want it to resize proportionate to the size of the screen I often use percentages. So
this.searchResults = Ti.UI.createTableView({
top:'10%',
height:'90%'
});
Alternatively, If you want pin point accurate calculations, you can ask appcelerator for the platform width and height, and resize things proportionately yourself. Like so:
var height = Ti.Platform.DisplayCaps.platformHeight; //Screen height in pixels
this.searchResults = Ti.UI.createTableView({
top:'75dp',
height: (height - (75 * Ti.Platform.DisplayCaps.logicalDensityFactor)) //height - 75dp converted to pixels
});

Resources