奇怪的行为:不同 Android 版本上的 Constraint Layout 动画

huangapple go评论73阅读模式
英文:

Strange behaviour Constraint Layout Animation on differente Android versions

问题

I made an animation to represent the number of players in my Android application (2 players = 2 bottles and so on..).
I'm pretty happy with the result but it is not working on my old device on Android 5.0.
The min SDK Version of the application is 21, so it should be alright.

I want to make an animation like this: [Correct animation on Android 10.0](https://streamable.com/bf745u). But in Android 5.0 we have for some values (eg from 3 to 4 but not from 5 to 4) this behaviour: [Wrong animation on Android 5.0](https://streamable.com/vomhpg).

I tried different layouts, resources and more, but I couldn't get it to work 100% correctly on Android 5.0.

// Code snippet
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.transition.ChangeBounds;
import android.transition.TransitionManager;
import android.view.View;
import android.view.animation.AnticipateInterpolator;
import android.widget.Button;
import android.widget.TextView;
import android.widget.VideoView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;

public class PickNbrPlayersScreen extends AppCompatActivity {
    // ... (code truncated for brevity)
}

// Layout snippet
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/bottles_2"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".menuScreens.PickNbrPlayersScreen">

    <!-- Layout components -->
</androidx.constraintlayout.widget.ConstraintLayout>

Is there any way to fix this strange behaviour? Or is it a version issue?

Thank you for your help and time, have a nice day!


<details>
<summary>英文:</summary>

I made an animation to represent the number of players in my Android application (2 players = 2 bottles and so on..).
I&#39;m pretty happy with the result but it is not working on my old device on Android 5.0.
The min SDK Version of the application is 21, so it should be alright.

I want to make an animation like this: [Correct animation on Android 10.0](https://streamable.com/bf745u). But in Android 5.0 we have for some values (eg from 3 to 4 but not from 5 to 4) this behaviour: [Wrong animation on Android 5.0](https://streamable.com/vomhpg).

I tried different layouts, resources and more, but I couldn&#39;t get it to work 100% correctly on Android 5.0.

import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.transition.ChangeBounds;
import android.transition.TransitionManager;
import android.view.View;
import android.view.animation.AnticipateInterpolator;
import android.widget.Button;
import android.widget.TextView;
import android.widget.VideoView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.ConstraintSet;

public class PickNbrPlayersScreen extends AppCompatActivity {

private ConstraintLayout layout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.menu_pick_nbr_players_2);

    layout = findViewById(R.id.bottles_2);

    nbrPlayers = findViewById(R.id.currentPlayerCountTextView);
}

public void decreasePlayerNbr(View view) {
    nbrOfPlayers--;
    if (nbrOfPlayers &lt; 2) {
        nbrOfPlayers = 8;
    }
    nbrPlayers.setText(String.valueOf(nbrOfPlayers));
    playAnimation(nbrOfPlayers);
}

public void increasePlayerNbr(View view) {
    nbrOfPlayers = Math.max(2, (nbrOfPlayers + 1) % 9);
    nbrPlayers.setText(String.valueOf(nbrOfPlayers));
    playAnimation(nbrOfPlayers);
}

private void playAnimation(int nbrOfPlayers) {
    ConstraintSet constraintSet = new ConstraintSet();
    int currentLayoutId = getCorrectLayout(nbrOfPlayers);
    constraintSet.clone(this, currentLayoutId);

    ChangeBounds transition = new ChangeBounds();
    transition.setInterpolator(new AnticipateInterpolator(1.0f));
    transition.setDuration(500);

    TransitionManager.beginDelayedTransition(layout, transition);
    constraintSet.applyTo(layout);
}

private int getCorrectLayout(int nbrOfPlayers) {
    int layoutId;
    switch (nbrOfPlayers) {
        case 2:
            layoutId = R.layout.menu_pick_nbr_players_2;
            break;
        case 3:
            layoutId = R.layout.menu_pick_nbr_players_3;
            break;
        case 4:
            layoutId = R.layout.menu_pick_nbr_players_4;
            break;
        case 5:
            layoutId = R.layout.menu_pick_nbr_players_5;
            break;
        case 6:
            layoutId = R.layout.menu_pick_nbr_players_6;
            break;
        case 7:
            layoutId = R.layout.menu_pick_nbr_players_7;
            break;
        case 8:
            layoutId = R.layout.menu_pick_nbr_players_8;
            break;
        default:
            throw new IllegalStateException(&quot;Unexpected value: &quot; + nbrOfPlayers);
    }
    return layoutId;
}

}


one of my layouts for example:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bottles_2"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".menuScreens.PickNbrPlayersScreen">

