| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.example.android.toongame; |
| |
| import android.animation.Animator; |
| import android.animation.AnimatorListenerAdapter; |
| import android.animation.AnimatorSet; |
| import android.animation.ObjectAnimator; |
| import android.animation.PropertyValuesHolder; |
| import android.animation.TimeInterpolator; |
| import android.animation.ValueAnimator; |
| import android.app.Activity; |
| import android.content.res.ColorStateList; |
| import android.graphics.Color; |
| import android.graphics.Typeface; |
| import android.graphics.drawable.ShapeDrawable; |
| import android.graphics.drawable.shapes.OvalShape; |
| import android.os.Bundle; |
| import android.util.TypedValue; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.ViewTreeObserver; |
| import android.view.animation.AccelerateInterpolator; |
| import android.view.animation.DecelerateInterpolator; |
| import android.view.animation.LinearInterpolator; |
| import android.view.animation.OvershootInterpolator; |
| import android.widget.Button; |
| import android.widget.EditText; |
| import android.widget.RelativeLayout; |
| |
| /** |
| * This activity, launched from the ToonGame activity, takes the user between three |
| * different setup screens where they choose a name, choose a difficulty rating, and |
| * enter important financial information. All of the screens are meant to be |
| * simple, engaging, and fun. |
| */ |
| public class PlayerSetupActivity extends Activity { |
| |
| private static final AccelerateInterpolator sAccelerator = new AccelerateInterpolator(); |
| private static final LinearInterpolator sLinearInterpolator = new LinearInterpolator(); |
| ViewGroup mContainer; |
| EditText mEditText; |
| |
| private static final int NAME_STATE = 0; |
| private static final int DIFFICULTY_STATE = 1; |
| private static final int CREDIT_STATE = 2; |
| private int mEntryState = NAME_STATE; |
| |
| SkewableTextView mNameTV, mDifficultyTV, mCreditTV; |
| |
| ViewGroup mNameButtons, mDifficultyButtons, mCreditButtons1, mCreditButtons2; |
| |
| Button mBobButton, mJaneButton, mPatButton; |
| |
| private static final TimeInterpolator sOvershooter = new OvershootInterpolator(); |
| private static final DecelerateInterpolator sDecelerator = new DecelerateInterpolator(); |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| setContentView(R.layout.player_setup_layout); |
| overridePendingTransition(0, 0); |
| |
| mContainer = (ViewGroup) findViewById(R.id.container); |
| mContainer.getViewTreeObserver().addOnPreDrawListener(mPreDrawListener); |
| |
| mNameTV = (SkewableTextView) findViewById(R.id.nameTV); |
| mDifficultyTV = (SkewableTextView) findViewById(R.id.ageTV); |
| mCreditTV = (SkewableTextView) findViewById(R.id.creditTV); |
| |
| mBobButton = setupButton(R.id.bobButton); |
| setupButton(R.id.janeButton); |
| setupButton(R.id.patButton); |
| setupButton(R.id.easyButton); |
| setupButton(R.id.hardButton); |
| setupButton(R.id.megaHardButton); |
| |
| mNameButtons = (ViewGroup) findViewById(R.id.nameButtons); |
| mDifficultyButtons = (ViewGroup) findViewById(R.id.difficultyButtons); |
| mCreditButtons1 = (ViewGroup) findViewById(R.id.creditButtons1); |
| mCreditButtons2 = (ViewGroup) findViewById(R.id.creditButtons2); |
| } |
| |
| @Override |
| public void finish() { |
| super.finish(); |
| overridePendingTransition(0, 0); |
| } |
| |
| private Button setupButton(int resourceId) { |
| Button button = (Button) findViewById(resourceId); |
| button.setOnTouchListener(mButtonPressListener); |
| return button; |
| } |
| |
| private View.OnTouchListener mButtonPressListener = |
| new View.OnTouchListener() { |
| public boolean onTouch(View v, MotionEvent event) { |
| switch (event.getAction()) { |
| case MotionEvent.ACTION_DOWN: |
| v.animate().setDuration(ToonGame.SHORT_DURATION). |
| scaleX(.8f).scaleY(.8f).setInterpolator(sDecelerator); |
| break; |
| case MotionEvent.ACTION_UP: |
| v.animate().setDuration(ToonGame.SHORT_DURATION). |
| scaleX(1).scaleY(1).setInterpolator(sAccelerator); |
| break; |
| default: |
| break; |
| } |
| return false; |
| } |
| }; |
| |
| public void buttonClick(View clickedView, int alignmentRule) { |
| ViewGroup parent = (ViewGroup) clickedView.getParent(); |
| for (int i = 0; i < parent.getChildCount(); ++i) { |
| Button child = (Button) parent.getChildAt(i); |
| if (child != clickedView) { |
| child.animate().alpha(0); |
| } else { |
| final Button buttonCopy = new Button(this); |
| child.setVisibility(View.INVISIBLE); |
| buttonCopy.setBackground(child.getBackground()); |
| buttonCopy.setText(((Button) child).getText()); |
| RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams( |
| RelativeLayout.LayoutParams.WRAP_CONTENT, |
| RelativeLayout.LayoutParams.WRAP_CONTENT); |
| params.addRule(RelativeLayout.ALIGN_PARENT_TOP); |
| params.addRule(alignmentRule); |
| params.setMargins(25, 50, 25, 50); |
| buttonCopy.setLayoutParams(params); |
| buttonCopy.setPadding(child.getPaddingLeft(), child.getPaddingTop(), |
| child.getPaddingRight(), child.getPaddingBottom()); |
| buttonCopy.setTextSize(TypedValue.COMPLEX_UNIT_PX, child.getTextSize()); |
| buttonCopy.setTypeface(child.getTypeface(), Typeface.BOLD); |
| ColorStateList colors = child.getTextColors(); |
| buttonCopy.setTextColor(colors.getDefaultColor()); |
| final int[] oldLocationInWindow = new int[2]; |
| child.getLocationInWindow(oldLocationInWindow); |
| mContainer.addView(buttonCopy); |
| buttonCopy.getViewTreeObserver().addOnPreDrawListener( |
| new ViewTreeObserver.OnPreDrawListener() { |
| |
| @Override |
| public boolean onPreDraw() { |
| buttonCopy.getViewTreeObserver().removeOnPreDrawListener(this); |
| int[] locationInWindow = new int[2]; |
| buttonCopy.getLocationInWindow(locationInWindow); |
| float deltaX = oldLocationInWindow[0] - locationInWindow[0]; |
| float deltaY = oldLocationInWindow[1] - locationInWindow[1]; |
| |
| buttonCopy.setTranslationX(deltaX); |
| buttonCopy.setTranslationY(deltaY); |
| |
| PropertyValuesHolder pvhSX = |
| PropertyValuesHolder.ofFloat(View.SCALE_X, 3); |
| PropertyValuesHolder pvhSY = |
| PropertyValuesHolder.ofFloat(View.SCALE_Y, 3); |
| ObjectAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder( |
| buttonCopy, pvhSX, pvhSY); |
| bounceAnim.setRepeatCount(1); |
| bounceAnim.setRepeatMode(ValueAnimator.REVERSE); |
| bounceAnim.setInterpolator(sDecelerator); |
| bounceAnim.setDuration(300); |
| |
| PropertyValuesHolder pvhTX = |
| PropertyValuesHolder.ofFloat(View.TRANSLATION_X, 0); |
| PropertyValuesHolder pvhTY = |
| PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, 0); |
| ObjectAnimator moveAnim = ObjectAnimator.ofPropertyValuesHolder( |
| buttonCopy, pvhTX, pvhTY); |
| moveAnim.setDuration(600); |
| bounceAnim.start(); |
| moveAnim.start(); |
| moveAnim.addListener(new AnimatorListenerAdapter() { |
| public void onAnimationEnd(Animator animation) { |
| switch (mEntryState) { |
| case (NAME_STATE) : |
| { |
| Runnable runnable = new Runnable() { |
| public void run() { |
| mDifficultyButtons.setVisibility(View.VISIBLE); |
| mNameButtons.setVisibility(View.GONE); |
| popChildrenIn(mDifficultyButtons, null); |
| } |
| }; |
| slideToNext(mNameTV, mDifficultyTV, runnable); |
| mEntryState = DIFFICULTY_STATE; |
| break; |
| } |
| case (DIFFICULTY_STATE) : |
| { |
| mDifficultyButtons.setVisibility(View.GONE); |
| for (int i = 0; i < 5; ++i) { |
| mCreditButtons1.addView(setupNumberButton(i)); |
| } |
| for (int i = 5; i < 10; ++i) { |
| mCreditButtons2.addView(setupNumberButton(i)); |
| } |
| Runnable runnable = new Runnable() { |
| public void run() { |
| mCreditButtons1.setVisibility(View.VISIBLE); |
| Runnable runnable = new Runnable() { |
| public void run() { |
| mCreditButtons2.setVisibility(View.VISIBLE); |
| popChildrenIn(mCreditButtons2, null); |
| } |
| }; |
| popChildrenIn(mCreditButtons1, runnable); |
| } |
| }; |
| slideToNext(mDifficultyTV, mCreditTV, runnable); |
| mEntryState = CREDIT_STATE; |
| } |
| break; |
| } |
| } |
| }); |
| return true; |
| } |
| }); |
| } |
| } |
| } |
| |
| public void selectDifficulty(View clickedView) { |
| buttonClick(clickedView, RelativeLayout.ALIGN_PARENT_RIGHT); |
| } |
| |
| public void selectName(View clickedView) { |
| buttonClick(clickedView, RelativeLayout.ALIGN_PARENT_LEFT); |
| } |
| |
| private Button setupNumberButton(int number) { |
| Button button = new Button(PlayerSetupActivity.this); |
| button.setTextSize(15); |
| button.setTextColor(Color.WHITE); |
| button.setTypeface(mBobButton.getTypeface(), Typeface.BOLD); |
| button.setText(Integer.toString(number)); |
| button.setPadding(0, 0, 0, 0); |
| |
| OvalShape oval = new OvalShape(); |
| ShapeDrawable drawable = new ShapeDrawable(oval); |
| drawable.getPaint().setColor(0xFF << 24 | (int) (50 + 150 * Math.random()) << 16 | |
| (int) (50 + 150 * Math.random()) << 8 | (int) (50 + 150 * Math.random())); |
| button.setBackground(drawable); |
| |
| button.setOnTouchListener(mButtonPressListener); |
| |
| return button; |
| } |
| |
| ViewTreeObserver.OnPreDrawListener mPreDrawListener = |
| new ViewTreeObserver.OnPreDrawListener() { |
| |
| @Override |
| public boolean onPreDraw() { |
| mContainer.getViewTreeObserver().removeOnPreDrawListener(this); |
| mContainer.setScaleX(0); |
| mContainer.setScaleY(0); |
| mContainer.animate().scaleX(1).scaleY(1).setInterpolator(new OvershootInterpolator()); |
| mContainer.animate().setDuration(ToonGame.LONG_DURATION).withEndAction(new Runnable() { |
| |
| @Override |
| public void run() { |
| ViewGroup buttonsParent = (ViewGroup) findViewById(R.id.nameButtons); |
| buttonsParent.setVisibility(View.VISIBLE); |
| popChildrenIn(buttonsParent, null); |
| } |
| }); |
| return false; |
| } |
| }; |
| |
| private void popChildrenIn(ViewGroup parent, final Runnable endAction) { |
| // for all children, scale in one at a time |
| TimeInterpolator overshooter = new OvershootInterpolator(); |
| int childCount = parent.getChildCount(); |
| ObjectAnimator[] childAnims = new ObjectAnimator[childCount]; |
| for (int i = 0; i < childCount; ++i) { |
| View child = parent.getChildAt(i); |
| child.setScaleX(0); |
| child.setScaleY(0); |
| PropertyValuesHolder pvhSX = PropertyValuesHolder.ofFloat(View.SCALE_X, 1); |
| PropertyValuesHolder pvhSY = PropertyValuesHolder.ofFloat(View.SCALE_Y, 1); |
| ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(child, pvhSX, pvhSY); |
| anim.setDuration(150); |
| anim.setInterpolator(overshooter); |
| childAnims[i] = anim; |
| } |
| AnimatorSet set = new AnimatorSet(); |
| set.playSequentially(childAnims); |
| set.start(); |
| if (endAction != null) { |
| set.addListener(new AnimatorListenerAdapter() { |
| public void onAnimationEnd(Animator animation) { |
| endAction.run(); |
| } |
| }); |
| } |
| } |
| |
| private void slideToNext(final SkewableTextView currentView, |
| final SkewableTextView nextView, final Runnable endAction) { |
| // skew/anticipate current view, slide off, set GONE, restore translation |
| ObjectAnimator currentSkewer = ObjectAnimator.ofFloat(currentView, "skewX", -.5f); |
| currentSkewer.setInterpolator(sDecelerator); |
| ObjectAnimator currentMover = ObjectAnimator.ofFloat(currentView, View.TRANSLATION_X, |
| -mContainer.getWidth()); |
| currentMover.setInterpolator(sLinearInterpolator); |
| currentMover.setDuration(ToonGame.MEDIUM_DURATION); |
| |
| // set next view visible, translate off to right, skew, |
| // slide on in parallel, overshoot/wobble, unskew |
| nextView.setVisibility(View.VISIBLE); |
| nextView.setSkewX(-.5f); |
| nextView.setTranslationX(mContainer.getWidth()); |
| |
| ObjectAnimator nextMover = ObjectAnimator.ofFloat(nextView, View.TRANSLATION_X, 0); |
| nextMover.setInterpolator(sAccelerator); |
| nextMover.setDuration(ToonGame.MEDIUM_DURATION); |
| ObjectAnimator nextSkewer = ObjectAnimator.ofFloat(nextView, "skewX", 0); |
| nextSkewer.setInterpolator(sOvershooter); |
| |
| AnimatorSet moverSet = new AnimatorSet(); |
| moverSet.playTogether(currentMover, nextMover); |
| AnimatorSet fullSet = new AnimatorSet(); |
| fullSet.playSequentially(currentSkewer, moverSet, nextSkewer); |
| fullSet.addListener(new AnimatorListenerAdapter() { |
| @Override |
| public void onAnimationEnd(Animator animation) { |
| currentView.setSkewX(0); |
| currentView.setVisibility(View.GONE); |
| currentView.setTranslationX(0); |
| if (endAction != null) { |
| endAction.run(); |
| } |
| } |
| }); |
| |
| fullSet.start(); |
| } |
| |
| } |