From b6eeed4a19d38f344f5713a3764ae544e69ce47d Mon Sep 17 00:00:00 2001 From: Daniel Olshansky Date: Wed, 3 Jul 2013 15:47:19 -0700 Subject: [PATCH] First commit for CardFlip. Change-Id: Ic0e68fdcb23ea70208adfda69f9e500955fa1254 --- .../animation/CardFlip/AndroidManifest.xml | 30 ++ .../CardFlip/res/drawable-hdpi/blue.jpg | Bin 0 -> 25949 bytes .../res/drawable-hdpi/ic_launcher.png | Bin 0 -> 9397 bytes .../CardFlip/res/drawable-hdpi/red.jpg | Bin 0 -> 26415 bytes .../res/drawable-ldpi/ic_launcher.png | Bin 0 -> 2729 bytes .../res/drawable-mdpi/ic_launcher.png | Bin 0 -> 5237 bytes .../res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 14383 bytes .../animation/CardFlip/res/layout/main.xml | 19 + .../animation/CardFlip/res/values/integer.xml | 20 ++ .../animation/CardFlip/res/values/strings.xml | 19 + .../example/android/cardflip/CardFlip.java | 297 ++++++++++++++++ .../android/cardflip/CardFlipListener.java | 27 ++ .../example/android/cardflip/CardView.java | 329 ++++++++++++++++++ 13 files changed, 741 insertions(+) create mode 100644 samples/devbytes/animation/CardFlip/AndroidManifest.xml create mode 100644 samples/devbytes/animation/CardFlip/res/drawable-hdpi/blue.jpg create mode 100644 samples/devbytes/animation/CardFlip/res/drawable-hdpi/ic_launcher.png create mode 100644 samples/devbytes/animation/CardFlip/res/drawable-hdpi/red.jpg create mode 100644 samples/devbytes/animation/CardFlip/res/drawable-ldpi/ic_launcher.png create mode 100644 samples/devbytes/animation/CardFlip/res/drawable-mdpi/ic_launcher.png create mode 100644 samples/devbytes/animation/CardFlip/res/drawable-xhdpi/ic_launcher.png create mode 100644 samples/devbytes/animation/CardFlip/res/layout/main.xml create mode 100644 samples/devbytes/animation/CardFlip/res/values/integer.xml create mode 100644 samples/devbytes/animation/CardFlip/res/values/strings.xml create mode 100644 samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java create mode 100644 samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java create mode 100644 samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java diff --git a/samples/devbytes/animation/CardFlip/AndroidManifest.xml b/samples/devbytes/animation/CardFlip/AndroidManifest.xml new file mode 100644 index 000000000..d915f3eff --- /dev/null +++ b/samples/devbytes/animation/CardFlip/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/samples/devbytes/animation/CardFlip/res/drawable-hdpi/blue.jpg b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/blue.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2f7b7868fec4fec1d81ebf4e190741e7e8a6d8d1 GIT binary patch literal 25949 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 G|0V$6CF`O9 literal 0 HcmV?d00001 diff --git a/samples/devbytes/animation/CardFlip/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..96a442e5b8e9394ccf50bab9988cb2316026245d GIT binary patch literal 9397 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 literal 0 HcmV?d00001 diff --git a/samples/devbytes/animation/CardFlip/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..99238729d8753585237a65b91c7cde426c90baef GIT binary patch literal 2729 zcmV;a3Rd-rP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L02dMf02dMgXP?qi00007bV*G`2ipt~ z7YY(F`_Sb8017EdL_t(o!?l=uuwPYm$3JVI^ZWho?|E--5|R`W6G$K=z*GYY6wr=V zEHLAs& zdz|M!d-acV?}e00xbt)P@m$z^s#fV*k#SgXB4;4pFT(w@xz)o_l~EwJ+$tL zNA}&l{N}CqzO8^B)M@;g^aHT<;0E84yNhu{N${eJ-?VeV-AUA6q$<9trt}a{U45TFsn9Sc6zfp($j8t2s@dE zQIjAUBn)CY?J)11fS?@`1`%Nx6NL#$Z0Usk7(Wr4STgIdiMw7!!ptNtBYrmL$nY(+rzsSZg&+Q(Pts z$DVsczi`HH^ri&>wJ9FAf9p&De1OdZH!;t<6V-n!4>5RGht>sq2l{?Fa6~?LaQm$9 z9qH`6yjb)4PhAIa?cbkttcHHF=ZgDOlWSCc`VaTB=hp)doVH}{g9J0z z{OG}rx?{_LG>2kT!Sf8oqKD@j#DD_oG}lq0#F53O8AgO^qo8w6oGP^*|D}1SXUk7K zb?V*KdY9iC3G_f;Tb_CB@TqH89N00=&{%tU%c0Z4WB~ApI*tQ-I@60@=bck#y}*T6 z_R1w!Pet&si6M<0X$&@1Z04|OhSLnh!5CX8&N-6E$;g1?;NIcJ!9M@ET6asjDj{j& zq&1Y$9Lh>#7>)s?>Lr;~P$jdD%&Hf*{8+t^cGKb)1Y-;$qr{4!>WIP!krE;qzA0ie zH@2QMam0}lG!0Rtu2d9Jhk!tC3eGyD1bu2t1_*& znD@VXDUHfZeztiTyAJ-0ENzq8EH4L{qM4F8hdRitic@fz!#TyN5{GdxF+&jQ7@$l6 zDL9*@Sw_A%6O4hL>RjG2?L1CC{!f_IyJ&pj%>v_aJj(1 zDV}G@zl}MeEcR)=MBzMj!s=}<^ zGdSzCOStu`m-76U#|fg&xSoPB<%f3P={hr%`p}{nf+USozR$hK7$G3*$9{2!b{no?XWStM8y#?82#n6GW?7)Zsa` zwL!I2XXA1vS#2G_6uFg)uUPcjE9|${UC9d@_w0xRuPYew-0*;GI=nx){rvMUu(54@ z+`1-W3}TdRyVvvF=0|BZ+svA_fYc`R9sDKlJoSV8^oiAcd+nE5_tZVqd%^b&f>BQz zGBTL-|M&8(H=O;xQ=e^A=e^iz^4+6@yKlSf%8Tv#hqkcmS4VRN-hS^#_`+wt2f#&F zoaoiN8`U^;=?_+H4ewj^5AQhK+SC`?KJ^PeVnke)?{!I}B<(sU&3He<>2?MWWu%2Z z{8ENr@N(U$qFI3=v-$PTS07#Z@0&k3QOG}i+j)HBi%%Z=`tcW^UCejx+4hFXpTF~> z6_NH`)m1V01y2Phns1H@BEv%=rBZ<`6)ly05y^ASTBkN~;?g=vr9P;=m7CX$|G)Zgm+aiXZ~uaNy+(I$oqD4|rBaJZ zrIPx7!4u>8HcdFJC#TdexmzBje$|6hQ{z`W;j zcxEL`omomE>(d+x8Qd8VhX=5+`P#GV58evMdoP*&lTI}9fl8%JsjEQ2FXPkIUzaTk zaNk#c^;wYqAW|>-DX%0C?1}#Zoic`Di%g1kcS7qn!=Ut&(rcy6c zEP5*Vl6GWL2O9olCKpP^6ib5fJT(SUCo~-tix$s^a?N*TuSl&?#P^M4X@Pb!L1}-x z&WA*#CC1=+BE_;txmKWDDTfD-_Gz_Ib&Z~KTI()QX%w`p;#2A}c%F3r-vD)*@$xL` zN{seU@}^QO)(>T_xfWpdaeovRE7^CZPMr}#|!d*|R6{H=+M{MV$Mp3LNPKT_t5 z(-+S5yz=?J*A+!U{KSTh8xFttSbqQdFU>bSjT8Q$)Ky#JnbOd}k;7ZR_W37=|NQzh jFn-Lp|K;W1YU6(Zg`N}+zmb=x00000NkvXXu0mjf_|!_9 literal 0 HcmV?d00001 diff --git a/samples/devbytes/animation/CardFlip/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..359047dfa4ed206e41e2354f9c6b307e713efe32 GIT binary patch literal 5237 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 literal 0 HcmV?d00001 diff --git a/samples/devbytes/animation/CardFlip/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/CardFlip/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..71c6d760f05183ef8a47c614d8d13380c8528499 GIT binary patch literal 14383 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 literal 0 HcmV?d00001 diff --git a/samples/devbytes/animation/CardFlip/res/layout/main.xml b/samples/devbytes/animation/CardFlip/res/layout/main.xml new file mode 100644 index 000000000..ef23d69ee --- /dev/null +++ b/samples/devbytes/animation/CardFlip/res/layout/main.xml @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/samples/devbytes/animation/CardFlip/res/values/integer.xml b/samples/devbytes/animation/CardFlip/res/values/integer.xml new file mode 100644 index 000000000..2eb363c43 --- /dev/null +++ b/samples/devbytes/animation/CardFlip/res/values/integer.xml @@ -0,0 +1,20 @@ + + + + 30 + 30 + + \ No newline at end of file diff --git a/samples/devbytes/animation/CardFlip/res/values/strings.xml b/samples/devbytes/animation/CardFlip/res/values/strings.xml new file mode 100644 index 000000000..bd248d1c5 --- /dev/null +++ b/samples/devbytes/animation/CardFlip/res/values/strings.xml @@ -0,0 +1,19 @@ + + + + CardFlip + + diff --git a/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java new file mode 100644 index 000000000..746afec3d --- /dev/null +++ b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlip.java @@ -0,0 +1,297 @@ +/* + * 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.cardflip; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.app.Activity; +import android.os.Build; +import android.os.Bundle; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ViewTreeObserver; +import android.widget.RelativeLayout; + +import java.util.ArrayList; +import java.util.List; + +/** + * This application creates 2 stacks of playing cards. Using fling events, + * these cards can be flipped from one stack to another where each flip comes with + * an associated animation. The cards can be flipped horizontally from left to right + * or right to left depending on which stack the animating card currently belongs to. + * + * This application demonstrates an animation where a stack of cards can either be + * be rotated out or back in about their bottom left corner in a counter-clockwise direction. + * Rotate out: Down fling on stack of cards + * Rotate in: Up fling on stack of cards + * Full rotation: Tap on stack of cards + * + * Note that in this demo touch events are disabled in the middle of any animation so + * only one card can be flipped at a time. When the cards are in a rotated-out + * state, no new cards can be rotated to or from that stack. These changes were made to + * simplify the code for this demo. + */ + +public class CardFlip extends Activity implements CardFlipListener { + + final static int CARD_PILE_OFFSET = 3; + final static int STARTING_NUMBER_CARDS = 15; + final static int RIGHT_STACK = 0; + final static int LEFT_STACK = 1; + + int mCardWidth = 0; + int mCardHeight = 0; + + int mVerticalPadding; + int mHorizontalPadding; + + boolean mTouchEventsEnabled = true; + boolean[] mIsStackEnabled; + + RelativeLayout mLayout; + + List> mStackCards; + + GestureDetector gDetector; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + mStackCards = new ArrayList>(); + mStackCards.add(new ArrayList()); + mStackCards.add(new ArrayList()); + + mIsStackEnabled = new boolean[2]; + mIsStackEnabled[0] = true; + mIsStackEnabled[1] = true; + + mVerticalPadding = getResources().getInteger(R.integer.vertical_card_magin); + mHorizontalPadding = getResources().getInteger(R.integer.horizontal_card_magin); + + gDetector = new GestureDetector(this, mGestureListener); + + mLayout = (RelativeLayout)findViewById(R.id.main_relative_layout); + ViewTreeObserver observer = mLayout.getViewTreeObserver(); + observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + mLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this); + } else { + mLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + + mCardHeight = mLayout.getHeight(); + mCardWidth = mLayout.getWidth() / 2; + + for (int x = 0; x < STARTING_NUMBER_CARDS; x++) { + addNewCard(RIGHT_STACK); + } + } + }); + } + + /** + * Adds a new card to the specified stack. Also performs all the necessary layout setup + * to place the card in the correct position. + */ + public void addNewCard(int stack) { + CardView view = new CardView(this); + view.updateTranslation(mStackCards.get(stack).size()); + view.setCardFlipListener(this); + view.setPadding(mHorizontalPadding, mVerticalPadding, mHorizontalPadding, mVerticalPadding); + + RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(mCardWidth, + mCardHeight); + params.topMargin = 0; + params.leftMargin = (stack == RIGHT_STACK ? mCardWidth : 0); + + mStackCards.get(stack).add(view); + mLayout.addView(view, params); + } + + /** + * Gesture Detector listens for fling events in order to potentially initiate + * a card flip event when a fling event occurs. Also listens for tap events in + * order to potentially initiate a full rotation animation. + */ + private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector + .SimpleOnGestureListener() { + @Override + public boolean onSingleTapUp(MotionEvent motionEvent) { + int stack = getStack(motionEvent); + rotateCardsFullRotation(stack, CardView.Corner.BOTTOM_LEFT); + return true; + } + + @Override + public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float v, + float v2) { + int stack = getStack(motionEvent); + ArrayList cardStack = mStackCards.get(stack); + int size = cardStack.size(); + if (size > 0) { + rotateCardView(cardStack.get(size - 1), stack, v, v2); + } + return true; + } + }; + + /** Returns the appropriate stack corresponding to the MotionEvent. */ + public int getStack(MotionEvent ev) { + boolean isLeft = ev.getX() <= mCardWidth; + return isLeft ? LEFT_STACK : RIGHT_STACK; + } + + /** + * Uses the stack parameter, along with the velocity values of the fling event + * to determine in what direction the card must be flipped. By the same logic, the + * new stack that the card belongs to after the animation is also determined + * and updated. + */ + public void rotateCardView(final CardView cardView, int stack, float velocityX, + float velocityY) { + + boolean xGreaterThanY = Math.abs(velocityX) > Math.abs(velocityY); + + boolean bothStacksEnabled = mIsStackEnabled[RIGHT_STACK] && mIsStackEnabled[LEFT_STACK]; + + ArrayListleftStack = mStackCards.get(LEFT_STACK); + ArrayListrightStack = mStackCards.get(RIGHT_STACK); + + switch (stack) { + case RIGHT_STACK: + if (velocityX < 0 && xGreaterThanY) { + if (!bothStacksEnabled) { + break; + } + mLayout.bringChildToFront(cardView); + mLayout.requestLayout(); + rightStack.remove(rightStack.size() - 1); + leftStack.add(cardView); + cardView.flipRightToLeft(leftStack.size() - 1, (int)velocityX); + break; + } else if (!xGreaterThanY) { + boolean rotateCardsOut = velocityY > 0; + rotateCards(RIGHT_STACK, CardView.Corner.BOTTOM_LEFT, rotateCardsOut); + } + break; + case LEFT_STACK: + if (velocityX > 0 && xGreaterThanY) { + if (!bothStacksEnabled) { + break; + } + mLayout.bringChildToFront(cardView); + mLayout.requestLayout(); + leftStack.remove(leftStack.size() - 1); + rightStack.add(cardView); + cardView.flipLeftToRight(rightStack.size() - 1, (int)velocityX); + break; + } else if (!xGreaterThanY) { + boolean rotateCardsOut = velocityY > 0; + rotateCards(LEFT_STACK, CardView.Corner.BOTTOM_LEFT, rotateCardsOut); + } + break; + default: + break; + } + } + + @Override + public void onCardFlipEnd() { + mTouchEventsEnabled = true; + } + + @Override + public void onCardFlipStart() { + mTouchEventsEnabled = false; + } + + @Override + public boolean onTouchEvent(MotionEvent me) { + if (mTouchEventsEnabled) { + return gDetector.onTouchEvent(me); + } else { + return super.onTouchEvent(me); + } + } + + /** + * Retrieves an animator object for each card in the specified stack that either + * rotates it in or out depending on its current state. All of these animations + * are then played together. + */ + public void rotateCards (final int stack, CardView.Corner corner, + final boolean isRotatingOut) { + List animations = new ArrayList(); + + ArrayList cards = mStackCards.get(stack); + + for (int i = 0; i < cards.size(); i++) { + CardView cardView = cards.get(i); + animations.add(cardView.getRotationAnimator(i, corner, isRotatingOut, false)); + mLayout.bringChildToFront(cardView); + } + /** All the cards are being brought to the front in order to guarantee that + * the cards being rotated in the current stack will overlay the cards in the + * other stack. After the z-ordering of all the cards is updated, a layout must + * be requested in order to apply the changes made.*/ + mLayout.requestLayout(); + + AnimatorSet set = new AnimatorSet(); + set.playTogether(animations); + set.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIsStackEnabled[stack] = !isRotatingOut; + } + }); + set.start(); + } + + /** + * Retrieves an animator object for each card in the specified stack to complete a + * full revolution around one of its corners, and plays all of them together. + */ + public void rotateCardsFullRotation (int stack, CardView.Corner corner) { + List animations = new ArrayList(); + + ArrayList cards = mStackCards.get(stack); + for (int i = 0; i < cards.size(); i++) { + CardView cardView = cards.get(i); + animations.add(cardView.getFullRotationAnimator(i, corner, false)); + mLayout.bringChildToFront(cardView); + } + /** Same reasoning for bringing cards to front as in rotateCards().*/ + mLayout.requestLayout(); + + mTouchEventsEnabled = false; + AnimatorSet set = new AnimatorSet(); + set.playTogether(animations); + set.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mTouchEventsEnabled = true; + } + }); + set.start(); + } +} \ No newline at end of file diff --git a/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java new file mode 100644 index 000000000..0af6941bf --- /dev/null +++ b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardFlipListener.java @@ -0,0 +1,27 @@ +/* + * 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.cardflip; + +/** + * This interface is used to prevent flipping multiple cards at the same time. + * These callback methods are used to disable and re-enable touches when a card + * flip animation begins and ends respectively. + * */ +public interface CardFlipListener { + public void onCardFlipEnd(); + public void onCardFlipStart(); +} diff --git a/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java new file mode 100644 index 000000000..9a3ab7126 --- /dev/null +++ b/samples/devbytes/animation/CardFlip/src/com/example/android/cardflip/CardView.java @@ -0,0 +1,329 @@ +/* + * 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.cardflip; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.Keyframe; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.drawable.BitmapDrawable; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +/** + * This CardView object is a view which can flip horizontally about its edges, + * as well as rotate clockwise or counter-clockwise about any of its corners. In + * the middle of a flip animation, this view darkens to imitate a shadow-like effect. + * + * The key behind the design of this view is the fact that the layout parameters and + * the animation properties of this view are updated and reset respectively after + * every single animation. Therefore, every consecutive animation that this + * view experiences is completely independent of what its prior state was. + */ +public class CardView extends ImageView { + + enum Corner { + TOP_LEFT, + TOP_RIGHT, + BOTTOM_LEFT, + BOTTOM_RIGHT + } + + private final int CAMERA_DISTANCE = 8000; + private final int MIN_FLIP_DURATION = 300; + private final int VELOCITY_TO_DURATION_CONSTANT = 15; + private final int MAX_FLIP_DURATION = 700; + private final int ROTATION_PER_CARD = 2; + private final int ROTATION_DELAY_PER_CARD = 50; + private final int ROTATION_DURATION = 2000; + private final int ANTIALIAS_BORDER = 1; + + private BitmapDrawable mFrontBitmapDrawable, mBackBitmapDrawable, mCurrentBitmapDrawable; + + private boolean mIsFrontShowing = true; + private boolean mIsHorizontallyFlipped = false; + + private Matrix mHorizontalFlipMatrix; + + private CardFlipListener mCardFlipListener; + + public CardView(Context context) { + super(context); + init(context); + } + + public CardView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + /** Loads the bitmap drawables used for the front and back for this card.*/ + public void init(Context context) { + mHorizontalFlipMatrix = new Matrix(); + + setCameraDistance(CAMERA_DISTANCE); + + mFrontBitmapDrawable = bitmapWithBorder((BitmapDrawable)getResources() + .getDrawable(R.drawable.red)); + mBackBitmapDrawable = bitmapWithBorder((BitmapDrawable) getResources() + .getDrawable(R.drawable.blue)); + + updateDrawableBitmap(); + } + + /** + * Adding a 1 pixel transparent border around the bitmap can be used to + * anti-alias the image as it rotates. + */ + private BitmapDrawable bitmapWithBorder(BitmapDrawable bitmapDrawable) { + Bitmap bitmapWithBorder = Bitmap.createBitmap(bitmapDrawable.getIntrinsicWidth() + + ANTIALIAS_BORDER * 2, bitmapDrawable.getIntrinsicHeight() + ANTIALIAS_BORDER * 2, + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmapWithBorder); + canvas.drawBitmap(bitmapDrawable.getBitmap(), ANTIALIAS_BORDER, ANTIALIAS_BORDER, null); + return new BitmapDrawable(getResources(), bitmapWithBorder); + } + + /** Initiates a horizontal flip from right to left. */ + public void flipRightToLeft(int numberInPile, int velocity) { + setPivotX(0); + flipHorizontally(numberInPile, false, velocity); + } + + /** Initiates a horizontal flip from left to right. */ + public void flipLeftToRight(int numberInPile, int velocity) { + setPivotX(getWidth()); + flipHorizontally(numberInPile, true, velocity); + } + + /** + * Animates a horizontal (about the y-axis) flip of this card. + * @param numberInPile Specifies how many cards are underneath this card in the new + * pile so as to properly adjust its position offset in the stack. + * @param clockwise Specifies whether the horizontal animation is 180 degrees + * clockwise or 180 degrees counter clockwise. + */ + public void flipHorizontally (int numberInPile, boolean clockwise, int velocity) { + toggleFrontShowing(); + + PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat(View.ROTATION_Y, + clockwise ? 180 : -180); + + PropertyValuesHolder xOffset = PropertyValuesHolder.ofFloat(View.TRANSLATION_X, + numberInPile * CardFlip.CARD_PILE_OFFSET); + PropertyValuesHolder yOffset = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, + numberInPile * CardFlip.CARD_PILE_OFFSET); + + ObjectAnimator cardAnimator = ObjectAnimator.ofPropertyValuesHolder(this, rotation, + xOffset, yOffset); + cardAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + if (valueAnimator.getAnimatedFraction() >= 0.5) { + updateDrawableBitmap(); + } + } + }); + + Keyframe shadowKeyFrameStart = Keyframe.ofFloat(0, 0); + Keyframe shadowKeyFrameMid = Keyframe.ofFloat(0.5f, 1); + Keyframe shadowKeyFrameEnd = Keyframe.ofFloat(1, 0); + PropertyValuesHolder shadowPropertyValuesHolder = PropertyValuesHolder.ofKeyframe + ("shadow", shadowKeyFrameStart, shadowKeyFrameMid, shadowKeyFrameEnd); + ObjectAnimator colorizer = ObjectAnimator.ofPropertyValuesHolder(this, + shadowPropertyValuesHolder); + + mCardFlipListener.onCardFlipStart(); + AnimatorSet set = new AnimatorSet(); + int duration = MAX_FLIP_DURATION - Math.abs(velocity) / VELOCITY_TO_DURATION_CONSTANT; + duration = duration < MIN_FLIP_DURATION ? MIN_FLIP_DURATION : duration; + set.setDuration(duration); + set.playTogether(cardAnimator, colorizer); + set.setInterpolator(new AccelerateDecelerateInterpolator()); + set.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + toggleIsHorizontallyFlipped(); + updateDrawableBitmap(); + updateLayoutParams(); + mCardFlipListener.onCardFlipEnd(); + } + }); + set.start(); + } + + /** Darkens this ImageView's image by applying a shadow color filter over it. */ + public void setShadow(float value) { + int colorValue = (int)(255 - 200 * value); + setColorFilter(Color.rgb(colorValue, colorValue, colorValue), + android.graphics.PorterDuff.Mode.MULTIPLY); + } + + public void toggleFrontShowing() { + mIsFrontShowing = !mIsFrontShowing; + } + + public void toggleIsHorizontallyFlipped() { + mIsHorizontallyFlipped = !mIsHorizontallyFlipped; + invalidate(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mHorizontalFlipMatrix.setScale(-1, 1, w / 2, h / 2); + } + + /** + * Scale the canvas horizontally about its midpoint in the case that the card + * is in a horizontally flipped state. + */ + @Override + protected void onDraw(Canvas canvas) { + if (mIsHorizontallyFlipped) { + canvas.concat(mHorizontalFlipMatrix); + } + super.onDraw(canvas); + } + + /** + * Updates the layout parameters of this view so as to reset the rotationX and + * rotationY parameters, and remain independent of its previous position, while + * also maintaining its current position in the layout. + */ + public void updateLayoutParams () { + RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) getLayoutParams(); + + params.leftMargin = (int)(params.leftMargin + ((Math.abs(getRotationY()) % 360) / 180) * + (2 * getPivotX () - getWidth())); + + setRotationX(0); + setRotationY(0); + + setLayoutParams(params); + } + + /** + * Toggles the visible bitmap of this view between its front and back drawables + * respectively. + */ + public void updateDrawableBitmap () { + mCurrentBitmapDrawable = mIsFrontShowing ? mFrontBitmapDrawable : mBackBitmapDrawable; + setImageDrawable(mCurrentBitmapDrawable); + } + + /** + * Sets the appropriate translation of this card depending on how many cards + * are in the pile underneath it. + */ + public void updateTranslation (int numInPile) { + setTranslationX(CardFlip.CARD_PILE_OFFSET * numInPile); + setTranslationY(CardFlip.CARD_PILE_OFFSET * numInPile); + } + + /** + * Returns a rotation animation which rotates this card by some degree about + * one of its corners either in the clockwise or counter-clockwise direction. + * Depending on how many cards lie below this one in the stack, this card will + * be rotated by a different amount so all the cards are visible when rotated out. + */ + public ObjectAnimator getRotationAnimator (int cardFromTop, Corner corner, + boolean isRotatingOut, boolean isClockwise) { + rotateCardAroundCorner(corner); + int rotation = cardFromTop * ROTATION_PER_CARD; + + if (!isClockwise) { + rotation = -rotation; + } + + if (!isRotatingOut) { + rotation = 0; + } + + return ObjectAnimator.ofFloat(this, View.ROTATION, rotation); + } + + /** + * Returns a full rotation animator which rotates this card by 360 degrees + * about one of its corners either in the clockwise or counter-clockwise direction. + * Depending on how many cards lie below this one in the stack, a different start + * delay is applied to the animation so the cards don't all animate at once. + */ + public ObjectAnimator getFullRotationAnimator (int cardFromTop, Corner corner, + boolean isClockwise) { + final int currentRotation = (int)getRotation(); + + rotateCardAroundCorner(corner); + int rotation = 360 - currentRotation; + rotation = isClockwise ? rotation : -rotation; + + ObjectAnimator animator = ObjectAnimator.ofFloat(this, View.ROTATION, rotation); + + animator.setStartDelay(ROTATION_DELAY_PER_CARD * cardFromTop); + animator.setDuration(ROTATION_DURATION); + + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + setRotation(currentRotation); + } + }); + + return animator; + } + + /** + * Sets the appropriate pivot of this card so that it can be rotated about + * any one of its four corners. + */ + public void rotateCardAroundCorner(Corner corner) { + switch(corner) { + case TOP_LEFT: + setPivotX(0); + setPivotY(0); + break; + case TOP_RIGHT: + setPivotX(getWidth()); + setPivotY(0); + break; + case BOTTOM_LEFT: + setPivotX(0); + setPivotY(getHeight()); + break; + case BOTTOM_RIGHT: + setPivotX(getWidth()); + setPivotY(getHeight()); + break; + } + } + + public void setCardFlipListener(CardFlipListener cardFlipListener) { + mCardFlipListener = cardFlipListener; + } + +}