mirror of
https://github.com/topjohnwu/Magisk
synced 2024-11-16 00:13:57 +01:00
Fix bottom nav sometimes not hide correctly
Replace homemade animation with StateListAnimator
This commit is contained in:
parent
ff8f3e766e
commit
bfe6bc3095
@ -11,6 +11,7 @@ import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.view.forEach
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.interpolator.view.animation.FastOutLinearInInterpolator
|
||||
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
|
||||
@ -97,10 +98,8 @@ class MainActivity : BaseMainActivity<MainViewModel, ActivityMainMd2Binding>() {
|
||||
|
||||
getScreen(section)?.navigate()
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
if (!isRootFragment) {
|
||||
requestNavigationHidden()
|
||||
}
|
||||
if (!isRootFragment) {
|
||||
requestNavigationHidden(requiresAnimation = savedInstanceState == null)
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,45 +119,13 @@ class MainActivity : BaseMainActivity<MainViewModel, ActivityMainMd2Binding>() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal fun requestNavigationHidden(hide: Boolean = true) {
|
||||
internal fun requestNavigationHidden(hide: Boolean = true, requiresAnimation: Boolean = true) {
|
||||
val bottomView = binding.mainNavigation
|
||||
|
||||
// A copy of HideBottomViewOnScrollBehavior's animation
|
||||
|
||||
fun animateTranslationY(
|
||||
view: View, targetY: Int, duration: Long, interpolator: TimeInterpolator
|
||||
) {
|
||||
view.tag = view
|
||||
.animate()
|
||||
.translationY(targetY.toFloat())
|
||||
.setInterpolator(interpolator)
|
||||
.setDuration(duration)
|
||||
.setListener(
|
||||
object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator) {
|
||||
view.tag = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
(bottomView.tag as? Animator)?.cancel()
|
||||
bottomView.clearAnimation()
|
||||
|
||||
if (hide) {
|
||||
animateTranslationY(
|
||||
bottomView,
|
||||
bottomView.measuredHeight,
|
||||
175L,
|
||||
FastOutLinearInInterpolator()
|
||||
)
|
||||
if (requiresAnimation) {
|
||||
bottomView.isVisible = true
|
||||
bottomView.isHidden = hide
|
||||
} else {
|
||||
animateTranslationY(
|
||||
bottomView,
|
||||
0,
|
||||
225L,
|
||||
LinearOutSlowInInterpolator()
|
||||
)
|
||||
bottomView.isGone = hide
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,136 @@
|
||||
package com.topjohnwu.magisk.widget;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.StateListAnimator;
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.interpolator.view.animation.FastOutLinearInInterpolator;
|
||||
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
import com.topjohnwu.magisk.R;
|
||||
|
||||
public class ConcealableBottomNavigationView extends BottomNavigationView {
|
||||
|
||||
private static final int[] STATE_SET = {
|
||||
R.attr.state_hidden
|
||||
};
|
||||
|
||||
private boolean isHidden;
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
this(context, attrs, R.attr.bottomNavigationStyle);
|
||||
}
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, R.style.Widget_Design_BottomNavigationView);
|
||||
}
|
||||
|
||||
public ConcealableBottomNavigationView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
private void recreateAnimator(int height) {
|
||||
Animator toHidden = ObjectAnimator.ofFloat(this, "translationY", height);
|
||||
toHidden.setDuration(175);
|
||||
toHidden.setInterpolator(new FastOutLinearInInterpolator());
|
||||
Animator toUnhidden = ObjectAnimator.ofFloat(this, "translationY", 0);
|
||||
toHidden.setDuration(225);
|
||||
toHidden.setInterpolator(new FastOutLinearInInterpolator());
|
||||
|
||||
StateListAnimator animator = new StateListAnimator();
|
||||
|
||||
animator.addState(STATE_SET, toHidden);
|
||||
animator.addState(new int[]{}, toUnhidden);
|
||||
|
||||
setStateListAnimator(animator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
recreateAnimator(getMeasuredHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] onCreateDrawableState(int extraSpace) {
|
||||
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
|
||||
if (isHidden()) {
|
||||
mergeDrawableStates(drawableState, STATE_SET);
|
||||
}
|
||||
return drawableState;
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return isHidden;
|
||||
}
|
||||
|
||||
public void setHidden(boolean raised) {
|
||||
if (isHidden != raised) {
|
||||
isHidden = raised;
|
||||
refreshDrawableState();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
SavedState state = new SavedState(super.onSaveInstanceState());
|
||||
state.isHidden = isHidden();
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
final SavedState ss = (SavedState) state;
|
||||
super.onRestoreInstanceState(ss.getSuperState());
|
||||
|
||||
if (ss.isHidden) {
|
||||
setHidden(isHidden);
|
||||
}
|
||||
}
|
||||
|
||||
static class SavedState extends View.BaseSavedState {
|
||||
|
||||
public boolean isHidden;
|
||||
|
||||
public SavedState(Parcel source) {
|
||||
super(source);
|
||||
isHidden = source.readByte() != 0;
|
||||
}
|
||||
|
||||
public SavedState(Parcelable superState) {
|
||||
super(superState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeByte(isHidden ? (byte) 1 : (byte) 0);
|
||||
}
|
||||
|
||||
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
|
||||
|
||||
@Override
|
||||
public SavedState createFromParcel(Parcel source) {
|
||||
return new SavedState(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SavedState[] newArray(int size) {
|
||||
return new SavedState[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||
<com.topjohnwu.magisk.widget.ConcealableBottomNavigationView
|
||||
android:id="@+id/main_navigation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -47,4 +47,8 @@
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="ConcealableView">
|
||||
<attr name="state_hidden" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user