Merge pull request #458 from alexbakker/respect-anim-settings

Respect the global animator duration scale setting
This commit is contained in:
Michael Schättgen 2020-06-07 23:30:34 +02:00 committed by GitHub
commit 49c8c2d57d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 102 additions and 103 deletions

View file

@ -1,10 +1,8 @@
package com.beemdevelopment.aegis.ui; package com.beemdevelopment.aegis.ui;
import android.animation.ValueAnimator;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Toast; import android.widget.Toast;
@ -47,9 +45,6 @@ public abstract class AegisActivity extends AppCompatActivity implements AegisAp
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} }
// apply a dirty hack to make progress bars work even if animations are disabled
setGlobalAnimationDurationScale();
// register a callback to listen for lock events // register a callback to listen for lock events
_app.registerLockListener(this); _app.registerLockListener(this);
} }
@ -152,17 +147,6 @@ public abstract class AegisActivity extends AppCompatActivity implements AegisAp
return !(this instanceof MainActivity) && _app.isVaultLocked(); return !(this instanceof MainActivity) && _app.isVaultLocked();
} }
private void setGlobalAnimationDurationScale() {
float durationScale = Settings.Global.getFloat(getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 0);
if (durationScale != 1) {
try {
ValueAnimator.class.getMethod("setDurationScale", float.class).invoke(null, 1f);
} catch (Throwable t) {
Toast.makeText(this, R.string.progressbar_error, Toast.LENGTH_SHORT).show();
}
}
}
protected Theme getCurrentTheme() { protected Theme getCurrentTheme() {
return _currentTheme; return _currentTheme;
} }

View file

@ -224,7 +224,7 @@ public class EntryAdapter extends RecyclerView.Adapter<EntryHolder> implements I
notifyDataSetChanged(); notifyDataSetChanged();
} else { } else {
for (EntryHolder holder : _holders) { for (EntryHolder holder : _holders) {
holder.refreshCode(); holder.refresh();
} }
} }
} }

View file

