Wix React Native Navigation V2 - custom navigation transitions - react-native

Wix React Native Navigation V2 Custom Navigation Transition
Content moderators like myself may get tripped up on this one and mark as duplicate as there are similarly named libraries like React Navigation which have nothing to do with this.
Is there a general way to customize transition animations for push/pop? The documentation seems to be sparse and incorrect after experimenting.
The default push animation moves from right-to-left. I would like to be able to override this in some cases to left-to-right or from top-to-bottom, etc.
Doing this per push/pop doesn't seem to work either when using "animations" and the "x" or "y" properties.
Here's an example of what I've tried.
class MyComponent extends React.PureComponent {
static options(passProps) {
return {
animations: {
push: {
content: {
x: {
from: -1000, to: 0, duration: 300
},
y: {
from: 0, to: 0, duration: 300
}
}
},
pop: {
content: {
x: {
from: 0, to: -1000, duration: 300
},
y: {
from: 0, to: 0, duration: 300
}
}
}
}
}
}
}
But I've tried also per actual command and globally as well with no effect, also tried using "_" in front as some random examples show this.
I'm generally confused on how to customize due to very poor docs on this.

You probably forget enabled: 'true'. I set it globally like:
Navigation.setDefaultOptions({
animations: {
push: {
enabled: 'true',
content: {
x: {
from: 2000,
to: 0,
duration: 200
}
}
},
pop: {
enabled: 'true',
content: {
x: {
from: 0,
to: 2000,
duration: 200
}
}
}
});
and works fine

Related

QML - change how transition between pages looks

I know this is probably super basic, but I am new to learning QML and have a question about transition between pages.
In this example I have a button with which I want to switch between my 3 pages.
the transition works, but the pages always move from the right-to-the-left-side of the window.
how can I change this? I need the new page to appear as a whole right away.
(e.g. when changing from firstPage to secondPage, for the user it looks like only the AppText changes, because the button is at the same position in both cases)
code example:
App {
id: app
width: px(250); height: px(250)
NavigationStack {
Page {
id: page
navigationBarHidden: true
AppText { text: "startpage" }
SimpleButton{
x: 220; y: 0
onClicked: page.navigationStack.push(firstPage)
}
}
}
Component {
id: firstPage
Page {
navigationBarHidden: true
AppText { text: qsTr("1st page") }
SimpleButton{
x: 220; y: 0
onClicked: page.navigationStack.push(secondPage)
}
}
}
Component {
id: secondPage
Page {
navigationBarHidden: true
AppText { text: qsTr("2nd page") }
SimpleButton{
x: 220; y: 0
onClicked: page.navigationStack.push(page)
}
}
}
}
Any help would be greatly appreciated!
It looks like you're using Felgo, which I think is an extra library on top of Qt. For instance, there is no built-in QML component called NavigationStack. That comes from Felgo. You should mention that in your question to get better help with it.
I've never used Felgo myself, but just looking at the documentation real quick, it looks like you need to define a new transitionDelegate for your needs. Here is the example they give where new pages fade in/fade out.
NavigationStack {
// custom transition delegate
transitionDelegate: StackViewDelegate {
pushTransition: StackViewTransition {
NumberAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
duration: 1000
}
}
popTransition: StackViewTransition {
NumberAnimation {
target: exitItem
property: "opacity"
from: 1
to: 0
duration: 1000
}
}
}
initialPage: pageComponent
}

wix navigation [v2] showModal with custom animation type

I used to use wix navigation v1 for my projects, and I was able to set animationType within my showModal function :
this.props.navigator.showModal(
screen: 'example.ModalScreen',
animationType: 'none'
)
but in wix v2, there is no way to do so. default animation type for me is slide-up, and I don't want that. I tried setDefaultOptions with the following opitons:
animations: {
showModal: {
alpha: {
from: 0,
to: 1,
duration: 5,
startDelay: 0,
},
y: {
from: 0,
to: 0,
duration: 5,
startDelay: 0,
}
}
}
but it doesn't work at all.

