i want to crate animation from right to left when change activity, but not of window only certain layout, this is my code :
val transition = Slide()
transition.duration = 300
transition.slideEdge = Gravity.END
transition.mode = Visibility.MODE_IN
transition.interpolator = DecelerateInterpolator(2f)
transition.addTarget(R.id.ln_verification_phone)
window.enterTransition = transition
but when i remove transition.addTarget(R.id.ln_verification_phone), animation working but all of window, i want to target of view, are there wrong in my code, i try using exclude also not work
Related
I want to slide a PopupWindow from the bottom of the screen to some point above it, say center.
I have the following logic so far
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
val popupView: View = inflater.inflate(R.layout.popup_window, null)
val width = LinearLayout.LayoutParams.WRAP_CONTENT
val height = LinearLayout.LayoutParams.WRAP_CONTENT
val focusable = true // lets taps outside the popup also dismiss it
val popupWindow = PopupWindow(popupView, width, height, focusable)
val slide = Slide()
slide.apply {
duration = 300
slideEdge = Gravity.BOTTOM
}
view?.doOnAttach {
popupWindow.isFocusable = true
popupWindow.enterTransition = slide
popupWindow.exitTransition = slide
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0)
}
I am able to slide the window between its width. So what this does is that the sliding happens from -w/2 where w is the width of the window and ends at w/2. Which maybe expected since the position of the window is set as 0, 0. However I want the sliding to happen between 2 specific points. Like the sliding should start from the bottom of the screen and it should continue to slide till it reaches the coordinate 0,0.
I found a workaround by expanding the width of the window to the portion below 0,0 but that cause the views below it to not be clickable. So this doesn't work in my case. Is there a way to do this sliding? Thanks!
Consider the following Coordinator+AppBar+MotionLayout and its MotionScene from Google's demo. This creates a MotionLayout that sync's its Transition progress when the user is scrolling.
Video Preview: https://i.imgur.com/1MnPB8R.mp4
However, I would like to do this in programmatically in Kotlin. Here are my failed attempts.
val motion = findViewById<MotionLayout>(R.id.constraintToolbar)
motion.transitionToState(R.id.end)
The above would cause the MotionLayout to animate, but would immediately blink back to the start state once finished. The AppBarLayout also does not change height.
val appbar = findViewById<AppBarLayout>(R.id.app_bar)
val scrollable = findViewById<NestedScrollView>(R.id.scrollable)
val s = if(motion.progress==0F) appbar.totalScrollRange else 0
scrollable.smoothScrollTo(0, s)
The above scrolls the NestedScrollView, but the AppBarLayout and MotionLayout does not receive the scroll events.
val s = if(motion.progress==0F)-appbar.totalScrollRange else 0
val appbar = findViewById<AppBarLayout>(R.id.app_bar)
appbar.scrollTo(0,s)
appbar.offsetTopAndBottom(s)
The above shifts the AppBarLayout, breaking the layout completely.
How do you trigger this scroll programmatically?
If there's only 2 states, you should try setExpanded()
val e = motion.progress != 0F
appbar.setExpanded(e, true)
I am able to go to my next destination with a circular reveal animation. My only problem is the previous fragment is gone, unless I set a fade out exit transition in my action app:exitAnim="#anim/exit_fade_out". I wanted to ask if anyone has been able to keep the previous fragment visible while doing the circular revealing.
this is the code for revealing and hiding the new fragment.. so far this works yet I cannot show the previous fragment as its masking the next one
private val maxScreenDimension : Float
get() {
return max(container.width, container.height).toFloat()
}
private fun circularReveal(point: Point) {
val viewTreeObserver = container.viewTreeObserver
if (viewTreeObserver.isAlive) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
doCircularReveal(point)
container.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
}
}
private fun doCircularReveal(point: Point) {
val initRadius = 0f
val finalRadius = maxScreenDimension
val circularReveal = ViewAnimationUtils.createCircularReveal(
container,
point.x,
point.y,
initRadius,
finalRadius
)
circularReveal.duration = resources.getInteger(R.integer.circular_animation_out).toLong()
circularReveal.start()
}
private fun circularHide(point: Point) {
val initRadius = maxScreenDimension
val finalRadius = 0f
val circularReveal = ViewAnimationUtils.createCircularReveal(
container,
point.x,
point.y,
initRadius,
finalRadius
)
circularReveal.duration = resources.getInteger(R.integer.circular_animation_in).toLong()
circularReveal.doOnEnd {
container.isVisible = false
findNavController().popBackStack()
}
circularReveal.start()
}
You can do a little hack to make Navigation component to leave the fragment in place during circular reveal animation by giving it a fake animation for exitAnim with the same duration that your circular reveal.
For example it can look like this:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="#android:integer/config_mediumAnimTime" />
</set>
So in case you wonder how to retain the previous screen and do a circular reveal animation for the next screen. My solution was to simply add a new fragment. I don't think the Navigation component allows for this type of animation. Earlier I did a shared element transition which worked fine as long as I used a fade in/out transition between the two screens. In that way I was able to retain the previous screen while the shared element transition played out. I am thinking the Navigation component is constantly replacing the following fragment.
I am trying to animate RecyclerView items using ConstraintSet animation.
I have two layouts and they are switched properly using this code:
val constraint2 = ConstraintSet()
constraint2.clone(binding.root.context, R.layout.list_item_2)
val transition = ChangeBounds()
transition.interpolator = OvershootInterpolator(1.0f)
transition.duration = 1200
TransitionManager.beginDelayedTransition(binding.root.container, transition)
constraint2.applyTo(binding.root.container)
However delayed transition is completely ignored and it works the same way whether or not I add beginDelayedTransition code, so there is no animation.
I'd like to make enter animation for activity using ConstraintSet, as it's shown in this video:
https://www.youtube.com/watch?v=OHcfs6rStRo.
The problem is I don't know in which lifecycle method to put code to make the transition visible to user.
In onCreate I'm calling:
setContentView(R.layout.layout_first_keyframe_detail);
topConstraintLayout = findViewById(R.id.top_constraint_layout);
constraintSet = new ConstraintSet();
constraintSet.clone(this, R.layout.layout_detail_top);
and then I'd like to call:
TransitionManager.beginDelayedTransition(topConstraintLayout);
constraintSet.applyTo(topConstraintLayout);
when activity is already visible. Unfortunately I don't find any lifecycle method to do this.
If you look at TransitionManager.beginDelayedTransiton() implementation, you will see that it starts with following check :
if (!sPendingTransitions.contains(sceneRoot) && sceneRoot.isLaidOut())
Looking at isLaidOut() documentation will make you understand that the view has to be drawn at least once so the animation can be executed :
Returns true if this view has been through at least one layout since
it was last attached to or detached from a window.
However, wrapping the animation launch in a message worked for me. So you should try to do it like :
myView.post{
TransitionManager.beginDelayedTransition(topConstraintLayout);
constraintSet.applyTo(topConstraintLayout);
}
to create animations using ConstraintLayout and ConstraintSet you must first consider that there must be a starting layout and an ending layout
Step 1: Create your layouts
create your starting layout and ending layout as you want
--> suppose the starting layout name is (activity) the ending layout name is (activity_alt)
Step 2: Create Animation
now in the MainActivity inside onCreate method call your function foo
private void foo() {
var set = false
val constraint1 = ConstraintSet()
constraint1.clone(root)
val constraint2 = ConstraintSet()
constraint2.clone(this, R.layout.activity_alt)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
TransitionManager.beginDelayedTransition(root)
val constraint = if(set) constraint1 else constraint2
constraint.applyTo(root)
set = !set
}
}