How to specify TransitionManager.beginDelayedTransition to affect only direct child views

android, android-recyclerview, android-transitions

Solution

pskink posted the answer in the comments, but after asking twice for him to post as an answer for me to accept and never doing it, I'll post it instead and mark this as answered.

The `TransitionManager` had a method `excludeChildren` that works perfectly for what I was looking for. You can use by class types, children of a specific view and so on.

EDIT: Adding example requested

    AutoTransition autoTransition = new AutoTransition();
    autoTransition.excludeChildren(R.id.recyclerView, true);
    TransitionManager.beginDelayedTransition(constraintLayout, autoTransition);

With `constraintLayout` as the parent of the target view and `R.id.recyclerView` being a child view of that parent that I don't want to be animated, in this specific example that is. You can also exclude all children that are of a specific class (`EditText` for example) and so on.

Problem

I am trying to use a `ConstraintLayout` in conjunction with views that slide up and down with animation. These views are organized vertically, with a `RecyclerView` at the top and two other views stacked under it: ``` <constraint layout container> [ ] [ recycler view ] [ ] [48dp height 1st view] [48dp height 2nd view] </constraint layout container> ``` The animation is very simple: When a button is tapped the 1st view moves from the bottom of the container to the position you can see above, when tapped again it moves down and stays overlapped on the 2nd view. When this happens the `RecyclerView` at the top changes height since it is constrained to that 1st view, otherwise it would leave an empty space. So far so good and the animation is working well, but the problem arises when the user taps the button too fast, leading to the following error: ``` java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first. ``` After investigating what was going on I discovered that this problem is a consequence of the `TransitionManager` that I am using to animate the changes. What I discovered was interesting, when the button was tapped to move the 1st view up (or down, just imagine the opposite steps) the manager was doing the following: - Fade out the first/last view from the `RecyclerView` (depends on whether or not you have a reversed layout or stack from end enabled) - Remove that view from the `RecyclerView` - Decrease the height of the `RecyclerView` - Move the 1st view up Even though I specified in all the places I could imagine that the `RecyclerView` should not animate item changes, the `TransitionManager` was overriding it and that meant there is a window when the same view that is being about to be removed from the `RecyclerView` can be added again to the same parent, and that window is when the view is fading out by the manager. Since the fade animation is not that fast, a user can very easily tap the button twice during that time, causing the manager to re-add the fading view, which is already in the `RecyclerView` and thus crashing the app while throwing the above error. Since this is an issue caused inside the `RecyclerView` I would be perfectly fine with no animations inside it and for that reason I would like to know how can I specify in the `TransitionManager.beginDelayedTransition` to only animate the direct child views of the `ConstraintLayout`, this way it will not animate the views inside the `RecyclerView`. The related documentation does not shine anything over this, so I present here this question; How can I restrict the transition to direct child views? In case it might be helpful I include here the snippet of the transition manager ``` final ConstraintSet constraintSet; final ConstraintLayout constraintLayout; constraintSet = new ConstraintSet(); constraintLayout = (ConstraintLayout) viewParent; TransitionManager.beginDelayedTransition(constraintLayout); constraintSet.clone(constraintLayout); constraintSet.connect(startId, startSide, endId, endSide, margin); constraintSet.applyTo(constraintLayout); ```

Original source

Related problems