package com.llamacorp.equate.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.llamacorp.equate.R;
public class AnimatedHoldButton extends SecondaryTextButton {
private final int CLICK_HOLD_TIME;
protected float mSecAdditionalXOffset = getContext().getResources().
getDimensionPixelSize(R.dimen.button_secondary_text_additional_offset_x);
protected float mSecAdditionalYOffset = getContext().getResources().
getDimensionPixelSize(R.dimen.button_secondary_text_additional_offset_y);
private OnClickListener mClickListen = null;
private OnLongClickListener mLongClickListen = null;
private OnExtraLongClickListener mExtraLongClickListener = null;
private Handler mColorHoldHandler;
private boolean mLongClickPerformed = false;
private boolean mWaitingForExtraLongClick = false;
private Drawable mNormalDrawable;
private int mPressedColor;
//used to count up holding time
private int mHoldInc;
private String mPrimaryText;
public AnimatedHoldButton(Context context, AttributeSet attrs) {
super(context, attrs);
CLICK_HOLD_TIME = ViewUtils.getLongClickTimeout(context);
mPrimaryText = "";
mNormalDrawable = getBackground();
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AnimatedHoldButton, 0, 0);
try {
mPrimaryText = ta.getString(R.styleable.AnimatedHoldButton_primary_text);
mPressedColor = ta.getColor(R.styleable.AnimatedHoldButton_pressed_color,
ContextCompat.getColor(context, R.color.op_button_pressed));
} finally {
ta.recycle();
}
//this is needed for so paint knows what to measure in layoutText
setText(mPrimaryText);
}
@Override
protected void findSecondaryTextCoordinates() {
mSecXCord = mButtonWidth - mSecTextWidth - mSecAdditionalXOffset;
mSecYCord = 0 + mSecTextHeight + mSecAdditionalYOffset;
}
/**
* Setup custom clicking and long clicking handlers
* Click will be performed if button is pressed down and released
* before the long click timeout. As the long click timeout is
* expiring, button's color will change and finally flash at the timeout
* event, at which point the long click function will be called.
*/
@SuppressWarnings("deprecation") //for setBackgroundDrawable
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mHoldInc = 0;
if (mColorHoldHandler != null) return true;
mColorHoldHandler = new Handler();
mColorHoldHandler.postDelayed(mColorRunnable, 10);
break;
case MotionEvent.ACTION_UP:
if (mColorHoldHandler == null) return true;
if (!mLongClickPerformed)
clickButton();
mLongClickPerformed = false;
mWaitingForExtraLongClick = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
setBackground(mNormalDrawable);
else setBackgroundDrawable(mNormalDrawable);
mColorHoldHandler.removeCallbacks(mColorRunnable);
mColorHoldHandler = null;
postInvalidate();
break;
}
return true;
}
//set up the runnable for when button is held down
Runnable mColorRunnable = new Runnable() {
private static final int NUM_COLOR_CHANGES = 10;
private Integer mGradStartCol, mGradEndCol, mAccentColor, mFinalColor;
@Override
public void run() {
initializeColors();
if (mWaitingForExtraLongClick){
extraLongClickButton();
return;
}
//after hold operation is performed and 100ms is up, set final color
if (mLongClickPerformed){
setBackgroundColor(mFinalColor);
//set up another delay to wait for a very long click
mColorHoldHandler.postDelayed(this, 2000);
mWaitingForExtraLongClick = true;
return;
}
//color the button black for a second and perform long click operation
if (mHoldInc == NUM_COLOR_CHANGES){
longClickButton();
mLongClickPerformed = true;
setBackgroundColor(mAccentColor);
//only post again so it runs to catch the final bit of code
mColorHoldHandler.postDelayed(this, 100);
return;
}
mColorHoldHandler.postDelayed(this, CLICK_HOLD_TIME / NUM_COLOR_CHANGES);
float deltaRed = (float) Color.red(mGradStartCol) + ((float) Color.red(mGradEndCol) - (float) Color.red(mGradStartCol)) * ((float) mHoldInc) / ((float) NUM_COLOR_CHANGES);
float deltaGreen = (float) Color.green(mGradStartCol) + ((float) Color.green(mGradEndCol) - (float) Color.green(mGradStartCol)) * ((float) mHoldInc) / ((float) NUM_COLOR_CHANGES);
float deltaBlue = (float) Color.blue(mGradStartCol) + ((float) Color.blue(mGradEndCol) - (float) Color.blue(mGradStartCol)) * ((float) mHoldInc) / ((float) NUM_COLOR_CHANGES);
setBackgroundColor(Color.argb(255, (int) deltaRed, (int) deltaGreen, (int) deltaBlue));
mHoldInc++;
}
/**
* Helper method so colors only get initialed once
*/
private void initializeColors() {
if (mGradStartCol == null){
mGradStartCol = mPressedColor;
mGradEndCol = ContextCompat.getColor(getContext(),
R.color.op_button_long_press_accent);
mAccentColor = mPressedColor;
mFinalColor = mPressedColor;
}
}
};
/**
* Calls listener's onClick, which gets setup by code controlling button
*/
private void clickButton() {
if (mClickListen != null)
mClickListen.onClick(this);
}
/**
* Calls listener's onLongClick, which gets setup by code controlling button
*/
private void longClickButton() {
if (mLongClickListen != null)
mLongClickListen.onLongClick(this);
}
private void extraLongClickButton() {
if (mExtraLongClickListener != null)
mExtraLongClickListener.onExtraLongClick(this);
}
public void setPrimaryText(CharSequence text) {
super.setText(text);
mPrimaryText = text.toString();
}
@Override
protected String getPrimaryText() {
if (mPrimaryText == null)
return "";
return mPrimaryText;
}
@Override
public void setOnClickListener(OnClickListener l) {
mClickListen = l;
}
@Override
public void setOnLongClickListener(OnLongClickListener l) {
mLongClickListen = l;
}
public void setOnExtraLongClickListener(OnExtraLongClickListener l) {
mExtraLongClickListener = l;
}
public interface OnExtraLongClickListener {
void onExtraLongClick(View var1);
}
}