Merge pull request #1165 from michaelschattgen/feature/disable-animations

Respect system animation setting
This commit is contained in:
Alexander Bakker 2023-08-30 15:17:26 +02:00 committed by GitHub
commit c19692b416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 124 additions and 26 deletions

View File

@ -0,0 +1,54 @@
package com.beemdevelopment.aegis.helpers;
import android.content.Context;
import android.provider.Settings;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
public class AnimationsHelper {
private AnimationsHelper() {
}
public static Animation loadScaledAnimation(Context context, int animationResId) {
return loadScaledAnimation(context, animationResId, Scale.ANIMATOR);
}
public static Animation loadScaledAnimation(Context context, int animationResId, Scale scale) {
Animation animation = AnimationUtils.loadAnimation(context, animationResId);
long newDuration = (long) (animation.getDuration() * scale.getValue(context));
animation.setDuration(newDuration);
return animation;
}
public static LayoutAnimationController loadScaledLayoutAnimation(Context context, int animationResId) {
return loadScaledLayoutAnimation(context, animationResId, Scale.ANIMATOR);
}
public static LayoutAnimationController loadScaledLayoutAnimation(Context context, int animationResId, Scale scale) {
LayoutAnimationController controller = AnimationUtils.loadLayoutAnimation(context, animationResId);
Animation animation = controller.getAnimation();
animation.setDuration((long) (animation.getDuration() * scale.getValue(context)));
return controller;
}
public enum Scale {
ANIMATOR(Settings.Global.ANIMATOR_DURATION_SCALE),
TRANSITION(Settings.Global.TRANSITION_ANIMATION_SCALE);
private final String _setting;
Scale(String setting) {
_setting = setting;
}
public float getValue(Context context) {
return Settings.Global.getFloat(context.getContentResolver(), _setting, 1.0f);
}
public boolean isZero(Context context) {
return getValue(context) == 0;
}
}
}

View File

