I have a Xamarin forms page that contains an absolute layout that wraps everything. Inside that, I have content that fills the whole space and has left padding of 80, and then I have a left nav sidebar that is 80 wide and sits on top of the main content:
I want a sort of modified "push" animation, which means doing two things:
Increase the width of left nav by 100 (to 180)
TranslateX the main content by 100
(Note that using TranslateTo() would be super easy, but the left nav needs to increase in width, not shift to the right, and there's no WidthTo() method).
I can do #1 by itself just fine.
I can do #2 by itself just fine.
But I can't get them to both animate. If I run the left nav animation first (via .Commit()), only the main content animates. If I run the main content animation first, neither animates. Strange! What is going on here?
Here's the basic code I'm using:
var leftNavAnimation = new Animation(
callback: x => leftNav.WidthRequest = x,
start: 80,
end: 180,
easing: Easing.Linear
);
var mainContentAnimation = new Animation(
callback: x => mainContent.TranslationX = x,
start: 0,
end: 100,
easing: Easing.Linear
);
leftNavAnimation.Commit(this, "leftNavAnimationName", length: animationLength);
pageContentAnimation.Commit(this, "mainContentAnimationName", length: animationLength);
I figured out that the first parameter of .Commit() needs to refer to the element you're animating. So changing from:
mainContentAnimation.Commit(this, "mainContentAnimationName", length: animationLength);
To:
mainContentAnimation.Commit(mainContent, "mainContentAnimationName", length: animationLength);
Fixed it.
Related
I have a div that contains two element on top of each other :
one is a svg bar chart, where each bar is a rect with a data-test-id
the other one is an input range laying on top of the bar chart, offsetted so that the range length matches the chart width. It covers the whole graph so that receives any click event on the graph. Its opacity is set to 0.01
Here is what it looks like :
When I click on bar matched by a test-id in a cypress, I would like it to update the range value, as it works in a standard browser.
However it does not. If I try to cy.click on my rect, it does not work because it only tries to click on the rect.
I tried computing the x, y position to click on the range input but it does not work sadly :
cy.get("[data-test-id='2021-07-28T05:56:00Z']")
.as("targetBar")
.then(() =>
cy.get('[data-test-id="conversations-offset-cursor"]').as("cursor")
)
.then(() => {
const targetOffset = this.targetBar.offset();
const cursorOffset = this.cursor.offset();
const top = targetOffset.top - cursorOffset.top;
const left = targetOffset.left - cursorOffset.left;
cy.get('[data-test-id="conversations-offset-cursor"]').click({
x: top,
y: left,
force: true,
});
return cy.wait(10000);
});
But while the click is registered, and the x y coordinates seem relevant, it's as if I didn't set any coordinate at all. Here is the coordinates passed to the .click:
click 19.646743774414062 867.7333374023438
And here is the click log :
EDIT : I had mixed x and y coordinates, it clicks at the right place now, but still not triggering the event of the slider
I am using the following code to "zoom" a page in and out.
const doEffect = args => {
const screen = args.object.page.getViewById('mainScreen')
screen.animate({
scale: {
x: isSettingsShown ? 1 : .75,
y: isSettingsShown ? 1 : .75
},
duration: 2000
})
isSettingsShown = !isSettingsShown
}
There is a toggle button on the page that updates the isSettingsShown variable. However when I toggle the var before the animation has ended, it "jumps" to the end of the animation. Can I prevent this from happening? I would like to start the animation from the last position it was at.
Pausing the animation or retaining the state of animation is still an open feature request at the moment.
You may still be able to do this natively by operating on the nativeView's CALayer (iOS) / Animator (Android).
I noticed that this code doesn't quite work as expected on iOS 11, because the "adjustedContentInset" property value changes as the "navigationBar" shrinks during a scroll:
CGFloat contentInsetTop=[scrollView contentInset].top;
if (#available(iOS 11.0, *))
{
contentInsetTop=[scrollView adjustedContentInset].top;
}
////
[scrollView setContentOffset:CGPointMake(0, -contentInsetTop) animated:YES];
... For example, this might start out as 140, then reduce to 88 beyond a minimal scroll offset. This means if you call this, it doesn't actually scroll all the way to the top.
Aside from preserving the original offset in memory from when the UIScrollView loads, is there a way to recover this value later to ensure that it does indeed scroll to top consistently, no matter the "adjustedContentInset"?
Currently, there is indeed no way to do this with iOS 11, I have heard. The only way to do so is to capture the initial value and store it for the life of the navigation/view controller.
I will update my answer accordingly if I hear otherwise, but it will be broken in the base iOS 11 release forever unfortunately.
I had this same problem with a Large Title in iOS 11, and the following code worked for me.
The following code first scrolls the offset a reasonable size above where you want to be. The value -204.666666666667 was the tallest value from setting the Accessibility > Larger Text > Larger Accessibility Sizes to the highest. I'm sure this doesn't cover other possibilities, but it is working for me so far. -CGFloat.greatestFiniteMagnitude is otherwise too problematic.
tableView.setContentOffset(CGPoint(x: 0.0, y: -204.666666666667), animated: false)
This will now give you back the right adjusted content size. To avoid being scrolled too far higher, i.e. leaving white space, just use the value as follows.
var contentOffset = CGPoint.zero // Just setting a variable we can change as needed below, as per iOS version.
if #available(iOS 11, *) {
contentOffset = CGPoint(x: 0.0, y: -tableView.adjustedContentInset.top)
} else {
contentOffset = CGPoint(x: 0.0, y: -tableView.contentInset.top)
}
tableView.setContentOffset(contentOffset, animated: false)
In summary, set the offset higher first (-204.666666666667 in my case, or just -300 or whatever), then that readjusts the adjustedContentInset.top to include the Large Title, scroll bar, etc., then you can now set the content offset as needed.
The goal: Have a scroll view that displays an array of uiimageviews (photos) that you can horizontally scroll through them
How I understand to do this: Make the frame (CGRect) of each uiimageview the height and width of the scroll view, the y value to 0 on each, and set the first imgViews x value to 0. For every imgView after that, add the width of the scrollview to the x value. In theory, this would line the imgViews (Photos) up next to each other horizontally and not allow for any vertical scrolling or zooming, purely a horizontal photo viewer.
The storyboard setup: I am creating my scrollview in a xib file (It’s a custom uiCollectionViewCell), with these constraints:
— Top space to cell (0)
— Trailing space to cell (0)
— Leading space to cell (0)
— Height of 400
— Bottom space to a view (0)
—— (See Below for img)
Laying out the UIImgViews:
func layoutScrollView() {
for (index, img) in currentImages.enumerate() {
let imgView = UIImageView(frame: CGRect(x: CGFloat(index) * scrollView.bounds.width, y: CGFloat(0), width: scrollView.bounds.width, height: scrollView.bounds.height))
imgView.contentMode = .ScaleAspectFill
imgView.image = img
scrollView.addSubview(imgView)
scrollView.contentSize = CGSize(width: imgView.frame.width * CGFloat(index), height: scrollView.bounds.height)
scrollView.setNeedsLayout()
}
}
My suspicion: I suspect the issue is stemming from the auto layout constraints i’ve specified, but (considering Im asking a SO question) not sure
If there is a better way to do this (really the correct way) please let me know! I have been trying to wrap my head around this for a few days now.
I appreciate all responses! Thanks for reading
EDIT #1
I tried paulvs approach of setting setNeedsLayout & layoutIfNeeded before the "for" loop, and still no luck. Here is (out of three images selected) the second photo displaying. It seems that both the first and second photos are way longer than the content view and that would move the middle view over (Squished).
Your code looks fine except for a few details (that may be causing the problem):
Add:
view.setNeedsLayout()
view.layoutIfNeeded()
before accessing the scrollView's frame (a good place would be before the for-loop).
This is because when using Autolayout, if you access a view's frame before the layout engine has performed a pass, you will get incorrect frames sizes/positions.
Remove these lines from inside the for-loop:
scrollView.contentSize = CGSize(width: imgView.frame.width * CGFloat(index), height: scrollView.bounds.height)
scrollView.setNeedsLayout()
and place this line after (outside) the for loop:
scrollView.contentSize = CGSize(width: imgView.frame.width * CGFloat(currentImages.count), height: scrollView.bounds.height)
Is it possible to zoom in and zoom out in a view just like using a double tap or pinch functionality? If so can we still get the same coordinates or different coordinates after zooming in?
If I have a view of height 100 and width 100 and when I click on the end of the view it obviously returns y-position as 100.
Another question I have is after zoom using a pinch or doubletap, will it return the end y co-ordinate as 100 or will it return a different value since we zoomed-in?
If this is not possible, is there an an alternative?
Thank you.
You can add the view to a scrollView. When you've done this you can zoom in and out by pinching.
var scrollView = Titanium.UI.createScrollView({
contentWidth: 'auto',
contentHeight: 'auto',
top: 0,
bottom: 0,
showVerticalScrollIndicator: true,
showHorizontalScrollIndicator: true,
//Here you can determine the max and min zoom scale
maxZoomScale: 100,
minZoomScale: 0.1,
//With this property you can set the default zoom
zoomScale: 1
});
After you create this you can add your view to it
scrollView.add(view)
Hope this helps!
Tjeu