@ -45,7 +45,7 @@ public class EntryHolder extends RecyclerView.ViewHolder {
private boolean _hidden; private boolean _hidden;
private PeriodProgressBar _progressBar; private TotpProgressBar _progressBar;
private View _view; private View _view;
private UiRefresher _refresher; private UiRefresher _refresher;
@ -84,8 +84,6 @@ public class EntryHolder extends RecyclerView.ViewHolder {
if (!_hidden) { if (!_hidden) {
refreshCode(); refreshCode();
} }
_progressBar.refresh();
} }
@Override @Override
@ -199,10 +197,17 @@ public class EntryHolder extends RecyclerView.ViewHolder {
public void startRefreshLoop() { public void startRefreshLoop() {
_refresher.start(); _refresher.start();
_progressBar.start();
} }
public void stopRefreshLoop() { public void stopRefreshLoop() {
_refresher.stop(); _refresher.stop();
_progressBar.stop();
}
public void refresh() {
_progressBar.restart();
refreshCode();
} }
public void refreshCode() { public void refreshCode() {

View file

@ -23,8 +23,6 @@ import com.beemdevelopment.aegis.R;
import com.beemdevelopment.aegis.SortCategory; import com.beemdevelopment.aegis.SortCategory;
import com.beemdevelopment.aegis.ViewMode; import com.beemdevelopment.aegis.ViewMode;
import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback; import com.beemdevelopment.aegis.helpers.SimpleItemTouchHelperCallback;
import com.beemdevelopment.aegis.helpers.UiRefresher;
import com.beemdevelopment.aegis.otp.TotpInfo;
import com.beemdevelopment.aegis.vault.VaultEntry; import com.beemdevelopment.aegis.vault.VaultEntry;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.ListPreloader; import com.bumptech.glide.ListPreloader;
@ -46,13 +44,11 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
private RecyclerView _recyclerView; private RecyclerView _recyclerView;
private RecyclerView.ItemDecoration _dividerDecoration; private RecyclerView.ItemDecoration _dividerDecoration;
private ViewPreloadSizeProvider<VaultEntry> _preloadSizeProvider; private ViewPreloadSizeProvider<VaultEntry> _preloadSizeProvider;
private PeriodProgressBar _progressBar; private TotpProgressBar _progressBar;
private boolean _showProgress; private boolean _showProgress;
private ViewMode _viewMode; private ViewMode _viewMode;
private LinearLayout _emptyStateView; private LinearLayout _emptyStateView;
private UiRefresher _refresher;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -97,19 +93,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
int resId = R.anim.layout_animation_fall_down; int resId = R.anim.layout_animation_fall_down;
LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(getContext(), resId); LayoutAnimationController animation = AnimationUtils.loadLayoutAnimation(getContext(), resId);
_recyclerView.setLayoutAnimation(animation); _recyclerView.setLayoutAnimation(animation);
_refresher = new UiRefresher(new UiRefresher.Listener() {
@Override
public void onRefresh() {
refresh(false);
}
@Override
public long getMillisTillNextRefresh() {
return TotpInfo.getMillisTillNextRotation(_adapter.getMostFrequentPeriod());
}
});
_emptyStateView = view.findViewById(R.id.vEmptyList); _emptyStateView = view.findViewById(R.id.vEmptyList);
return view; return view;
@ -121,7 +104,6 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
@Override @Override
public void onDestroyView() { public void onDestroyView() {
_refresher.destroy();
super.onDestroyView(); super.onDestroyView();
} }
@ -175,8 +157,9 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
public void refresh(boolean hard) { public void refresh(boolean hard) {
if (_showProgress) { if (_showProgress) {
_progressBar.refresh(); _progressBar.restart();
} }
_adapter.refresh(hard); _adapter.refresh(hard);
} }
@ -224,13 +207,12 @@ public class EntryListView extends Fragment implements EntryAdapter.Listener {
public void onPeriodUniformityChanged(boolean isUniform, int period) { public void onPeriodUniformityChanged(boolean isUniform, int period) {
setShowProgress(isUniform); setShowProgress(isUniform);
if (_showProgress) { if (_showProgress) {
_refresher.stop();
_progressBar.setVisibility(View.VISIBLE); _progressBar.setVisibility(View.VISIBLE);
_progressBar.setPeriod(period); _progressBar.setPeriod(period);
_refresher.start(); _progressBar.start();
} else { } else {
_progressBar.setVisibility(View.GONE); _progressBar.setVisibility(View.GONE);
_refresher.stop(); _progressBar.stop();
} }
} }

View file

@ -1,54 +0,0 @@
package com.beemdevelopment.aegis.ui.views;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
import com.beemdevelopment.aegis.otp.TotpInfo;
import androidx.annotation.RequiresApi;
public class PeriodProgressBar extends ProgressBar {
private int _period;
public PeriodProgressBar(Context context) {
super(context);
}
public PeriodProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PeriodProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public PeriodProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setPeriod(int period) {
_period = period;
}
public void refresh() {
// reset the progress bar
int maxProgress = getMax();
setProgress(maxProgress);
// calculate the progress the bar should start at
long millisTillRotation = TotpInfo.getMillisTillNextRotation(_period);
long period = _period * maxProgress;
int currentProgress = maxProgress - (int) ((((double) period - millisTillRotation) / period) * maxProgress);
// start progress animation
ObjectAnimator animation = ObjectAnimator.ofInt(this, "progress", currentProgress, 0);
animation.setDuration(millisTillRotation);
animation.setInterpolator(new LinearInterpolator());
animation.start();
}
}

View file

@ -0,0 +1,82 @@
package com.beemdevelopment.aegis.ui.views;
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.otp.TotpInfo;
public class TotpProgressBar extends ProgressBar {
private int _period = 30;
private Handler _handler;
private float _animDurationScale;
public TotpProgressBar(Context context) {
super(context);
}
public TotpProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TotpProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public TotpProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public void setPeriod(int period) {
_period = period;
}
public void start() {
stop();
_handler = new Handler();
_animDurationScale = Settings.Global.getFloat(getContext().getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f);
refresh();
}
public void stop() {
if (_handler != null) {
_handler.removeCallbacksAndMessages(null);
_handler = null;
}
}
public void restart() {
stop();
start();
}
private void refresh() {
// calculate the current progress the bar should start at
int maxProgress = getMax();
long millisTillRotation = TotpInfo.getMillisTillNextRotation(_period);
int currentProgress = (int) (maxProgress * ((float) millisTillRotation / (_period * 1000)));
// start progress animation, compensating for any changes to the animator duration scale settings
int animPart = maxProgress / _period;
int animEnd = (currentProgress / animPart) * animPart;
int animPartDuration = (int) (1000 / _animDurationScale);
float animDurationFraction = (float) (currentProgress - animEnd) / animPart;
int realAnimDuration = (int) (1000 * animDurationFraction);
int animDuration = (int) (animPartDuration * animDurationFraction);
ObjectAnimator animation = ObjectAnimator.ofInt(this, "progress", currentProgress, animEnd);
animation.setDuration(animDuration);
animation.setInterpolator(new LinearInterpolator());
animation.start();
// the animation only lasts for (less than) one second, so restart it after that
_handler.postDelayed(this::refresh, realAnimDuration);
}
}

View file

@ -152,12 +152,12 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.beemdevelopment.aegis.ui.views.PeriodProgressBar <com.beemdevelopment.aegis.ui.views.TotpProgressBar
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="4dp" android:layout_height="4dp"
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:max="1000" android:max="5000"
android:layout_weight="1"/> android:layout_weight="1"/>
</LinearLayout> </LinearLayout>

View file

@ -151,7 +151,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.beemdevelopment.aegis.ui.views.PeriodProgressBar <com.beemdevelopment.aegis.ui.views.TotpProgressBar
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="3dp" android:layout_height="3dp"

View file

@ -150,7 +150,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.beemdevelopment.aegis.ui.views.PeriodProgressBar <com.beemdevelopment.aegis.ui.views.TotpProgressBar
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="3dp" android:layout_height="3dp"

View file

@ -6,14 +6,14 @@
android:background="?attr/background" android:background="?attr/background"
android:orientation="vertical"> android:orientation="vertical">
<com.beemdevelopment.aegis.ui.views.PeriodProgressBar <com.beemdevelopment.aegis.ui.views.TotpProgressBar
style="?android:attr/progressBarStyleHorizontal" style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="4dp" android:layout_height="4dp"
android:progressDrawable="@drawable/progress_horizontal" android:progressDrawable="@drawable/progress_horizontal"
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:visibility="gone" android:visibility="gone"
android:max="1000"/> android:max="5000"/>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent" android:layout_width="match_parent"