React Native LayoutAnimation custom presets

We have predefined presets like this.
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
But I did not found a way to use my custom presets for example with linear type and 0.1s speed.
You can use it like this:
LayoutAnimation.configureNext(CustomAnimation)
with
var CustomAnimation = {
duration: 400,
create: {
type: LayoutAnimation.Types.spring,
property: LayoutAnimation.Properties.scaleXY,
springDamping: 0.7
},
update: {
type: LayoutAnimation.Types.spring,
springDamping: 0.7
}
}

FullCalendar and Flot Resize Conflict

I've successfully integrated both a Flot line graph and an instance of FullCalendar into my site. They are both on separate pages (although the pages are loaded into a div via AJAX).
I've added the Flot Resize plugin and that works perfectly, re-sizing the line graph as expected. However, it seems to cause an error when resizing the calendar.
Even if I load the calendar page first, when I resize the window I get this error in the console (also, the calendar does not resize correctly):
TypeError: 'undefined' is not an object (evaluating 'r.w=o!==c?o:q.width()')
I was struggling to work out where the error was coming from, so I removed the link to the Flot Resize JS and tried again. Of course the line graph does not resize, but when resizing the calendar, it works correctly.
The div containers for the two elements have different names and the resize function is called from within the function to draw the line graph (as required).
I have tried moving the link to the Flot Resize plugin into different places (i.e. above/below the fullCalendar JS, into the template which holds the graph), but all to no avail.
Does anyone have any idea where the conflict might be and how I might solve it??
Thanks very much!
EDIT: It seems that the error is also triggered when loading the line graph (flot) page AFTER the fullcalendar page even without resizing the window.... Now I am very confused!
EDIT 2: The code which draws the line graph. The function is called on pageload and recieves the data from JSON pulled off the server. When the graph is loaded, I still get the error about shutdown() being undefined.
function plotLineGraph(theData){
var myData = theData['data'];
var myEvents = theData['events'];
var myDates = theData['dates'];
var events = new Array();
for (var i=0; i<myEvents.length; i++) {
events.push(
{
min: myEvents[i][0],
max: myEvents[i][1],
eventType: "Calendar Entry",
title: myEvents[i][2],
description: myEvents[i][3]
}
);
}
function showTooltip(x, y, contents) {
$('<div id="tooltip">' + contents + '</div>').css( {
position: 'absolute',
display: 'none',
top: y + 5,
left: x + 5,
border: '1px solid #fdd',
padding: '2px',
'background-color': 'black',
opacity: 0.80
}).appendTo("body").fadeIn(200);
}
var previousPoint = null;
$("#placeholder").bind("plothover", function (event, pos, item) {
$("#x").text(pos.x.toFixed(2));
$("#y").text(pos.y.toFixed(2));
if ($("#enableTooltip:checked").length == 0) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var x = item.datapoint[0].toFixed(2),
y = item.datapoint[1].toFixed(2);
if(item.series.label != null){
showTooltip(item.pageX, item.pageY,
item.series.label + " of " + y);
}
}
}
else {
$("#tooltip").remove();
previousPoint = null;
}
}
});
var d1 = [
myData[0], myData[1], myData[2], myData[3], myData[4],
myData[5], myData[6], myData[7], myData[8], myData[9],
myData[10], myData[11], myData[12], myData[13], myData[14],
myData[15], myData[16], myData[17], myData[18], myData[19],
myData[20], myData[21], myData[22], myData[23], myData[24],
myData[25], myData[26], myData[27], myData[28], myData[29]
];
var markings = [
{ color: '#FFBDC1', yaxis: { from: 0, to: 2 } },
{ color: '#F2E2C7', yaxis: { from: 2, to: 3.5 } },
{ color: '#B6F2B7', yaxis: { from: 3.5, to: 5 } }
];
$.plot($("#placeholder"), [
{label: "Average Daily Rating", data: d1, color: "black"}
], {
events: {
data: events,
},
series: {
lines: { show: true },
points: { show: true }
},
legend: { show: true, container: '#legend-holder' },
xaxis: {
ticks:[
myDates[0], myDates[1], myDates[2], myDates[3], myDates[4],
myDates[5], myDates[6], myDates[7], myDates[8], myDates[9],
myDates[10], myDates[11], myDates[12], myDates[13], myDates[14],
myDates[15], myDates[16], myDates[17], myDates[18], myDates[19],
myDates[20], myDates[21], myDates[22], myDates[23], myDates[24],
myDates[25], myDates[26], myDates[27], myDates[28], myDates[29]
],
},
yaxis: {
ticks: 5,
min: 0,
max: 5
},
grid: {
backgroundColor: { colors: ["#fff", "#eee"] },
hoverable: true,
clickable: true,
markings: markings
},
selection: {
color: 'white',
mode: 'x'
},
});
$('#placeholder').resize();
$('#placeholder').shutdown();
}
EDIT 3:
The calendar is called like this:
function showCalendar() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#fullcalendar').fullCalendar({
header: {
left: 'prev',
center: 'title',
right: 'next'
},
clickable: true,
firstDay: 1,
eventSources: [
{
url: '/populate-calendar/{{theProductUuid}}/',
color: 'black',
data: {
text: 'text'
}
}
],
eventClick: function(calEvent, jsEvent, view) {
var startDate = $.fullCalendar.formatDate(calEvent.start, 'yyyy-MM-dd');
var endDate = $.fullCalendar.formatDate(calEvent.end, 'yyyy-MM-dd');
var eventId = calEvent.uuid;
$('#modal-event-title').text(calEvent.title);
$('#edit-event-name').val(calEvent.title);
$('#edit-start-date').val(startDate);
$('#edit-end-date').val(endDate);
$('#edit-event-text').val(calEvent.text);
$('#edit-event-btn').attr('data-uuid', eventId);
$('#modal-edit-event').on('click', '#delete-btn', function(){
deleteCalendarEvent(eventId);
});
$('#modal-edit-event').modal();
},
});
}
The AJAX to load the page containing the flot chart:
function loadDetailedReports(uuid){
$('#product-content').fadeOut('slow', function(){
$('#product-content').empty();
$('#whole-product-sub-nav .active').removeClass('active');
$('#detailed-reports-content').load('/detailed-reports/' + uuid + '/', function(){
$('#detailed-reports-btn').addClass('active');
$('#detailed-reports-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadDetailedReports&' + uuid);
getChartData(uuid);
} else {
setLocationHash('');
}
});
});
});
}
And the AJAX to load the page containing the calendar:
function loadCalendar(uuid){
$('#detailed-reports-content').empty().hide();
$('#product-content').fadeOut('slow', function(){
$('#whole-product-sub-nav .active').removeClass('active');
$('#product-content').load('/calendar/' + uuid + '/', function(){
$('#calendar-btn').addClass('active');
$('#product-content').fadeIn('slow', function(){
if (authorized){
setLocationHash('loadCalendar&' + uuid);
} else {
setLocationHash('');
}
showCalendar();
});
});
});
}
The calls to .resize and .shutdown are there because I was under the impression that they are necessary to achieve the resizing function and in response to your earlier comment regarding shutdown...... They're quite possibly n00b errors........?!?!
It looks like this is triggering on line 198 of jquery-resize:
data.w = w !== undefined ? w : elem.width();
This sounds like a race-condition stemming from the way you load different content into the same div. Flot binds the resize event to the chart div, and only un-binds it if the plot is destroyed cleanly.
EDIT: Looking at your code, my first suggestion would be to get rid of the resize and shutdown calls at the end of plotLineGraph. The resize plugin doesn't require any setup; it hooks into Flot to attach automatically to any new plot. So your call to resize is actually to jQuery's resize event trigger, which may be what's causing the error.
EDIT #2: I'm still not clear on your structure, but to generalize: anywhere that you might be getting rid of #placeholder (via emptying its parent or anything like that) you should first call shutdown on the plot object. If you aren't keeping a reference to it, you can do it like this: $("#placeholder").data("plot").shutdown(); but then have to account for the fact that it's undefined prior to the creation of your first plot.
If that still doesn't work, I'd need to see a live (simplified) example to make any further suggestions.

