package tk.wasdennnoch.androidn_ify.phone.emergency;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import tk.wasdennnoch.androidn_ify.R;
import tk.wasdennnoch.androidn_ify.XposedHook;
import tk.wasdennnoch.androidn_ify.ui.emergency.view.ViewInfoActivity;
import tk.wasdennnoch.androidn_ify.utils.ResourceUtils;
@SuppressWarnings("WeakerAccess")
public class EmergencyButtonWrapper implements View.OnClickListener {
private static final String TAG = "EmergencyButton";
private static final long HIDE_DELAY = 3000;
private static final int RIPPLE_DURATION = 600;
private static final long RIPPLE_PAUSE = 1000;
private final Interpolator mFastOutLinearInInterpolator;
private final Context mContext;
private final FrameLayout mLayout;
private final Button mButton;
private final ViewGroup mSelectedContainer;
private final TextView mSelectedLabel;
private final View mRippleView;
private final TextView mLaunchHint;
private boolean mHiding;
public EmergencyButtonWrapper(Context context, ViewGroup parent) {
mContext = context;
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_linear_in);
ResourceUtils res = ResourceUtils.getInstance(context);
mLayout = (FrameLayout) LayoutInflater.from(context).inflate(
res.getLayout(R.layout.emergency_button),
parent,
false); // We don't want the button to be the last view in its parent but the first, so add it later
parent.addView(mLayout, 0);
mButton = (Button) mLayout.findViewById(R.id.button);
mSelectedContainer = (ViewGroup) mLayout.findViewById(R.id.selected_container);
mSelectedLabel = (TextView) mLayout.findViewById(R.id.selected_label);
mRippleView = mLayout.findViewById(R.id.ripple_view);
mLaunchHint = (TextView) mLayout.findViewById(R.id.launch_hint);
mButton.setOnClickListener(this);
mSelectedContainer.setOnClickListener(this);
// Need to set text here because otherwise it would use the Dialer's resources
mButton.setText(res.getString(R.string.emergency_info));
mLaunchHint.setText(res.getString(R.string.emergency_info_launch_hint));
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
XposedHook.logI("androidn_ify", "click button");
if (((AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE)).isTouchExplorationEnabled()) {
startEmergencyActivity();
} else {
revealTheButton((Button) v);
}
break;
case R.id.selected_container:
XposedHook.logI("androidn_ify", "click select container");
if (!mHiding) {
startEmergencyActivity();
}
break;
}
}
private void startEmergencyActivity() {
try {
XposedHook.logI("androidn_ify", "try");
mContext.startActivity(new Intent("tk.wasdennnoch.androidn_ify.EMERGENCY_ASSISTANCE")
.setClassName("tk.wasdennnoch.androidn_ify", ViewInfoActivity.class.getName()).setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS));
} catch (Exception e) {
XposedHook.logI("androidn_ify", "catch");
XposedHook.logE(TAG, "Unable to start emergency activity!", e);
}
}
private void revealTheButton(Button v) {
XposedHook.logD("androidn_ify", "reveal");
mSelectedContainer.setVisibility(View.VISIBLE);
int centerX = v.getLeft() + v.getWidth() / 2;
int centerY = v.getTop() + v.getHeight() / 2;
Animator reveal = ViewAnimationUtils.createCircularReveal( // TODO work out why this isn't working, same for hide
mSelectedContainer,
centerX,
centerY,
0,
Math.max(centerX, mSelectedContainer.getWidth() - centerX)
+ Math.max(centerY, mSelectedContainer.getHeight() - centerY));
reveal.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mButton.setVisibility(View.INVISIBLE);
}
});
reveal.start();
//animateHintText(mSelectedLabel, v, reveal);
animateHintText(mLaunchHint, v, reveal);
mSelectedLabel.setText(v.getText());
mLayout.postDelayed(mHideRunnable, HIDE_DELAY);
mLayout.postDelayed(mRippleRunnable, RIPPLE_PAUSE / 2);
// Transfer focus from the originally clicked button to the expanded button.
mSelectedContainer.requestFocus();
}
private void animateHintText(View selectedView, View v, Animator reveal) {
selectedView.setTranslationX(
(v.getLeft() + v.getWidth() / 2 - mSelectedContainer.getWidth() / 2) / 5);
selectedView.animate()
.setDuration(reveal.getDuration() / 3)
.setStartDelay(reveal.getDuration() / 5)
.translationX(0)
.setInterpolator(mFastOutLinearInInterpolator)
.start();
}
private void hideTheButton() {
XposedHook.logD("androidn_ify", "hide");
if (mHiding || mSelectedContainer.getVisibility() != View.VISIBLE) {
return;
}
mHiding = true;
mLayout.removeCallbacks(mHideRunnable);
View v = mButton;
v.setVisibility(View.VISIBLE);
int centerX = v.getLeft() + v.getWidth() / 2;
int centerY = v.getTop() + v.getHeight() / 2;
Animator reveal = ViewAnimationUtils.createCircularReveal(
mSelectedContainer,
centerX,
centerY,
Math.max(centerX, mSelectedContainer.getWidth() - centerX)
+ Math.max(centerY, mSelectedContainer.getHeight() - centerY),
0);
reveal.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mSelectedContainer.setVisibility(View.INVISIBLE);
mLayout.removeCallbacks(mRippleRunnable);
mHiding = false;
}
});
reveal.start();
// Transfer focus back to the originally clicked button.
if (mSelectedContainer.isFocused()) {
v.requestFocus();
}
}
private void startRipple() {
XposedHook.logD("androidn_ify", "ripple");
final View ripple = mRippleView;
ripple.animate().cancel();
ripple.setVisibility(View.VISIBLE);
Animator reveal = ViewAnimationUtils.createCircularReveal(
ripple,
ripple.getLeft() + ripple.getWidth() / 2,
ripple.getTop() + ripple.getHeight() / 2,
0,
ripple.getWidth() / 2);
reveal.setDuration(RIPPLE_DURATION);
reveal.start();
ripple.setAlpha(0);
ripple.animate().alpha(1).setDuration(RIPPLE_DURATION / 2)
.withEndAction(new Runnable() {
@Override
public void run() {
ripple.animate().alpha(0).setDuration(RIPPLE_DURATION / 2)
.withEndAction(new Runnable() {
@Override
public void run() {
ripple.setVisibility(View.INVISIBLE);
mLayout.postDelayed(mRippleRunnable, RIPPLE_PAUSE);
}
}).start();
}
}).start();
}
private final Runnable mHideRunnable = new Runnable() {
@Override
public void run() {
if (!mLayout.isAttachedToWindow()) return;
hideTheButton();
}
};
private final Runnable mRippleRunnable = new Runnable() {
@Override
public void run() {
if (!mLayout.isAttachedToWindow()) return;
startRipple();
}
};
}