diff --git a/samples/devbytes/animation/SlidingFragments/AndroidManifest.xml b/samples/devbytes/animation/SlidingFragments/AndroidManifest.xml
new file mode 100644
index 000000000..2e71b6c9c
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/AndroidManifest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_in.xml b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_in.xml
new file mode 100644
index 000000000..7fe333b6d
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_in.xml
@@ -0,0 +1,22 @@
+
+
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_out.xml b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_out.xml
new file mode 100644
index 000000000..4d4134a32
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/animator/slide_fragment_out.xml
@@ -0,0 +1,22 @@
+
+
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/golden_gate.jpg b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/golden_gate.jpg
new file mode 100644
index 000000000..9a3d3fd7b
Binary files /dev/null and b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/golden_gate.jpg differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 000000000..96a442e5b
Binary files /dev/null and b/samples/devbytes/animation/SlidingFragments/res/drawable-hdpi/ic_launcher.png differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-ldpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 000000000..99238729d
Binary files /dev/null and b/samples/devbytes/animation/SlidingFragments/res/drawable-ldpi/ic_launcher.png differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-mdpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 000000000..359047dfa
Binary files /dev/null and b/samples/devbytes/animation/SlidingFragments/res/drawable-mdpi/ic_launcher.png differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/drawable-xhdpi/ic_launcher.png b/samples/devbytes/animation/SlidingFragments/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..71c6d760f
Binary files /dev/null and b/samples/devbytes/animation/SlidingFragments/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/samples/devbytes/animation/SlidingFragments/res/layout/image_fragment.xml b/samples/devbytes/animation/SlidingFragments/res/layout/image_fragment.xml
new file mode 100644
index 000000000..eb555fea4
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/layout/image_fragment.xml
@@ -0,0 +1,20 @@
+
+
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/layout/sliding_fragments_layout.xml b/samples/devbytes/animation/SlidingFragments/res/layout/sliding_fragments_layout.xml
new file mode 100644
index 000000000..a789a77c7
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/layout/sliding_fragments_layout.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/layout/text_fragment.xml b/samples/devbytes/animation/SlidingFragments/res/layout/text_fragment.xml
new file mode 100644
index 000000000..652acaa7f
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/layout/text_fragment.xml
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/colors.xml b/samples/devbytes/animation/SlidingFragments/res/values/colors.xml
new file mode 100644
index 000000000..f5eb07aad
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/colors.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ #ff0000
+ #000000
+ #ffffff
+ #00ff00
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/dimens.xml b/samples/devbytes/animation/SlidingFragments/res/values/dimens.xml
new file mode 100644
index 000000000..2b378c132
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/dimens.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 50dp
+ 18dp
+ 10dp
+
+
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/integers.xml b/samples/devbytes/animation/SlidingFragments/res/values/integers.xml
new file mode 100644
index 000000000..57c19acdd
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/integers.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ 200
+ 150
+ 150
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/items.xml b/samples/devbytes/animation/SlidingFragments/res/values/items.xml
new file mode 100644
index 000000000..2b7f0b58b
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/items.xml
@@ -0,0 +1,20 @@
+
+
+
+
+ - 0.67
+
+
\ No newline at end of file
diff --git a/samples/devbytes/animation/SlidingFragments/res/values/strings.xml b/samples/devbytes/animation/SlidingFragments/res/values/strings.xml
new file mode 100644
index 000000000..dbc41da47
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/res/values/strings.xml
@@ -0,0 +1,29 @@
+
+
+
+
+ SlidingFragments
+ Golden Gate Sunset by Romain Guy
+ Address: Golden Gate Bridge, San Francisco, CA 94129
+ Elevation: 220\' (67 m)
+ Height: 746\' (227 m)
+ Construction started: 1933
+ Longest span: 4,200\' (1,280 m)
+ Total length: 8,980\' (2,737 m)
+ "The Golden Gate Bridge is a suspension bridge spanning the Golden Gate, the opening of the San Francisco Bay into the Pacific Ocean."
+ Golden Gate Bridge
+
+
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/FractionalLinearLayout.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/FractionalLinearLayout.java
new file mode 100644
index 000000000..55f7269da
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/FractionalLinearLayout.java
@@ -0,0 +1,62 @@
+/*
+ * 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.slidingfragments;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+/**
+ * In order to animate the fragment containing text on/off the screen,
+ * it is required that we know the height of the device being used. However,
+ * this can only be determined at runtime, so we cannot specify the required
+ * translation in an xml file. Since FragmentTransaction's setCustomAnimations
+ * method requires an ID of an animation defined via an xml file, this linear
+ * layout was built as a workaround. This custom linear layout is created to specify
+ * the location of the fragment's layout as a fraction of the device's height. By
+ * animating yFraction from 0 to 1, we can animate the fragment from the top of
+ * the screen to the bottom of the screen, regardless of the device's specific size.
+ */
+public class FractionalLinearLayout extends LinearLayout {
+
+ private float mYFraction;
+ private int mScreenHeight;
+
+ public FractionalLinearLayout(Context context) {
+ super(context);
+ }
+
+ public FractionalLinearLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onSizeChanged (int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ mScreenHeight = h;
+ setY(mScreenHeight);
+ }
+
+ public float getYFraction() {
+ return mYFraction;
+ }
+
+ public void setYFraction(float yFraction) {
+ mYFraction = yFraction;
+ setY((mScreenHeight > 0) ? (mScreenHeight - yFraction * mScreenHeight) : 0);
+ }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/ImageFragment.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/ImageFragment.java
new file mode 100644
index 000000000..e306c98a8
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/ImageFragment.java
@@ -0,0 +1,39 @@
+/*
+ * 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.slidingfragments;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ImageFragment extends Fragment {
+
+ View.OnClickListener clickListener;
+
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.image_fragment, container, false);
+ view.setOnClickListener(clickListener);
+ return view;
+ }
+
+ public void setClickListener(View.OnClickListener clickListener) {
+ this.clickListener = clickListener;
+ }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/OnTextFragmentAnimationEndListener.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/OnTextFragmentAnimationEndListener.java
new file mode 100644
index 000000000..692a7cbc7
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/OnTextFragmentAnimationEndListener.java
@@ -0,0 +1,26 @@
+/*
+ * 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.slidingfragments;
+
+/**
+ * This interface is used to inform the main activity when the entry
+ * animation of the text fragment has completed in order to avoid the
+ * start of a new animation before the current one has completed.
+ */
+public interface OnTextFragmentAnimationEndListener {
+ public void onAnimationEnd();
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/SlidingFragments.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/SlidingFragments.java
new file mode 100644
index 000000000..9bfd8d4a2
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/SlidingFragments.java
@@ -0,0 +1,200 @@
+/*
+ * 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.slidingfragments;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.view.View;
+
+/**
+ * This application shows a simple technique to animate and overlay two fragments
+ * on top of each other in order to provide a more immersive experience,
+ * as opposed to only having full screen transitions. When additional content
+ * (text) related to the currently displayed content (image) is to be shown,
+ * the currently visible content can be moved into the background instead of
+ * being removed from the screen entirely. This effect can therefore
+ * provide a more natural way of displaying additional information to the user
+ * using a different fragment.
+ *
+ * In this specific demo, tapping on the screen toggles between the two
+ * animated states of the fragment. When the animation is called,
+ * the fragment with an image animates into the background while the fragment
+ * containing text slides up on top of it. When the animation is toggled once
+ * more, the text fragment slides back down and the image fragment regains
+ * focus.
+ */
+public class SlidingFragments extends Activity implements
+ OnTextFragmentAnimationEndListener, FragmentManager.OnBackStackChangedListener {
+
+ ImageFragment mImageFragment;
+ TextFragment mTextFragment;
+ View mDarkHoverView;
+
+ boolean mDidSlideOut = false;
+ boolean mIsAnimating = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.sliding_fragments_layout);
+
+ mDarkHoverView = findViewById(R.id.dark_hover_view);
+ mDarkHoverView.setAlpha(0);
+
+ mImageFragment = (ImageFragment) getFragmentManager().findFragmentById(R.id.move_fragment);
+ mTextFragment = new TextFragment();
+
+ getFragmentManager().addOnBackStackChangedListener(this);
+
+ mImageFragment.setClickListener(mClickListener);
+ mTextFragment.setClickListener(mClickListener);
+ mTextFragment.setOnTextFragmentAnimationEnd(this);
+ mDarkHoverView.setOnClickListener(mClickListener);
+
+ }
+
+ View.OnClickListener mClickListener = new View.OnClickListener () {
+ @Override
+ public void onClick(View view) {
+ switchFragments();
+ }
+ };
+
+ /**
+ * This method is used to toggle between the two fragment states by
+ * calling the appropriate animations between them. The entry and exit
+ * animations of the text fragment are specified in R.animator resource
+ * files. The entry and exit animations of the image fragment are
+ * specified in the slideBack and slideForward methods below. The reason
+ * for separating the animation logic in this way is because the translucent
+ * dark hover view must fade in at the same time as the image fragment
+ * animates into the background, which would be difficult to time
+ * properly given that the setCustomAnimations method can only modify the
+ * two fragments in the transaction.
+ */
+ private void switchFragments () {
+ if (mIsAnimating) {
+ return;
+ }
+ mIsAnimating = true;
+ if (mDidSlideOut) {
+ mDidSlideOut = false;
+ getFragmentManager().popBackStack();
+ } else {
+ mDidSlideOut = true;
+
+ AnimatorListener listener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ transaction.setCustomAnimations(R.animator.slide_fragment_in, 0, 0,
+ R.animator.slide_fragment_out);
+ transaction.add(R.id.move_to_back_container, mTextFragment);
+ transaction.addToBackStack(null);
+ transaction.commit();
+ }
+ };
+ slideBack (listener);
+ }
+ }
+
+ @Override
+ public void onBackStackChanged() {
+ if (!mDidSlideOut) {
+ slideForward(null);
+ }
+
+ }
+
+ /**
+ * This method animates the image fragment into the background by both
+ * scaling and rotating the fragment's view, as well as adding a
+ * translucent dark hover view to inform the user that it is inactive.
+ */
+ public void slideBack(AnimatorListener listener)
+ {
+ View movingFragmentView = mImageFragment.getView();
+
+ PropertyValuesHolder rotateX = PropertyValuesHolder.ofFloat("rotationX", 40f);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.8f);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 0.8f);
+ ObjectAnimator movingFragmentAnimator = ObjectAnimator.
+ ofPropertyValuesHolder(movingFragmentView, rotateX, scaleX, scaleY);
+
+ ObjectAnimator darkHoverViewAnimator = ObjectAnimator.
+ ofFloat(mDarkHoverView, "alpha", 0.0f, 0.5f);
+
+ ObjectAnimator movingFragmentRotator = ObjectAnimator.
+ ofFloat(movingFragmentView, "rotationX", 0);
+ movingFragmentRotator.setStartDelay(getResources().
+ getInteger(R.integer.half_slide_up_down_duration));
+
+ AnimatorSet s = new AnimatorSet();
+ s.playTogether(movingFragmentAnimator, darkHoverViewAnimator, movingFragmentRotator);
+ s.addListener(listener);
+ s.start();
+ }
+
+ /**
+ * This method animates the image fragment into the foreground by both
+ * scaling and rotating the fragment's view, while also removing the
+ * previously added translucent dark hover view. Upon the completion of
+ * this animation, the image fragment regains focus since this method is
+ * called from the onBackStackChanged method.
+ */
+ public void slideForward(AnimatorListener listener)
+ {
+ View movingFragmentView = mImageFragment.getView();
+
+ PropertyValuesHolder rotateX = PropertyValuesHolder.ofFloat("rotationX", 40f);
+ PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1.0f);
+ PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1.0f);
+ ObjectAnimator movingFragmentAnimator = ObjectAnimator.
+ ofPropertyValuesHolder(movingFragmentView, rotateX, scaleX, scaleY);
+
+ ObjectAnimator darkHoverViewAnimator = ObjectAnimator.
+ ofFloat(mDarkHoverView, "alpha", 0.5f, 0.0f);
+
+ ObjectAnimator movingFragmentRotator = ObjectAnimator.
+ ofFloat(movingFragmentView, "rotationX", 0);
+ movingFragmentRotator.setStartDelay(
+ getResources().getInteger(R.integer.half_slide_up_down_duration));
+
+ AnimatorSet s = new AnimatorSet();
+ s.playTogether(movingFragmentAnimator, movingFragmentRotator, darkHoverViewAnimator);
+ s.setStartDelay(getResources().getInteger(R.integer.slide_up_down_duration));
+ s.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mIsAnimating = false;
+ }
+ });
+ s.start();
+ }
+
+ public void onAnimationEnd() {
+ mIsAnimating = false;
+ }
+}
diff --git a/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/TextFragment.java b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/TextFragment.java
new file mode 100644
index 000000000..f1f245cee
--- /dev/null
+++ b/samples/devbytes/animation/SlidingFragments/src/com/example/android/slidingfragments/TextFragment.java
@@ -0,0 +1,65 @@
+/*
+ * 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.slidingfragments;
+
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class TextFragment extends Fragment {
+
+ View.OnClickListener clickListener;
+ OnTextFragmentAnimationEndListener mListener;
+
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.text_fragment, container, false);
+ view.setOnClickListener(clickListener);
+ return view;
+ }
+
+ public void setClickListener(View.OnClickListener clickListener) {
+ this.clickListener = clickListener;
+ }
+
+ @Override
+ public Animator onCreateAnimator(int transit, boolean enter, int nextAnim)
+ {
+ int id = enter ? R.animator.slide_fragment_in : R.animator.slide_fragment_out;
+ final Animator anim = AnimatorInflater.loadAnimator(getActivity(), id);
+ if (enter) {
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mListener.onAnimationEnd();
+ }
+ });
+ }
+ return anim;
+ }
+
+ public void setOnTextFragmentAnimationEnd(OnTextFragmentAnimationEndListener listener)
+ {
+ mListener = listener;
+ }
+
+}