fragments, android:zAdjustment (z order) and animations - android-fragments

I'm using the support library. Now, I want to have a fragment shifting in from the bottom, moving OVER the previous one.
For this I use this to keep the previous fragment (the one that is being slided over) visible until the new fragment is in its place:
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="2500"
android:zAdjustment="bottom" />
this is animation used for the new fragment to slide in from bottom:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p" android:toYDelta="0"
android:duration="#android:integer/config_mediumAnimTime"
android:zAdjustment="top"/>
I've put the z adjustment to bottom and top for both, but still the 'bottom' animation is still on top of the new fragment! I have put the duration to 2500 for testing and it stays on top for the whole time.
Does zAdjustment not work for fragment animations?

According to this google group thread Z adjustment only works for window animations.
"The Z adjustment only works for window animations. I thought this was documented, but apparently not."
-- Dianne Hackborn (Android framework engineer)

You can override the onCreateAnimation method and for any animations you can check what animation is currently running and if you need it to be on top, set the Z-axis from there.
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (nextAnim == R.anim.enter_from_right || nextAnim == R.anim.exit_to_right) {
ViewCompat.setTranslationZ(view, 1f)
} else {
ViewCompat.setTranslationZ(view, 0f)
}
return super.onCreateAnimation(transit, enter, nextAnim)
}
Recommend implementing this as a base Fragment class for all your fragments.

I've also got stuck with that problem. So instead of using transaction.replace(containerId, newFragment) I've created two containers for fragments and now my code looks like this one
Add first fragment:
transaction.add(containerId1, firstFragment).commit();
Add second fragment with animation over the first one:
findViewById(containerId2).bringToFront();
transaction.setCustomAnimations(R.anim.slide_in_up,
R.anim.stay).remove(oldFragment).add(containerId2, newFragment).commit()

You can use androidx.fragment.app.FragmentContainerView as a fragments container. It automatically handles z order for animations specified in setCustomAnimations()

Related

Reveal Timestamp React Native (iMessage Clone)

I was wondering how I would go about dragging/sliding left to reveal the timestamp on react native. I am using a flatlist in react-native and I have the timestamp data but I am unsure of how to render the timestamps on slight drag. Anyone have detailed ideas on how to do this. I have included images of current implementation and iMessage slide/drag. This feature is also on Instagram (ios version at least). I should add that I'm not trying to do a drag and drop feature more like just a solution review what is not currently in the view from a slide/drag
Current App
Current iMessage
This is the eventual solution i came up with all credit from #Abe and reading the gesture-handler documentation referenced above. I
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated'
const translateX = useSharedValue(0)
const startX = useRef(0)
My flatlist renders elements like this now
<Animated.View
className="mx-2 flex-1 flex-row"
style={sty}
onTouchStart={(e) => {
startX.current = e.nativeEvent.pageX
}}
onTouchMove={(e) => {
const delta = startX.current - e.nativeEvent.pageX
if (delta > 0) {
translateX.value = -delta / 2
}
}}
onTouchEnd={() => {
translateX.value = withSpring(0)
}}>
...
</Animated.View>
The most common way to handle this is with a PanGestureHandler from react-native-gesture-handler and an Animated.View from react-native-reanimated.
Wrap your component in one, and make the View that you want to move into an Animated.View. (The component that the PanGestureHandler wraps also should be an Animated.View.) Create a shared value (from Reanimated) that represents the x offset of the component. Then create a handler method that responds to the drag gesture and changes the shared value. You may want to add some limits, like not scrolling past a certain offset in either direction. Then, use the shared value in an animated style (something like left: offsetX,) that you apply to your Animated.View.
Since you're using this inside a scrollable list, make sure to set the activeOffsetX prop to something like [-5, 5]. This means that if the user is only trying to scroll up and down, your gesture handler won't steal that touch.
The example in the gesture-handler docs should help.

Problems changing the flags of a QWidget