&lt;ImageView
android:id=&quot;@+id/bgImage&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:contentDescription=&quot;@null&quot;
android:scaleType=&quot;centerCrop&quot;
app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.0&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:layout_constraintVertical_bias=&quot;0.0&quot;
app:srcCompat=&quot;@drawable/nbrplayersback&quot; /&gt;
&lt;!-- Beer Bottles --&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_2&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintBottom_toTopOf=&quot;@+id/increasePlayerNbrButton&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.551&quot;
app:layout_constraintStart_toEndOf=&quot;@+id/beerBottle_1&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:layout_constraintVertical_bias=&quot;0.545&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_1&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintBottom_toTopOf=&quot;@+id/decreasePlayerButton&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.231&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:layout_constraintVertical_bias=&quot;0.145&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_8&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintStart_toStartOf=&quot;@+id/beerBottle_4&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_7&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintEnd_toEndOf=&quot;@+id/beerBottle_3&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_6&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintStart_toEndOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_5&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintEnd_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_4&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintStart_toEndOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;ImageView
android:id=&quot;@+id/beerBottle_3&quot;
android:layout_width=&quot;@dimen/beerBottle_width&quot;
android:layout_height=&quot;@dimen/beerBottle_height&quot;
app:layout_constraintEnd_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:srcCompat=&quot;@drawable/beerbottle&quot; /&gt;
&lt;!-- Buttons and TextViews --&gt;
&lt;Button
android:id=&quot;@+id/decreasePlayerButton&quot;
style=&quot;@style/RoundButton&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:onClick=&quot;decreasePlayerNbr&quot;
android:text=&quot;@string/minusSign&quot;
android:textSize=&quot;@dimen/menu_decrease_textSize&quot;
app:layout_constraintBottom_toBottomOf=&quot;@+id/currentPlayerCountTextView&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.25&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;@+id/currentPlayerCountTextView&quot;
app:layout_constraintVertical_bias=&quot;0.5&quot; /&gt;
&lt;Button
android:id=&quot;@+id/increasePlayerNbrButton&quot;
style=&quot;@style/RoundButton&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:onClick=&quot;increasePlayerNbr&quot;
android:text=&quot;@string/plusSign&quot;
android:textSize=&quot;@dimen/menu_decrease_textSize&quot;
app:layout_constraintBottom_toBottomOf=&quot;@+id/currentPlayerCountTextView&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.75&quot;
app:layout_constraintStart_toStartOf=&quot;@+id/bgImage&quot;
app:layout_constraintTop_toTopOf=&quot;@+id/currentPlayerCountTextView&quot; /&gt;
&lt;TextView
android:id=&quot;@+id/currentPlayerCountTextView&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_marginBottom=&quot;16dp&quot;
android:text=&quot;2&quot;
android:textColor=&quot;@color/colorNormalText&quot;
android:textSize=&quot;@dimen/menu_nbr_of_players_textSize&quot;
app:layout_constraintBottom_toTopOf=&quot;@+id/continueButton&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintHorizontal_bias=&quot;0.5&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot;
app:layout_constraintTop_toTopOf=&quot;parent&quot;
app:layout_constraintVertical_bias=&quot;1&quot; /&gt;
&lt;Button
android:id=&quot;@+id/continueButton&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_marginBottom=&quot;@dimen/menu_button_margin_bottom&quot;
android:onClick=&quot;nextMenu&quot;
android:text=&quot;@string/Continue&quot;
app:layout_constraintBottom_toTopOf=&quot;@+id/subtitle_textView&quot;
app:layout_constraintEnd_toEndOf=&quot;@+id/subtitle_textView&quot;
app:layout_constraintStart_toStartOf=&quot;@+id/subtitle_textView&quot;
app:layout_constraintTop_toTopOf=&quot;@+id/videoView&quot;
app:layout_constraintVertical_bias=&quot;1.0&quot; /&gt;
&lt;TextView
android:id=&quot;@+id/subtitle_textView&quot;
android:layout_width=&quot;wrap_content&quot;
android:layout_height=&quot;wrap_content&quot;
android:layout_marginBottom=&quot;@dimen/menu_subtext_margin_bottom&quot;
android:text=&quot;@string/subtitle_NbrPlayers&quot;
android:textColor=&quot;@color/colorNormalButton&quot;
android:textSize=&quot;@dimen/menu_subtext_textSize&quot;
app:layout_constraintBottom_toBottomOf=&quot;@+id/videoView&quot;
app:layout_constraintEnd_toEndOf=&quot;parent&quot;
app:layout_constraintStart_toStartOf=&quot;parent&quot; /&gt;

</androidx.constraintlayout.widget.ConstraintLayout>


Is there any way to fix this strange behaviour? Or is it an version issue?
Thank you for your help and time, have a nice day!
</details>
# 答案1
**得分**: 2
我无法查看动画,因为链接已损坏。顺便建议使用来自 `androidx` 包的过渡类。我的意思是使用[这个][1]
```java
import androidx.transition.ChangeBounds;
import androidx.transition.TransitionManager;

而不是这个:

import android.transition.ChangeBounds;
import android.transition.TransitionManager;

android.transition 类是内置在平台中的,它们可能包含永远不会修复的错误。

英文:

I couldn't view animations because links are broken. Btw I suggest to use transition classes from androidx package. I mean use this

import androidx.transition.ChangeBounds;
import androidx.transition.TransitionManager;

instead of this:

import android.transition.ChangeBounds;
import android.transition.TransitionManager;

android.transition classes are build into platform, they may contain bugs which will never be fixed.

huangapple
  • 本文由 发表于 2020年10月24日 22:35:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/64514488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定