@ -33,6 +33,7 @@ import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.encoding.Base32;
import com.beemdevelopment.aegis.encoding.EncodingException;
import com.beemdevelopment.aegis.encoding.Hex;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.helpers.DropdownHelper;
import com.beemdevelopment.aegis.helpers.EditTextHelper;
import com.beemdevelopment.aegis.helpers.IconViewHelper;
@ -376,12 +377,12 @@ public class EditEntryActivity extends AegisActivity {
private void openAdvancedSettings() {
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(220);
fadeOut.setDuration(220 * (long) AnimationsHelper.Scale.ANIMATOR.getValue(this));
_advancedSettingsHeader.startAnimation(fadeOut);
Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new AccelerateInterpolator());
fadeIn.setDuration(250);
fadeIn.setDuration(250 * (long) AnimationsHelper.Scale.ANIMATOR.getValue(this));
fadeOut.setAnimationListener(new SimpleAnimationEndListener((a) -> {
_advancedSettingsHeader.setVisibility(View.GONE);

View File

@ -6,16 +6,19 @@ import android.net.Uri;
import android.os.Bundle;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.view.animation.Animation;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.helpers.FabScrollHelper;
import com.beemdevelopment.aegis.icons.IconPack;
import com.beemdevelopment.aegis.icons.IconPackException;
@ -81,6 +84,16 @@ public class IconPacksManagerFragment extends Fragment implements IconPackAdapte
updateEmptyState();
}
@Override
@Nullable
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if (nextAnim != 0) {
return AnimationsHelper.loadScaledAnimation(requireContext(), nextAnim, AnimationsHelper.Scale.TRANSITION);
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
@Override
public void onRemoveIconPack(IconPack pack) {
Dialogs.showSecureDialog(new AlertDialog.Builder(requireContext())

View File

@ -3,14 +3,17 @@ package com.beemdevelopment.aegis.ui.fragments.preferences;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.animation.Animation;
import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.ui.dialogs.Dialogs;
import com.beemdevelopment.aegis.vault.VaultManager;
import com.beemdevelopment.aegis.vault.VaultRepositoryException;
@ -62,6 +65,16 @@ public abstract class PreferencesFragment extends PreferenceFragmentCompat {
return _result;
}
@Override
@Nullable
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if (nextAnim != 0) {
return AnimationsHelper.loadScaledAnimation(requireContext(), nextAnim, AnimationsHelper.Scale.TRANSITION);
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
public void setResult(Intent result) {
_result = result;
requireActivity().setResult(Activity.RESULT_OK, _result);

View File

@ -14,6 +14,7 @@ import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.ui.AegisActivity;
import java.lang.ref.WeakReference;
@ -135,7 +136,10 @@ public abstract class IntroBaseActivity extends AegisActivity implements IntroAc
Class<? extends SlideFragment> newSlide = _slides.get(pos);
if (!onBeforeSlideChanged(oldSlide, newSlide)) {
_pager.setCurrentItem(pos);
// We can't easily control the speed of the smooth scroll animation, but we
// can at least disable it if animations are disabled
boolean smoothScroll = !AnimationsHelper.Scale.TRANSITION.isZero(this);
_pager.setCurrentItem(pos, smoothScroll);
}
onAfterSlideChanged(oldSlide, newSlide);

View File

@ -4,7 +4,6 @@ import android.graphics.PorterDuff;
import android.os.Handler;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
@ -17,6 +16,7 @@ import com.beemdevelopment.aegis.AccountNamePosition;
import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.helpers.IconViewHelper;
import com.beemdevelopment.aegis.helpers.TextDrawableHelper;
import com.beemdevelopment.aegis.helpers.ThemeHelper;
@ -91,8 +91,8 @@ public class EntryHolder extends RecyclerView.ViewHolder {
_progressBar.getProgressDrawable().setColorFilter(primaryColorId, PorterDuff.Mode.SRC_IN);
_view.setBackground(_view.getContext().getResources().getDrawable(R.color.card_background));
_scaleIn = AnimationUtils.loadAnimation(view.getContext(), R.anim.item_scale_in);
_scaleOut = AnimationUtils.loadAnimation(view.getContext(), R.anim.item_scale_out);
_scaleIn = AnimationsHelper.loadScaledAnimation(view.getContext(), R.anim.item_scale_in);
_scaleOut = AnimationsHelper.loadScaledAnimation(view.getContext(), R.anim.item_scale_out);
_refresher = new UiRefresher(new UiRefresher.Listener() {
@Override
@ -379,10 +379,10 @@ public class EntryHolder extends RecyclerView.ViewHolder {
public void animateCopyText(boolean includeSlideAnimation) {
_animationHandler.removeCallbacksAndMessages(null);
Animation slideDownFadeIn = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.slide_down_fade_in);
Animation slideDownFadeOut = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.slide_down_fade_out);
Animation fadeOut = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.fade_out);
Animation fadeIn = AnimationUtils.loadAnimation(itemView.getContext(), R.anim.fade_in);
Animation slideDownFadeIn = AnimationsHelper.loadScaledAnimation(itemView.getContext(), R.anim.slide_down_fade_in);
Animation slideDownFadeOut = AnimationsHelper.loadScaledAnimation(itemView.getContext(), R.anim.slide_down_fade_out);
Animation fadeOut = AnimationsHelper.loadScaledAnimation(itemView.getContext(), R.anim.fade_out);
Animation fadeIn = AnimationsHelper.loadScaledAnimation(itemView.getContext(), R.anim.fade_in);
if (includeSlideAnimation) {
_profileCopied.startAnimation(slideDownFadeIn);

View File

@ -10,7 +10,6 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.LayoutAnimationController;
import android.widget.Button;
import android.widget.LinearLayout;
@ -30,6 +29,7 @@ import com.beemdevelopment.aegis.Preferences;
import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.SortCategory;
import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.helpers.MetricsHelper;
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
import com.beemdevelopment.aegis.helpers.ThemeHelper;
@ -101,6 +101,7 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
// set up the recycler view
_recyclerView = view.findViewById(R.id.rvKeyProfiles);
_recyclerView.setItemAnimator(null);
_recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
@ -141,10 +142,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
_touchHelper.attachToRecyclerView(_recyclerView);
_recyclerView.setAdapter(_adapter);
int resId = R.anim.layout_animation_fall_down;
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(requireContext(), resId);
_recyclerView.setLayoutAnimation(animation);
_refresher = new UiRefresher(new UiRefresher.Listener() {
@Override
public void onRefresh() {
@ -386,13 +383,25 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
if (focusEntry && position >= 0) {
if ((_recyclerView.canScrollVertically(1) && position > layoutManager.findLastCompletelyVisibleItemPosition())
|| (_recyclerView.canScrollVertically(-1) && position < layoutManager.findFirstCompletelyVisibleItemPosition())) {
boolean smoothScroll = !AnimationsHelper.Scale.TRANSITION.isZero(requireContext());
RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
private void handleScroll() {
_recyclerView.removeOnScrollListener(this);
_recyclerView.setOnTouchListener(null);
tempHighlightEntry(entry);
}
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
_recyclerView.removeOnScrollListener(this);
_recyclerView.setOnTouchListener(null);
tempHighlightEntry(entry);
if (smoothScroll && newState == RecyclerView.SCROLL_STATE_IDLE) {
handleScroll();
}
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
if (!smoothScroll) {
handleScroll();
}
}
};
@ -406,7 +415,13 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
return false;
});
_recyclerView.smoothScrollToPosition(position);
// We can't easily control the speed of the smooth scroll animation, but we
// can at least disable it if animations are disabled
if (smoothScroll) {
_recyclerView.smoothScrollToPosition(position);
} else {
_recyclerView.scrollToPosition(position);
}
} else {
tempHighlightEntry(entry);
}
@ -444,10 +459,9 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
}
public void runEntriesAnimation() {
final LayoutAnimationController controller =
AnimationUtils.loadLayoutAnimation(requireContext(), R.anim.layout_animation_fall_down);
LayoutAnimationController animationController = AnimationsHelper.loadScaledLayoutAnimation(requireContext(), R.anim.layout_animation_fall_down);
_recyclerView.setLayoutAnimation(controller);
_recyclerView.setLayoutAnimation(animationController);
_recyclerView.scheduleLayoutAnimation();
}

View File

@ -4,13 +4,13 @@ import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
import androidx.annotation.RequiresApi;
import com.beemdevelopment.aegis.helpers.AnimationsHelper;
import com.beemdevelopment.aegis.otp.TotpInfo;
public class TotpProgressBar extends ProgressBar {
@ -42,7 +42,7 @@ public class TotpProgressBar extends ProgressBar {
public void start() {
stop();
_handler = new Handler();
_animDurationScale = Settings.Global.getFloat(getContext().getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f);
_animDurationScale = AnimationsHelper.Scale.ANIMATOR.getValue(getContext());
refresh();
}

View File

@ -39,7 +39,6 @@
android:layout_height="0dp"
android:scrollbars="vertical"
android:id="@+id/rvKeyProfiles"
android:layoutAnimation="@anim/layout_animation_fall_down"
android:layout_weight="1"/>
<LinearLayout