I have a QWidget as the child of another within my application. The task consists of putting the internal widget in full screen mode and being able to see it again in normal mode with the same button. This partly I have managed to do it in the following way:
if(!isFullScreen())
{
setWindowFlags(windowFlags() | Qt::Window);
showFullScreen();
}
else
{
setWindowFlags(windowFlags() & ~Qt::Window);
showNormal();
activateWindow();
}
The problem arises when you return to see the widget in normal mode. Things that happen:
The mouse cursor stays with pointing hand cursor.
The button to change mode remains in hover state (the background color is changed when the mouse is over)
Passing the mouse through other widget controls does not change its appearance
I have to click on the widget to fix the behavior. It's as if the widget did not receive events of any kind or something like that. I tried calling setFocus () and it did not work. I have also tried to send an event by hand in the following way but it has not worked either:
QMouseEvent my_event(QEvent::MouseButtonPress, QPointF (0, 0), Qt :: NoButton, 0, 0);
QApplication::sendEvent(this, & my_event);
Any ideas?
Thanks.
Cannot reproduce your issue on Xubuntu with Qt5.9.4.
However I did the same in my last job, and it worked correctly on all platforms. It was something like this, I think:
if(!isFullScreen())
{
setParent(0);
showFullScreen();
}
else
{
orignalParentLayout->addWidget(this); // better: insert at correct position
showNormal();
}
For this you have to add some knowledge about the parent's layout though. You could try to detect that info before going into full screen mode, but it is probably not worth the effort.
You could also try:
if(!isFullScreen())
{
logicalParent = parentWidget();
setParent(0);
showFullScreen();
}
else
{
setParent(logicalParent);
showNormal();
}
If you have no layout. You might also want to store the geometry before going to full screen.

javafx setOpacity method doesn't work when repeated for some times

