Calculator.java revision 741471e3e99760acd44f8536534ac6121af9b03f
14b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen/* 24b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * Copyright (C) 2014 The Android Open Source Project 34b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * 44b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * Licensed under the Apache License, Version 2.0 (the "License"); 54b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * you may not use this file except in compliance with the License. 64b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * You may obtain a copy of the License at 74b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * 84b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * http://www.apache.org/licenses/LICENSE-2.0 94b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * 104b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * Unless required by applicable law or agreed to in writing, software 114b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * distributed under the License is distributed on an "AS IS" BASIS, 124b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * See the License for the specific language governing permissions and 144b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen * limitations under the License. 154b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen */ 164b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 174b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenpackage com.android.calculator2; 184b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 194b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.Animator; 204b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.AnimatorListenerAdapter; 214b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.AnimatorSet; 224b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.ArgbEvaluator; 234b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.ObjectAnimator; 244b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.ValueAnimator; 254b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.animation.ValueAnimator.AnimatorUpdateListener; 264b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.app.Activity; 274b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.os.Bundle; 283b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassenimport android.support.v4.view.ViewPager; 294b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.text.Editable; 304b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.text.TextUtils; 314b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.text.TextWatcher; 324b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.view.KeyEvent; 334b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.view.View; 343d6ecaf4d3365eeaff75a4bedb57fbe136cf5f64ztenghuiimport android.view.ViewAnimationUtils; 354b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.view.View.OnLongClickListener; 364b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.view.animation.AccelerateDecelerateInterpolator; 374b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenimport android.widget.Button; 38fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassenimport android.widget.TextView; 39fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen 40fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassenimport com.android.calculator2.CalculatorEditText.OnTextSizeChangeListener; 41fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassenimport com.android.calculator2.CalculatorExpressionEvaluator.EvaluateCallback; 424b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 434b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassenpublic class CalculatorActivity extends Activity 44fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen implements OnTextSizeChangeListener, EvaluateCallback, OnLongClickListener { 454b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 464b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public static final String CALCULATOR_ACTIVITY_CURRENT_STATE = 474b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen CalculatorActivity.class.getSimpleName() + "_currentState"; 484b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 494b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private enum CalculatorState { 504b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen INPUT, EVALUATE, RESULT, ERROR 514b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 524b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 534b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private final TextWatcher mFormulaTextWatcher = new TextWatcher() { 544b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 554b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) { 564b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 574b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 584b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 594b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onTextChanged(CharSequence charSequence, int start, int count, int after) { 604b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 614b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 624b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 634b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void afterTextChanged(Editable editable) { 644b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen setState(CalculatorState.INPUT); 654b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mEvaluator.evaluate(editable, CalculatorActivity.this); 664b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 674b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen }; 684b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 69741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen private final Editable.Factory mFormulaEditableFactory = new Editable.Factory() { 70741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen @Override 71741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen public Editable newEditable(CharSequence source) { 72741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen return new CalculatorExpressionBuilder(CalculatorActivity.this, source, 73741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen mCurrentState == CalculatorState.INPUT); 74741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen } 75741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen }; 76741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen 774b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private CalculatorState mCurrentState; 784b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private CalculatorExpressionEvaluator mEvaluator; 794b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 804b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private CalculatorEditText mFormulaEditText; 814b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private CalculatorEditText mResultEditText; 824b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 833b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen private ViewPager mPadViewPager; 843b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen 854b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private View mRevealView; 864b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private View mDeleteButton; 874b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private View mClearButton; 884b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 894b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private Animator mCurrentAnimator; 904b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 914b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 924b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen protected void onCreate(Bundle savedInstanceState) { 934b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen super.onCreate(savedInstanceState); 944b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen setContentView(R.layout.activity_calculator); 954b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 96741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen if (savedInstanceState == null) { 97741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen savedInstanceState = Bundle.EMPTY; 98741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen } 994b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1004b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText = (CalculatorEditText) findViewById(R.id.formula); 1014b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText = (CalculatorEditText) findViewById(R.id.result); 1024b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1033b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen mPadViewPager = (ViewPager) findViewById(R.id.pad_pager); 1043b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen 1054b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mRevealView = findViewById(R.id.reveal); 1064b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mDeleteButton = findViewById(R.id.del); 1074b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mClearButton = findViewById(R.id.clr); 1084b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 109741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen setState(CalculatorState.values()[savedInstanceState.getInt( 110741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen CALCULATOR_ACTIVITY_CURRENT_STATE, CalculatorState.INPUT.ordinal())]); 111741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen mEvaluator = new CalculatorExpressionEvaluator(this); 112741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen 113741471e3e99760acd44f8536534ac6121af9b03fJustin Klaassen mFormulaEditText.setEditableFactory(mFormulaEditableFactory); 1144b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.addTextChangedListener(mFormulaTextWatcher); 115fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen mFormulaEditText.setOnTextSizeChangeListener(this); 116fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen 1174b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mDeleteButton.setOnLongClickListener(this); 1184b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1194b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1204b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 1214b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen protected void onSaveInstanceState(Bundle outState) { 1224b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen super.onSaveInstanceState(outState); 1234b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen outState.putInt(CALCULATOR_ACTIVITY_CURRENT_STATE, mCurrentState.ordinal()); 1244b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1254b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1264b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private void setState(CalculatorState state) { 1274b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (mCurrentState != state) { 1284b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mCurrentState = state; 1294b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1304b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (state == CalculatorState.RESULT || state == CalculatorState.ERROR) { 1314b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mDeleteButton.setVisibility(View.GONE); 1324b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mClearButton.setVisibility(View.VISIBLE); 1334b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } else { 1344b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mDeleteButton.setVisibility(View.VISIBLE); 1354b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mClearButton.setVisibility(View.GONE); 1364b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1374b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1384b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (state == CalculatorState.ERROR) { 1394b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int errorColor = getResources().getColor(R.color.calculator_error_color); 1404b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.setTextColor(errorColor); 1414b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setTextColor(errorColor); 1424b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getWindow().setStatusBarColor(errorColor); 1434b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } else { 1444b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.setTextColor( 1454b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getResources().getColor(R.color.display_formula_text_color)); 1464b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setTextColor( 1474b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getResources().getColor(R.color.display_result_text_color)); 1484b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getWindow().setStatusBarColor( 1494b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getResources().getColor(R.color.calculator_accent_color)); 1504b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1514b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1524b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1534b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1544b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 1553b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen public void onBackPressed() { 1563b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen if (mPadViewPager == null || mPadViewPager.getCurrentItem() == 0) { 1573b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen // If the user is currently looking at the first pad (or the pad is not paged), 1583b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen // allow the system to handle the Back button. 1593b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen super.onBackPressed(); 1603b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen } else { 1613b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen // Otherwise, select the previous pad. 1623b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen mPadViewPager.setCurrentItem(mPadViewPager.getCurrentItem() - 1); 1633b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen } 1643b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen } 1653b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen 1663b4d13d528a14a0f46e7ae022357dfde90a307adJustin Klaassen @Override 1674b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onUserInteraction() { 1684b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen super.onUserInteraction(); 1694b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1704b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // If there's an animation in progress, cancel it so the user interaction can be handled 1714b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // immediately. 1724b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (mCurrentAnimator != null) { 1734b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mCurrentAnimator.cancel(); 1744b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1754b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1764b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 1774b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onButtonClick(View view) { 1784b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen switch (view.getId()) { 1794b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.eq: 1804b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (mCurrentState != CalculatorState.INPUT) { 1814b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.getEditableText().clear(); 1824b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } else { 1834b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen setState(CalculatorState.EVALUATE); 1844b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mEvaluator.evaluate(mFormulaEditText.getText(), this); 1854b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 1864b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen break; 1874b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.del: 1884b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.dispatchKeyEvent( 1894b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)); 1904b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen break; 1914b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.clr: 1924b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen onClear(view); 1934b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen break; 1944b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.fun_cos: 1954b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.fun_ln: 1964b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.fun_log: 1974b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.fun_sin: 1984b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen case R.id.fun_tan: 1994b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // add left paren after functions 2004b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.append(((Button) view).getText() + "("); 2014b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen break; 2024b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen default: 2034b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.append(((Button) view).getText()); 2044b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen break; 2054b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2064b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2074b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2084b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 2094b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public boolean onLongClick(View view) { 2104b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (view.getId() == R.id.del) { 2114b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen onClear(view); 2124b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen return true; 2134b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2144b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen return false; 2154b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2164b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2174b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 2184b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onEvaluate(String expr, String result, String error) { 2194b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen if (mCurrentState == CalculatorState.INPUT) { 2204b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setText(result); 2214b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } else if (!TextUtils.isEmpty(error)) { 2224b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen setState(CalculatorState.ERROR); 2234b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setText(error); 2244b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } else if (!TextUtils.isEmpty(result)) { 2254b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen onResult(result); 2264b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } else if (mCurrentState == CalculatorState.EVALUATE) { 2274b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // The current expression cannot be evaluated -> return to the input state. 2284b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen setState(CalculatorState.INPUT); 2294b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2304b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2314b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 232fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen @Override 233fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen public void onTextSizeChanged(final TextView textView, float oldSize) { 234fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen if (mCurrentState != CalculatorState.INPUT) { 235fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen // Only animate text changes that occur from user input. 236fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen return; 237fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen } 238fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen 239fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen // Calculate the values needed to perform the scale and translation animations, 240fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen // maintaining the same apparent baseline for the displayed text. 241fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen final float textScale = oldSize / textView.getTextSize(); 242fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen final float translationX = (1.0f - textScale) * 243fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen (textView.getWidth() / 2.0f - textView.getPaddingEnd()); 244fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen final float translationY = (1.0f - textScale) * 245fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen (textView.getHeight() / 2.0f - textView.getPaddingBottom()); 246fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen 247fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen final AnimatorSet animatorSet = new AnimatorSet(); 248fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen animatorSet.playTogether( 249fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen ObjectAnimator.ofFloat(textView, View.SCALE_X, textScale, 1.0f), 250fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen ObjectAnimator.ofFloat(textView, View.SCALE_Y, textScale, 1.0f), 251fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen ObjectAnimator.ofFloat(textView, View.TRANSLATION_X, translationX, 0.0f), 252fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen ObjectAnimator.ofFloat(textView, View.TRANSLATION_Y, translationY, 0.0f)); 253fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen animatorSet.setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime)); 254fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); 255fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen animatorSet.start(); 256fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen } 257fed941a1b4b2a3a011b8a17f486060f593db2f3cJustin Klaassen 2584b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private void onClear(View sourceView) { 2594b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int[] clearLocation = new int[2]; 2604b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen sourceView.getLocationInWindow(clearLocation); 2614b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen clearLocation[0] += sourceView.getWidth() / 2; 2624b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen clearLocation[1] += sourceView.getHeight() / 2; 2634b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2644b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int[] revealLocation = new int[2]; 2654b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mRevealView.getLocationInWindow(revealLocation); 2664b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2674b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int revealCenterX = clearLocation[0] - revealLocation[0]; 2684b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int revealCenterY = clearLocation[1] - revealLocation[1]; 2694b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2704b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final double x1_2 = Math.pow(mRevealView.getLeft() - revealCenterX, 2); 2714b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final double x2_2 = Math.pow(mRevealView.getRight() - revealCenterX, 2); 2724b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final double y_2 = Math.pow(mRevealView.getTop() - revealCenterY, 2); 2734b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final float revealRadius = (float) Math.max(Math.sqrt(x1_2 + y_2), Math.sqrt(x2_2 + y_2)); 2744b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2753d6ecaf4d3365eeaff75a4bedb57fbe136cf5f64ztenghui final Animator clearAnimator = 2763d6ecaf4d3365eeaff75a4bedb57fbe136cf5f64ztenghui ViewAnimationUtils.createCircularReveal(mRevealView, 2773d6ecaf4d3365eeaff75a4bedb57fbe136cf5f64ztenghui revealCenterX, revealCenterY, 0.0f, revealRadius); 2784b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen clearAnimator.setDuration( 2794b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getResources().getInteger(android.R.integer.config_longAnimTime)); 2804b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen clearAnimator.addListener(new AnimatorListenerAdapter() { 2814b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 2824b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onAnimationEnd(Animator animation) { 2834b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // Clear the formula after the reveal is finished, but before it's faded out. 2844b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.getEditableText().clear(); 2854b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 2864b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen }); 2874b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2884b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final Animator alphaAnimator = ObjectAnimator.ofFloat(mRevealView, View.ALPHA, 0.0f); 2894b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen alphaAnimator.setDuration( 2904b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen getResources().getInteger(android.R.integer.config_shortAnimTime)); 2914b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 2924b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final AnimatorSet animatorSet = new AnimatorSet(); 2934b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.play(clearAnimator).before(alphaAnimator); 2944b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); 2954b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.addListener(new AnimatorListenerAdapter() { 2964b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 2974b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onAnimationStart(Animator animator) { 2984b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mRevealView.setAlpha(1.0f); 2994b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mRevealView.setVisibility(View.VISIBLE); 3004b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3014b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3024b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 3034b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onAnimationEnd(Animator animator) { 3044b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mRevealView.setVisibility(View.GONE); 3054b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mCurrentAnimator = null; 3064b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3074b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen }); 3084b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3094b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mCurrentAnimator = animatorSet; 3104b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.start(); 3114b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3124b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3134b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen private void onResult(final String result) { 3144b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // Calculate the values needed to perform the scale and translation animations, 3154b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // accounting for how the scale will affect the final position of the text. 3164b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final float resultScale = 3174b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.getVariableTextSize(result) / mResultEditText.getTextSize(); 3184b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final float resultTranslationX = (1.0f - resultScale) * 3194b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen (mResultEditText.getWidth() / 2.0f - mResultEditText.getPaddingEnd()); 3204b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final float resultTranslationY = (1.0f - resultScale) * 3214b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen (mResultEditText.getHeight() / 2.0f - mResultEditText.getPaddingBottom()) + 3224b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen (mFormulaEditText.getBottom() - mResultEditText.getBottom()) + 3234b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen (mResultEditText.getPaddingBottom() - mFormulaEditText.getPaddingBottom()); 3244b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final float formulaTranslationY = -mFormulaEditText.getBottom(); 3254b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3264b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // Use a value animator to fade to the final text color over the course of the animation. 3274b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int resultTextColor = mResultEditText.getCurrentTextColor(); 3284b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final int formulaTextColor = mFormulaEditText.getCurrentTextColor(); 3294b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final ValueAnimator textColorAnimator = 3304b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen ValueAnimator.ofObject(new ArgbEvaluator(), resultTextColor, formulaTextColor); 3314b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen textColorAnimator.addUpdateListener(new AnimatorUpdateListener() { 3324b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 3334b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onAnimationUpdate(ValueAnimator valueAnimator) { 3344b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setTextColor((int) valueAnimator.getAnimatedValue()); 3354b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3364b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen }); 3374b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3384b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen final AnimatorSet animatorSet = new AnimatorSet(); 3394b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.playTogether( 3404b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen textColorAnimator, 3414b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen ObjectAnimator.ofFloat(mResultEditText, View.SCALE_X, resultScale), 3424b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen ObjectAnimator.ofFloat(mResultEditText, View.SCALE_Y, resultScale), 3434b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen ObjectAnimator.ofFloat(mResultEditText, View.TRANSLATION_X, resultTranslationX), 3444b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen ObjectAnimator.ofFloat(mResultEditText, View.TRANSLATION_Y, resultTranslationY), 3454b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen ObjectAnimator.ofFloat(mFormulaEditText, View.TRANSLATION_Y, formulaTranslationY)); 3464b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.setDuration(getResources().getInteger(android.R.integer.config_longAnimTime)); 3474b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); 3484b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.addListener(new AnimatorListenerAdapter() { 3494b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 3504b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onAnimationStart(Animator animation) { 3514b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setText(result); 3524b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3534b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3544b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen @Override 3554b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen public void onAnimationEnd(Animator animation) { 3564b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // Reset all of the values modified during the animation. 3574b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setTextColor(resultTextColor); 3584b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setScaleX(1.0f); 3594b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setScaleY(1.0f); 3604b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setTranslationX(0.0f); 3614b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mResultEditText.setTranslationY(0.0f); 3624b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.setTranslationY(0.0f); 3634b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3644b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen // Finally update the formula to use the current result. 3654b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mFormulaEditText.setText(result); 3664b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen setState(CalculatorState.RESULT); 3674b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3684b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mCurrentAnimator = null; 3694b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3704b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen }); 3714b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen 3724b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen mCurrentAnimator = animatorSet; 3734b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen animatorSet.start(); 3744b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen } 3754b3af0578b1a44038856bc56244aea8aaeac22d1Justin Klaassen} 376