package ru.adonixis.submitcreditcardflow; import android.animation.Animator; import android.animation.AnimatorInflater; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.Resources; import android.databinding.DataBindingUtil; import android.graphics.Point; import android.os.Bundle; import android.os.Handler; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.text.Editable; import android.text.TextWatcher; import android.util.DisplayMetrics; import android.view.Display; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.TextView; import android.widget.Toast; import ru.adonixis.submitcreditcardflow.databinding.ActivitySubmitCreditCardBinding; public class SubmitCreditCardActivity extends AppCompatActivity { private boolean showingGray = true; private AnimatorSet inSet; private AnimatorSet outSet; private ActivitySubmitCreditCardBinding activitySubmitCreditCardBinding; private Card card; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); activitySubmitCreditCardBinding = DataBindingUtil.setContentView(this, R.layout.activity_submit_credit_card); card = new Card(); setSupportActionBar(activitySubmitCreditCardBinding.toolbar); View.OnClickListener onHelpClickListener = new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(SubmitCreditCardActivity.this, "The CVV Number (\"Card Verification Value\") is a 3 or 4 digit number on your credit and debit cards", Toast.LENGTH_LONG).show(); } }; activitySubmitCreditCardBinding.iconHelpGray.setOnClickListener(onHelpClickListener); activitySubmitCreditCardBinding.iconHelpBlue.setOnClickListener(onHelpClickListener); activitySubmitCreditCardBinding.inputEditCardNumber.addTextChangedListener(new TextWatcher() { private boolean lock; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (s.length() != 0) { flipToBlue(); } } @Override public void afterTextChanged(Editable s) { if (lock || s.length() > 16) { return; } lock = true; for (int i = 4; i < s.length(); i += 5) { if (s.toString().charAt(i) != ' ') { s.insert(i, " "); } } lock = false; } }); activitySubmitCreditCardBinding.inputEditExpiredDate.addTextChangedListener(new TextWatcher() { private boolean lock; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (lock || s.length() > 4) { return; } lock = true; if (s.length() > 2 && s.toString().charAt(2) != '/') { s.insert(2, "/"); } lock = false; } }); Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; int height = size.y; PagerAdapter adapter = new MyPagerAdapter(); activitySubmitCreditCardBinding.viewPager.setAdapter(adapter); activitySubmitCreditCardBinding.viewPager.setClipToPadding(false); activitySubmitCreditCardBinding.viewPager.setPadding(width / 4, 0, width / 4, 0); activitySubmitCreditCardBinding.viewPager.setPageMargin(width / 14); activitySubmitCreditCardBinding.viewPager.setPagingEnabled(false); activitySubmitCreditCardBinding.viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { switch (position) { case 0: updateProgressBar(25); activitySubmitCreditCardBinding.inputEditCardNumber.setFocusableInTouchMode(true); activitySubmitCreditCardBinding.inputEditExpiredDate.setFocusable(false); activitySubmitCreditCardBinding.inputEditCardHolder.setFocusable(false); activitySubmitCreditCardBinding.inputEditCvvCode.setFocusable(false); activitySubmitCreditCardBinding.inputEditCardNumber.requestFocus(); return; case 1: updateProgressBar(50); activitySubmitCreditCardBinding.inputEditCardNumber.setFocusable(false); activitySubmitCreditCardBinding.inputEditExpiredDate.setFocusableInTouchMode(true); activitySubmitCreditCardBinding.inputEditCardHolder.setFocusable(false); activitySubmitCreditCardBinding.inputEditCvvCode.setFocusable(false); activitySubmitCreditCardBinding.inputEditExpiredDate.requestFocus(); return; case 2: updateProgressBar(75); activitySubmitCreditCardBinding.inputEditCardNumber.setFocusable(false); activitySubmitCreditCardBinding.inputEditExpiredDate.setFocusable(false); activitySubmitCreditCardBinding.inputEditCardHolder.setFocusableInTouchMode(true); activitySubmitCreditCardBinding.inputEditCvvCode.setFocusable(false); activitySubmitCreditCardBinding.inputEditCardHolder.requestFocus(); return; case 3: updateProgressBar(100); activitySubmitCreditCardBinding.inputEditCardNumber.setFocusable(false); activitySubmitCreditCardBinding.inputEditExpiredDate.setFocusable(false); activitySubmitCreditCardBinding.inputEditCardHolder.setFocusable(false); activitySubmitCreditCardBinding.inputEditCvvCode.setFocusableInTouchMode(true); activitySubmitCreditCardBinding.inputEditCvvCode.requestFocus(); return; case 4: activitySubmitCreditCardBinding.inputEditCardNumber.setFocusable(false); activitySubmitCreditCardBinding.inputEditExpiredDate.setFocusable(false); activitySubmitCreditCardBinding.inputEditCardHolder.setFocusable(false); activitySubmitCreditCardBinding.inputEditCvvCode.setFocusable(false); return; } } @Override public void onPageScrollStateChanged(int state) { } }); TextView.OnEditorActionListener onEditorActionListener = new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { boolean handled = false; if (actionId == EditorInfo.IME_ACTION_NEXT) { activitySubmitCreditCardBinding.viewPager.setCurrentItem(activitySubmitCreditCardBinding.viewPager.getCurrentItem() + 1); handled = true; } if (actionId == EditorInfo.IME_ACTION_DONE) { submit(); handled = true; } return handled; } }; activitySubmitCreditCardBinding.inputEditCardNumber.setOnEditorActionListener(onEditorActionListener); activitySubmitCreditCardBinding.inputEditExpiredDate.setOnEditorActionListener(onEditorActionListener); activitySubmitCreditCardBinding.inputEditCardHolder.setOnEditorActionListener(onEditorActionListener); activitySubmitCreditCardBinding.inputEditCvvCode.setOnEditorActionListener(onEditorActionListener); activitySubmitCreditCardBinding.inputEditCardNumber.requestFocus(); inSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.card_flip_in); outSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.card_flip_out); } private class MyPagerAdapter extends PagerAdapter { @Override public Object instantiateItem(ViewGroup container, int position) { int resId = 0; switch (position) { case 0: resId = R.id.input_layout_card_number; break; case 1: resId = R.id.input_layout_expired_date; break; case 2: resId = R.id.input_layout_card_holder; break; case 3: resId = R.id.input_layout_cvv_code; break; case 4: resId = R.id.space; break; } return findViewById(resId); } @Override public void destroyItem(ViewGroup container, int position, Object object) { } @Override public int getCount() { return 5; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } } private void hideKeyboard(View view) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } private void showKeyboard(View view) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, 0); } private void updateProgressBar(int progress) { ObjectAnimator animation = ObjectAnimator.ofInt(activitySubmitCreditCardBinding.progressHorizontal, "progress", progress); animation.setDuration(300); animation.setInterpolator(new DecelerateInterpolator()); animation.start(); } private void submit() { activitySubmitCreditCardBinding.viewPager.setCurrentItem(4); card.setCardNumber(activitySubmitCreditCardBinding.inputEditCardNumber.getText().toString()); card.setExpiredDate(activitySubmitCreditCardBinding.inputEditExpiredDate.getText().toString()); card.setCardHolder(activitySubmitCreditCardBinding.inputEditCardHolder.getText().toString()); card.setCvvCode(activitySubmitCreditCardBinding.inputEditCvvCode.getText().toString()); Toast.makeText(SubmitCreditCardActivity.this, card.toString(), Toast.LENGTH_LONG).show(); new Handler().postDelayed(new Runnable() { @Override public void run() { activitySubmitCreditCardBinding.inputLayoutCvvCode.setVisibility(View.INVISIBLE); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); activitySubmitCreditCardBinding.labelSecureSubmission.setVisibility(View.VISIBLE); hideKeyboard(activitySubmitCreditCardBinding.inputEditCvvCode); activitySubmitCreditCardBinding.progressCircle.setVisibility(View.VISIBLE); } }, 300); } private void reset() { getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); activitySubmitCreditCardBinding.inputLayoutCvvCode.setVisibility(View.VISIBLE); activitySubmitCreditCardBinding.progressCircle.setVisibility(View.GONE); activitySubmitCreditCardBinding.labelSecureSubmission.setVisibility(View.GONE); flipToGray(); activitySubmitCreditCardBinding.viewPager.setCurrentItem(0); activitySubmitCreditCardBinding.inputEditCardNumber.setText(""); activitySubmitCreditCardBinding.inputEditExpiredDate.setText(""); activitySubmitCreditCardBinding.inputEditCardHolder.setText(""); activitySubmitCreditCardBinding.inputEditCvvCode.setText(""); activitySubmitCreditCardBinding.inputEditCardNumber.requestFocus(); showKeyboard(activitySubmitCreditCardBinding.inputEditCardNumber); } private void flipToGray() { if (!showingGray && !outSet.isRunning() && !inSet.isRunning()) { showingGray = true; activitySubmitCreditCardBinding.cardBlue.setCardElevation(0); activitySubmitCreditCardBinding.cardGray.setCardElevation(0); outSet.setTarget(activitySubmitCreditCardBinding.cardBlue); outSet.start(); inSet.setTarget(activitySubmitCreditCardBinding.cardGray); inSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { activitySubmitCreditCardBinding.cardGray.setCardElevation(convertDpToPixel(12, SubmitCreditCardActivity.this)); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); inSet.start(); } } private void flipToBlue() { if (showingGray && !outSet.isRunning() && !inSet.isRunning()) { showingGray = false; activitySubmitCreditCardBinding.cardGray.setCardElevation(0); activitySubmitCreditCardBinding.cardBlue.setCardElevation(0); outSet.setTarget(activitySubmitCreditCardBinding.cardGray); outSet.start(); inSet.setTarget(activitySubmitCreditCardBinding.cardBlue); inSet.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { activitySubmitCreditCardBinding.cardBlue.setCardElevation(convertDpToPixel(12, SubmitCreditCardActivity.this)); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); inSet.start(); } } public static float convertDpToPixel(float dp, Context context){ Resources resources = context.getResources(); DisplayMetrics metrics = resources.getDisplayMetrics(); float px = dp * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); return px; } public static float convertPixelsToDp(float px, Context context){ Resources resources = context.getResources(); DisplayMetrics metrics = resources.getDisplayMetrics(); float dp = px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); return dp; } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_reset: reset(); return true; case android.R.id.home: finish(); return true; } return super.onOptionsItemSelected(item); } }