想要给BottomSheetDialogFragment的弹出和消失加spring动画
1、遇到的问题
由于是spring的动效,无法使用下面设置windowAnimations的方法来
@Override
public void onActivityCreated(Bundle arg0) {
super.onActivityCreated(arg0);
getDialog().getWindow()
.getAttributes().windowAnimations = R.style.DialogAnimation;
}
<style name="DialogAnimation">
<item name="android:windowEnterAnimation">@anim/slide_up</item>
<item name="android:windowExitAnimation">@anim/slide_down</item></style>
无法在xml中使用spring的插值器。
2、解决方式
只能通过动态的方式来设置动效
animator.setInterpolator(new SpringInterpolator(4f));
animator.setDuration(407);
1、设置弹出动效
可以在bottomSheetDialogFragment中获取dialog然后对dialog设置如下监听:
dialog?.setOnShowListener {
when (animationStyle()) {
AnimationStyle.Low -> {
showAnimal(SHOW_LOW_TIME)
}
AnimationStyle.Height -> {
showAnimal(SHOW_LONG_TIME)
}
AnimationStyle.Middle -> {
showAnimal(SHOW_MIDDLE_TIME)
}
}
}
Show animal动效
private fun showAnimal(time: Long) {
root?.let {
it.alpha = 0f
it.translationY = it.height.toFloat() - ScreenUtils.getNavigationBarHeight(activity)
it.animate().alpha(1f).translationY(0f).setDuration(time)
.setInterpolator(SpringInterpolator(4f))
.start()
}
}
2、设置消失动画
由于BottomSheetDialogFragment的消失事件可能是cancel导致的也可能第dismiss方法调用导致的,并且在调试过程中发现当调用BottomSheetDialogFragment的onDismiss时弹框已经消失,所以不能在BottomSheetDialogFragment中通过设置监听和override ondismiss等方法来重新动画。
debug的时候发现BottomSheetDialogFragment消失时,都会调用到BottomSheetDialog中的dismiss方法,所以可以通过重写BottomSheetDialog的dismiss方法来实现消失动效。
1、如何在BottomSheetDialogFragment中重写BottomSheetDialog的dismiss方法?
自己创建BottomSheetDialogFragment中的BottomSheetDialog
通过查看BottomSheetDialogFragment代码可以发现BottomSheetDialog是
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
return new BottomSheetDialog(getContext(), getTheme());
}
创建的,所以可以重写这个方法来创建BottomSheetDialog
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
//这个地方创建自己的dialog
return AnimalBottomSheetDialog(requireContext(), theme,animationStyle())
}
其中AnimalBottomSheetDialog继承BottomSheetDialog,并且重写了dismiss方法
override fun dismiss() {
//添加动画,做完动画之后再调用super的dismiss
dismissAnimal(time) {
super.dismiss()
}
}
private fun dismissAnimal(time: Long, callback: () -> Unit) {
root?.let {
height = sheet?.height?.toFloat() ?: 0f
LogDelegator.d(
TAG,
"translationY ${it.translationY} height ${it.height} height1 $height"
)
it.animate().alpha(0f).translationY(height).setDuration(time)
.setInterpolator(SpringInterpolator(4f)).withEndAction {
callback.invoke()
} .start()
}
}
问题
主动调用BottomSheetFragment的dismiss或者dismissAllowingStateLoss方法时,会调用到DialogFragment的到dismissInternal中:
mDialog.dismiss();
if (!fromOnDismiss) {
// onDismiss() is always called on the main thread, so
// we mimic that behavior here. The difference here is that
// we don't post the message to ensure that the onDismiss()
// callback still happens before onDestroy()
if (Looper.myLooper() == mHandler.getLooper()) {
onDismiss(mDialog);
} else {
mHandler.post(mDismissRunnable);
}
}
}
mViewDestroyed = true;
if (mBackStackId >= 0) {
getParentFragmentManager().popBackStack(mBackStackId,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
mBackStackId = -1;
} else {
FragmentTransaction ft = getParentFragmentManager().beginTransaction();
ft.remove(this);
if (allowStateLoss) {
ft.commitAllowingStateLoss();
} else {
ft.commit();
}
}
会调用到BottomSheetDialogFragment的onStop()方法,DialogFragment的onStop方法如下
public void onStop() {
super.onStop();
if (mDialog != null) {
mDialog.hide();
}
}
由于onStop中调用了mDialog.hide()方法,导致dismiss方法中动画没做完就消失了,所以这里动效会有问题。
解决方法
重写RoundTopBottomSheetDialogFragment的dismiss和dismissAllowingStateLoss方法如下
override fun dismiss() {
//做完动画再调用这个方法
dismissAnimal(getAnimalTime()) {
super.dismiss()
}
}
override fun dismissAllowingStateLoss() {
dismissAnimal(getAnimalTime()) {
super.dismissAllowingStateLoss()
}
}