onAnimationEnd が繰り返し呼び出されるという奇妙な問題があります (したがって、明示的に呼び出していなくても、アニメーションが何度も実行され続けます)。
これが何が起こっているかを記録したスクリーンショットです: https://youtu.be/TfGiLvwLdBM
以下は私のコードです:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TT_MainActivity";
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
setupViews();
showLogin();
}
private void setupViews() {
// Login views
binding.loginContainer.setTranslationY(Utils.getScreenHeight(this));
binding.tvNotRegistered.setTranslationY(Utils.getScreenHeight(this));
binding.tvLoginTitle.setTranslationY(-Utils.dpToPx(500));
binding.etEmail.setTranslationY(-Utils.dpToPx(500));
binding.etPassword.setTranslationY(-Utils.dpToPx(500));
binding.btnLogin.setTranslationY(-Utils.dpToPx(500));
// Signup views
binding.signupContainer.setTranslationY(-Utils.getScreenHeight(this));
binding.tvAlreadyHaveAAccount.setTranslationY(-Utils.getScreenHeight(this));
binding.tvSignupTitle.setTranslationY(-Utils.dpToPx(500));
binding.etEmailSignup.setTranslationY(-Utils.dpToPx(500));
binding.etPasswordSignup.setTranslationY(-Utils.dpToPx(500));
binding.btnSignup.setTranslationY(-Utils.dpToPx(500));
// Click listeners
setOnClickListeners();
}
private void setOnClickListeners() {
// LOGIN
binding.btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "login()...");
}
});
binding.tvNotRegistered.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "showSignup()..");
binding.tvNotRegistered.animate()
.translationY(Utils.getScreenHeight(MainActivity.this))
.setInterpolator(new AccelerateInterpolator());
binding.loginContainer.animate()
.translationY(Utils.getScreenHeight(MainActivity.this))
.setInterpolator(new AccelerateInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Log.d(TAG, "onAnimationEnd: showSignup()");
binding.loginContainer.setVisibility(View.GONE);
binding.tvNotRegistered.setVisibility(View.GONE);
showSignup();
}
});
}
});
binding.btnSignup.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "signup()...");
}
});
// SIGNUP
binding.tvAlreadyHaveAAccount.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, "showLogin()..");
binding.tvAlreadyHaveAAccount.animate()
.translationY(-Utils.getScreenHeight(MainActivity.this))
.setInterpolator(new AccelerateInterpolator());
binding.signupContainer.animate()
.translationY(-Utils.getScreenHeight(MainActivity.this))
.setInterpolator(new AccelerateInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Log.d(TAG, "onAnimationEnd: showLogin()");
binding.signupContainer.setVisibility(View.GONE);
binding.tvAlreadyHaveAAccount.setVisibility(View.GONE);
showLogin();
}
});
}
});
}
// SIGNUP
private void showSignup() {
binding.signupContainer.setVisibility(View.VISIBLE);
binding.tvAlreadyHaveAAccount.setVisibility(View.VISIBLE);
binding.signupContainer.animate()
.setDuration(300)
.setInterpolator(new OvershootInterpolator(1.0f))
.translationY(0)
.setStartDelay(300);
binding.tvAlreadyHaveAAccount.animate()
.setDuration(300)
.setStartDelay(400)
.translationY(0)
.setInterpolator(new OvershootInterpolator(1.0f))
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animateSignupContainerContents();
}
});
}
private void animateSignupContainerContents() {
binding.tvSignupTitle.animate()
.translationY(0)
.setDuration(400)
.setInterpolator(new DecelerateInterpolator());
binding.etEmailSignup.animate()
.translationY(0)
.setDuration(300)
.setInterpolator(new DecelerateInterpolator());
binding.etPasswordSignup.animate()
.translationY(0)
.setDuration(200)
.setInterpolator(new DecelerateInterpolator());
binding.btnSignup.animate()
.translationY(0)
.setDuration(100)
.setInterpolator(new DecelerateInterpolator());
}
// LOGIN
private void showLogin() {
binding.loginContainer.setVisibility(View.VISIBLE);
binding.tvNotRegistered.setVisibility(View.VISIBLE);
binding.loginContainer.animate()
.setDuration(300)
.setInterpolator(new OvershootInterpolator(1.0f))
.translationY(0)
.setStartDelay(300);
binding.tvNotRegistered.animate()
.setDuration(300)
.setStartDelay(400)
.translationY(0)
.setInterpolator(new OvershootInterpolator(1.0f))
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
animateLoginContainerContents();
}
});
}
private void animateLoginContainerContents() {
binding.tvLoginTitle.animate()
.translationY(0)
.setDuration(400)
.setInterpolator(new DecelerateInterpolator());
binding.etEmail.animate()
.translationY(0)
.setDuration(300)
.setInterpolator(new DecelerateInterpolator());
binding.etPassword.animate()
.translationY(0)
.setDuration(200)
.setInterpolator(new DecelerateInterpolator());
binding.btnLogin.animate()
.translationY(0)
.setDuration(100)
.setInterpolator(new DecelerateInterpolator());
}
}
対応する xml を使用:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="mango.matts.MainActivity">
<RelativeLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_login_gradient">
<include layout="@layout/anchors"/>
<!--Start login-->
<LinearLayout android:id="@+id/loginContainer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@android:color/white"
android:elevation="@dimen/material_dialog_elevation"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/login_container_padding_vertical"
android:paddingBottom="@dimen/login_container_padding_vertical"
android:paddingEnd="@dimen/login_container_padding_horizontal"
android:paddingStart="@dimen/login_container_padding_horizontal"
android:layout_marginBottom="@dimen/login_container_margin_bottom">
<TextView android:id="@+id/tvLoginTitle"
style="@style/MaterialTypography.Regular.Title"
android:layout_gravity="center_horizontal"
android:layout_width="@dimen/login_content_width"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/login_text_margin_bottom"
android:textAlignment="center"
android:text="@string/login"/>
<EditText android:id="@+id/etEmail"
android:inputType="textEmailAddress"
android:hint="@string/email"
android:layout_width="match_parent"
android:layout_marginBottom="@dimen/login_text_margin_bottom"
android:layout_height="wrap_content" />
<EditText android:id="@+id/etPassword"
android:inputType="textPassword"
android:hint="@string/password"
android:layout_marginBottom="@dimen/login_text_margin_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button android:id="@+id/btnLogin"
android:text="@string/login"
android:textAllCaps="true"
style="@style/MaterialTypography.Regular.Button"
android:textColor="@android:color/white"
android:backgroundTint="@color/colorAccent"
android:layout_width="match_parent"
android:layout_height="@dimen/btn_login_height" />
</LinearLayout>
<TextView android:id="@+id/tvNotRegistered"
android:layout_centerHorizontal="true"
android:layout_below="@+id/loginContainer"
style="@style/MaterialTypography.Regular"
android:textColor="@android:color/white"
android:text="@string/notRegisteredSignup"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!--End login-->
<!--Start Signup-->
<LinearLayout android:id="@+id/signupContainer"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@android:color/white"
android:elevation="@dimen/material_dialog_elevation"
android:layout_marginStart="@dimen/activity_horizontal_margin"
android:layout_marginEnd="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/login_container_padding_vertical"
android:paddingBottom="@dimen/login_container_padding_vertical"
android:paddingEnd="@dimen/login_container_padding_horizontal"
android:paddingStart="@dimen/login_container_padding_horizontal"
android:layout_marginBottom="@dimen/login_container_margin_bottom">
<TextView android:id="@+id/tvSignupTitle"
style="@style/MaterialTypography.Regular.Title"
android:layout_gravity="center_horizontal"
android:layout_width="@dimen/login_content_width"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/login_text_margin_bottom"
android:textAlignment="center"
android:text="@string/signup"/>
<EditText android:id="@+id/etEmailSignup"
android:inputType="textEmailAddress"
android:hint="@string/email"
android:layout_width="match_parent"
android:layout_marginBottom="@dimen/login_text_margin_bottom"
android:layout_height="wrap_content"/>
<EditText android:id="@+id/etPasswordSignup"
android:inputType="textPassword"
android:hint="@string/password"
android:layout_marginBottom="@dimen/login_text_margin_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button android:id="@+id/btnSignup"
android:text="@string/signup"
android:textAllCaps="true"
style="@style/MaterialTypography.Regular.Button"
android:textColor="@android:color/white"
android:backgroundTint="@color/colorAccent"
android:layout_width="match_parent"
android:layout_height="@dimen/btn_login_height" />
</LinearLayout>
<TextView android:id="@+id/tvAlreadyHaveAAccount"
android:layout_centerHorizontal="true"
android:layout_below="@+id/signupContainer"
style="@style/MaterialTypography.Regular"
android:textColor="@android:color/white"
android:text="@string/alreadyAMemberLogin"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>