mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 09:47:40 +00: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 android.view.WindowManager
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
|
import androidx.core.view.isGone
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.interpolator.view.animation.FastOutLinearInInterpolator
|
import androidx.interpolator.view.animation.FastOutLinearInInterpolator
|
||||||
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
|
import androidx.interpolator.view.animation.LinearOutSlowInInterpolator
|
||||||
@ -97,10 +98,8 @@ class MainActivity : BaseMainActivity<MainViewModel, ActivityMainMd2Binding>() {
|
|||||||
|
|
||||||
getScreen(section)?.navigate()
|
getScreen(section)?.navigate()
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (!isRootFragment) {
|
||||||
if (!isRootFragment) {
|
requestNavigationHidden(requiresAnimation = savedInstanceState == null)
|
||||||
requestNavigationHidden()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,45 +119,13 @@ class MainActivity : BaseMainActivity<MainViewModel, ActivityMainMd2Binding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
internal fun requestNavigationHidden(hide: Boolean = true, requiresAnimation: Boolean = true) {
|
||||||
internal fun requestNavigationHidden(hide: Boolean = true) {
|
|
||||||
val bottomView = binding.mainNavigation
|
val bottomView = binding.mainNavigation
|
||||||
|
if (requiresAnimation) {
|
||||||
// A copy of HideBottomViewOnScrollBehavior's animation
|
bottomView.isVisible = true
|
||||||
|
bottomView.isHidden = hide
|
||||||
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()
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
animateTranslationY(
|
bottomView.isGone = hide
|
||||||
bottomView,
|
|
||||||
0,
|
|
||||||
225L,
|
|
||||||
LinearOutSlowInInterpolator()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.appbar.AppBarLayout>
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.topjohnwu.magisk.widget.ConcealableBottomNavigationView
|
||||||
android:id="@+id/main_navigation"
|
android:id="@+id/main_navigation"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -47,4 +47,8 @@
|
|||||||
</attr>
|
</attr>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="ConcealableView">
|
||||||
|
<attr name="state_hidden" format="boolean" />
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user