I use a Thread to change the opacity of an AnchorPane.
I add an onMouseEnter method to raise opacity gradually,and an onMouseExited method to decrease opacity gradually.
I have two panes, if my mouse enter any one of them,both two panes will change opacity.
Then I start my application, I find that after my mouse enter and exit the pane for some times, one will stop at a specific opacity,while the other still change opacity gradually.
I am confused why this happen...
My codes are like:
private double base = 0.5;
private void changeOpacity(boolean increase){
new Thread(()-> {
while((increase && base < 0.9) || ((!increase)&&base > 0.5)){
base += increase?0.01:-0.01;
leftPane.setOpacity(base);
rightPane.setOpacity(base);
Thread.sleep(5);
}
}
}
I am sorry for my poor English.
Thanks.!
You are only allowed to change values of JavaFX components while you are on the JavaFX-Thread (something you are clearly not).
You need to sync yourself back using Platform.runLater(Runnable) but in your case you'd swap the event loop with Runnables which an equally bad idea.
The correct way is:
Use a Timeline with a KeyFrame
Use the already predefined FadeTransition foreach Node (together with a ParallelTransition)

Make two QDockWidgets mutual execlusive at the same position

I have two QDockWidget's, only one of them is visible at the time, I manage that by toggleViewAction().
What I need to do is that I want the two QDockWidget's to be in the same location, with the same size and docked at the same dockWidgetArea with the same orientation and order relative to other QDockWidgets.
I did most of the that by this code:
void myMainWindow::slotToggleDocks(QAction* action) {
if(action == viewDock1) {
Dock1->setFloating(Dock2->isFloating());
Dock1->resize(Dock2->size());
Dock1->restoreGeometry(Dock2->saveGeometry());
Dock1->move(Dock2->pos());
addDockWidget(dockWidgetArea(Dock2), Dock1);
...
Dock2->hide();
} else if(action == viewDock2) {
Dock2->setFloating(Dock1->isFloating());
Dock2->resize(Dock1->size());
Dock2->restoreGeometry(Dock1->saveGeometry());
Dock2->move(Dock1->pos());
addDockWidget(dockWidgetArea(Dock2), Dock1);
...
Dock1->hide();
}
}
this code make the two have the same location and size and docked to the same area (left, right, ...) but it doesn't guarantee that the Docks will have the same layout with the other QDockWidget's in the same dockWidgetArea.
Meaning if this was the before layout:
Layout before http://holmez.net/qdockwidget/1.png
This is after toggling:
Layout after toggling http://holmez.net/qdockwidget/2.png
This is what I want:
Expected result http://holmez.net/qdockwidget/3.png
I managed to do that by a simple trick, add this line of code:
splitDockWidget(Dock1,Dock2,Qt::Horizontal);
before hiding Dock1, and this line:
splitDockWidget(Dock2,Dock1,Qt::Horizontal);
before hiding Dock2.
This fixed the problem of the arrangement of docked widgets, not sure if this is the best way but it works for me.
What about only using 2 QDockWidgets, but having QStackedWidgets INSIDE of them which you can use to swap views? That's what I'm currently doing, and it works great.
Another advantage is that swapping views is as simple as:
stackedWidget->setCurrentIndex(index);
What about using QTabWidget?
The 2 widgets will have to be in the same Qt::DockWidgetAreas

Flex 3 - Change box border colors

I have a question that might seem "basic" but I just cannot figure out how to do it...
I have a box and I'd like to change the borderColor. Till there, nothing special. Just a box.bordercolor = xxxxxx...
BUT, I'd like to have the top and bottom border with one color, and the left and right border with another color... And that's the part where I'm stuck.
Any tips? Suggestions?
Thanks for your help and time! ;)
Regards,
BS_C3
#Senz
Hi!
Unfortunately, I won't be able to share the code without making it "incomprehensible"...
But this is the idea... We have 2 main components: ArrowButton and Navigator.
ArrowButton is a hbox containing a label and an image (this image is the arrow tip and it changes depeding on the state of the ArrowButton).
Navigator is a hbox containing a series of ArrowButton. An ArrowButton overlaps the arrowButton on its right in order to create the pointed end of the button.
And then you just create a whole bunch of functionnalities around these components.
I hope this helps... Do not hesitate if you have some more questions =)
Regards.
I noticed you are asking about the Flex 3 SDK. Skins are a good approach. They have changed somewhat in Flex 4(for the better IMHO). If you are wanting to use the Flex Drawing API, then just extend the Box class into a custom class that would look something like this:
public class MultiColorBorderBox extends Box
{
// You could add getters/setters or constructor parameters to be able to change these values.
private var topColor:uint = 0xFF0000;
private var rightColor:uint = 0x00FF00;
private var bottomColor:uint = 0x0000FF;
private var leftColor:uint = 0xFF00FF;
private var borderWidth:Number = 20;
public function MultiColorBorderBox()
{
super();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
// This just ensures you dont have content under your border
this.setStyle("paddingLeft", borderWidth);
this.setStyle("paddingRight", borderWidth);
this.setStyle("paddingTop", borderWidth);
this.setStyle("paddingBottom", borderWidth);
var g:Graphics = this.graphics; // This creates a new Graphics object and sets it to the MultiColorBorderBox graphics object. Since Box (superclass) descends from a Sprite object, it has a graphics object automatically.
g.clear();
g.moveTo(0,0); // Moves the position to the top left corner
g.lineStyle(borderWidth, topColor); // Sets the line style with the width and color
g.lineTo(unscaledWidth, 0); // Draws the top border from top left to top right corners
g.lineStyle(borderWidth, rightColor); // Changes the line style
g.lineTo(unscaledWidth, unscaledHeight); // Draws the line from top right to bottom right
g.lineStyle(borderWidth, bottomColor); //Changes the bottom border style
g.lineTo(0, unscaledHeight); // Draws the line from bottom right to bottom left
g.lineStyle(borderWidth, leftColor); // Changes the border color
g.lineTo(0,0); // Closes the box by drawing from bottom left to top left
}
I'm pretty sure you're going to have to create a borderSkin to accomplish this. I believe these are created in an external program, such as Flash Professional; but more info is in the docs.
I don't think that Flex makes any distinction between top/bottom borders and left/right borders. Creating a skin would certainly be the nifty-slick way to do it. A programmatic way might be to use box.graphics to draw your border by hand. I'd start by trying to override the updateDisplayList() function to draw your border...
I finally did a pretty simple thing.
I guess I wasn't detailed enough regarding the specifications.
The actual aim was to create a navigator with arrow shaped buttons.
Each button had to be highlighted when it was selected. And this http://www.freeimagehosting.net/uploads/bcd0d762d7.jpg is how the navigator looked like.
Each button is actually an HBox containing a Box (with a label) and an Image (for the arrow tip), with a horizontalGap = 0.
I didn't think about adding a glowfilter to the button. So I was trying to just change the colors of the top and bottom part of the Box...
So, the glowfilter in the button worked pretty well.
Sorry for the lack of explanations about the context >_< And thanks for your answers!!
Regards.

Resources