Animating dimensions in Sencha Touch 2

I'm trying to animate the height of a dataview, but it's currently just sliding the panel around the viewport instead of keeping it in place and changing it's height. The code is as follows:
Ext.Anim.run(el, 'slide', {
from: { height: height },
to: { height: newHeight },
out: false,
direction: 'up',
easing: 'ease-out',
duration: 1000
});
For instance, height=200, newHeight=100 will result in the dataview dropping immediately so that it's top is at 200px below the viewport, and then animating back to the top of the viewport.
How can I get it to change the height? Thanks.
Try using Ext.Animator.run instead:
Ext.Animator.run({
element: dataview.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: dataview.element.getHeight()
},
to: {
height: 100
}
});
And within a full example:
Ext.application({
name: 'Sencha',
launch: function() {
var dataview = Ext.create('Ext.DataView', {
fullscreen: true,
style: 'background:red',
store: {
fields: ['text'],
data: [
{ text: 'one' },
{ text: 'two' },
{ text: 'three' }
]
},
itemTpl: '{text}'
});
Ext.Viewport.add({
xtype: 'button',
docked: 'top',
handler: function() {
Ext.Animator.run({
element: dataview.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
to: {
height: 100
},
from: {
height: dataview.element.getHeight()
}
});
}
});
}
});
Since I can't add comments, I'll have to put this as a separate answer. I just wanted to add to what rdougan said and show how you can catch the animation end event. I find it's necessary in the above situation because Sencha Touch's component.getTop/Left/Height/Width() functions return incorrect values after an animation such as the one shown.
dataview.setHeight(dataview.element.getHeight()); // you may or may not need this
console.log('height before\t', dataview.getHeight());
var a = new Ext.fx.Animation({
element: dataview.element,
duration: 500,
easing: 'ease-in',
preserveEndState: true,
from: {
height: dataview.element.getHeight()
},
to: {
height: 100
}
});
a.on('animationend', function (animation, element, isInterrupted) {
console.log('height before\t', dataview.getHeight());
dataview.setHeight(dataview.element.getHeight());
console.log('height set\t', dataview.getHeight());
});
Ext.Animator.run(a);
I left in some logging so you can see just what I mean. This example was written against ST 2.1 RC2.
Here's a clean utility function you can use to accomplish this
function animatron (target, prop, duration, to, from, easing) {
// return if no target or prop
if (target == null || prop == null) { return; }
// defaults
if (duration == null) { duration = 250; }
if (to == null) { to = 0; }
if (from == null) { from = target.getHeight(); }
if (easing == null) { easing = 'ease-out'; }
// to property
var t = {};
t[prop] = to;
// from property
var f = {};
f[prop] = from;
// Animation Options
var opts = {
duration: duration,
easing: easing,
element: target.element,
from: f,
preserveEndState: true,
to: t
};
// Animation Object
var anime = new Ext.fx.Animation(opts);
// On animationend Event
anime.on('animationend', function (animation, element, isInterrupted) {
// Hide the target if the to is 0
if (to == 0 && (prop == 'height' || prop == 'width')) {
if (!isInterrupted) { target.hide(); }
}
// Update property if width or height
if (prop == 'height') { target.setHeight(to); }
if (prop == 'width') { target.setWidth(to); }
// Dispatch 'animated' event to target
target.fireEvent('animated', animation, element, to, from, isInterrupted);
});
// Show the target if it's hidden and to isn't 0
if (target.getHidden() == true && to != 0) { target.show(); }
// Run the animation
Ext.Animator.run(anime);
}
You can listen for the 'animated' event on the target element
animatron(dataview, 'height', 500, 0);
dataview.addListener('animated', function (animation, element, to, from, isInterrupted) {
console.log('animation ended');
console.log('interrupted: '+ isInterrupted);
});