upload android base code part7
|
@ -0,0 +1,45 @@
|
|||
<!-- 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.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.android.activityanim"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="16"
|
||||
android:targetSdkVersion="17" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme" >
|
||||
<activity
|
||||
android:name="com.example.android.activityanim.ActivityAnimations"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.example.android.activityanim.PictureDetailsActivity"
|
||||
android:label="@string/subactivity_name"
|
||||
android:theme="@style/Transparent" >
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 183 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 222 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,21 @@
|
|||
<!-- 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.
|
||||
-->
|
||||
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:id="@+id/gridLayout" >
|
||||
|
||||
</GridLayout>
|
|
@ -0,0 +1,41 @@
|
|||
<!-- 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.
|
||||
-->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/topLevelLayout">
|
||||
|
||||
<view
|
||||
class="com.example.android.activityanim.ShadowLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/shadowLayout"
|
||||
android:visibility="visible" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/imageView" />
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
|
||||
</view>
|
||||
</FrameLayout>
|
|
@ -0,0 +1,24 @@
|
|||
<!-- 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.
|
||||
-->
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_slow"
|
||||
android:orderInCategory="100"
|
||||
android:showAsAction="never"
|
||||
android:title="@string/menu_slow_animations"
|
||||
android:checkable="true"/>
|
||||
|
||||
</menu>
|
|
@ -0,0 +1,21 @@
|
|||
<!-- 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.
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<string name="app_name">Activity Animations</string>
|
||||
<string name="subactivity_name">PictureInfo!</string>
|
||||
<string name="menu_slow_animations">Slow</string>
|
||||
|
||||
</resources>
|
|
@ -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.
|
||||
-->
|
||||
<resources xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Holo.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
|
||||
<style name="Transparent">
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* 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.activityanim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* This example shows how to create a custom activity animation when you want something more
|
||||
* than window animations can provide. The idea is to disable window animations for the
|
||||
* activities and to instead launch or return from the sub-activity immediately, but use
|
||||
* property animations inside the activities to customize the transition.
|
||||
*
|
||||
* Watch the associated video for this demo on the DevBytes channel of developer.android.com
|
||||
* or on the DevBytes playlist in the androiddevelopers channel on YouTube at
|
||||
* https://www.youtube.com/playlist?list=PLWz5rJ2EKKc_XOgcRukSoKKjewFJZrKV0.
|
||||
*/
|
||||
public class ActivityAnimations extends Activity {
|
||||
|
||||
private static final String PACKAGE = "com.example.android.activityanim";
|
||||
static float sAnimatorScale = 1;
|
||||
|
||||
GridLayout mGridLayout;
|
||||
HashMap<ImageView, PictureData> mPicturesData = new HashMap<ImageView, PictureData>();
|
||||
BitmapUtils mBitmapUtils = new BitmapUtils();
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_animations);
|
||||
|
||||
// Grayscale filter used on all thumbnails
|
||||
ColorMatrix grayMatrix = new ColorMatrix();
|
||||
grayMatrix.setSaturation(0);
|
||||
ColorMatrixColorFilter grayscaleFilter = new ColorMatrixColorFilter(grayMatrix);
|
||||
|
||||
mGridLayout = (GridLayout) findViewById(R.id.gridLayout);
|
||||
mGridLayout.setColumnCount(3);
|
||||
mGridLayout.setUseDefaultMargins(true);
|
||||
|
||||
// add all photo thumbnails to layout
|
||||
Resources resources = getResources();
|
||||
ArrayList<PictureData> pictures = mBitmapUtils.loadPhotos(resources);
|
||||
for (int i = 0; i < pictures.size(); ++i) {
|
||||
PictureData pictureData = pictures.get(i);
|
||||
BitmapDrawable thumbnailDrawable =
|
||||
new BitmapDrawable(resources, pictureData.thumbnail);
|
||||
thumbnailDrawable.setColorFilter(grayscaleFilter);
|
||||
ImageView imageView = new ImageView(this);
|
||||
imageView.setOnClickListener(thumbnailClickListener);
|
||||
imageView.setImageDrawable(thumbnailDrawable);
|
||||
mPicturesData.put(imageView, pictureData);
|
||||
mGridLayout.addView(imageView);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.activity_better_window_animations, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.menu_slow) {
|
||||
sAnimatorScale = item.isChecked() ? 1 : 5;
|
||||
item.setChecked(!item.isChecked());
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the user clicks a thumbnail, bundle up information about it and launch the
|
||||
* details activity.
|
||||
*/
|
||||
private View.OnClickListener thumbnailClickListener = new View.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// Interesting data to pass across are the thumbnail size/location, the
|
||||
// resourceId of the source bitmap, the picture description, and the
|
||||
// orientation (to avoid returning back to an obsolete configuration if
|
||||
// the device rotates again in the meantime)
|
||||
int[] screenLocation = new int[2];
|
||||
v.getLocationOnScreen(screenLocation);
|
||||
PictureData info = mPicturesData.get(v);
|
||||
Intent subActivity = new Intent(ActivityAnimations.this,
|
||||
PictureDetailsActivity.class);
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
subActivity.
|
||||
putExtra(PACKAGE + ".orientation", orientation).
|
||||
putExtra(PACKAGE + ".resourceId", info.resourceId).
|
||||
putExtra(PACKAGE + ".left", screenLocation[0]).
|
||||
putExtra(PACKAGE + ".top", screenLocation[1]).
|
||||
putExtra(PACKAGE + ".width", v.getWidth()).
|
||||
putExtra(PACKAGE + ".height", v.getHeight()).
|
||||
putExtra(PACKAGE + ".description", info.description);
|
||||
startActivity(subActivity);
|
||||
|
||||
// Override transitions: we don't want the normal window animation in addition
|
||||
// to our custom one
|
||||
overridePendingTransition(0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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.activityanim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class BitmapUtils {
|
||||
|
||||
int[] mPhotos = {
|
||||
R.drawable.p1,
|
||||
R.drawable.p2,
|
||||
R.drawable.p3,
|
||||
R.drawable.p4
|
||||
};
|
||||
|
||||
String[] mDescriptions = {
|
||||
"This picture was taken while sunbathing in a natural hot spring, which was " +
|
||||
"unfortunately filled with acid, which is a lasting memory from that trip, whenever I " +
|
||||
"I look at my own skin.",
|
||||
"I took this shot with a pinhole camera mounted on a tripod constructed out of " +
|
||||
"soda straws. I felt that that combination best captured the beauty of the landscape " +
|
||||
"in juxtaposition with the detritus of mankind.",
|
||||
"I don't remember where or when I took this picture. All I know is that I was really " +
|
||||
"drunk at the time, and I woke up without my left sock.",
|
||||
"Right before I took this picture, there was a busload of school children right " +
|
||||
"in my way. I knew the perfect shot was coming, so I quickly yelled 'Free candy!!!' " +
|
||||
"and they scattered.",
|
||||
};
|
||||
|
||||
static HashMap<Integer, Bitmap> sBitmapResourceMap = new HashMap<Integer, Bitmap>();
|
||||
|
||||
/**
|
||||
* Load pictures and descriptions. A real app wouldn't do it this way, but that's
|
||||
* not the point of this animation demo. Loading asynchronously is a better way to go
|
||||
* for what can be time-consuming operations.
|
||||
*/
|
||||
public ArrayList<PictureData> loadPhotos(Resources resources) {
|
||||
ArrayList<PictureData> pictures = new ArrayList<PictureData>();
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
int resourceId = mPhotos[(int) (Math.random() * mPhotos.length)];
|
||||
Bitmap bitmap = getBitmap(resources, resourceId);
|
||||
Bitmap thumbnail = getThumbnail(bitmap, 200);
|
||||
String description = mDescriptions[(int) (Math.random() * mDescriptions.length)];
|
||||
pictures.add(new PictureData(resourceId, description, thumbnail));
|
||||
}
|
||||
return pictures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to get bitmap from cache or, if not there, load it
|
||||
* from its resource.
|
||||
*/
|
||||
static Bitmap getBitmap(Resources resources, int resourceId) {
|
||||
Bitmap bitmap = sBitmapResourceMap.get(resourceId);
|
||||
if (bitmap == null) {
|
||||
bitmap = BitmapFactory.decodeResource(resources, resourceId);
|
||||
sBitmapResourceMap.put(resourceId, bitmap);
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a thumbnail image given the original source bitmap and a max
|
||||
* dimension (width or height).
|
||||
*/
|
||||
private Bitmap getThumbnail(Bitmap original, int maxDimension) {
|
||||
int width = original.getWidth();
|
||||
int height = original.getHeight();
|
||||
int scaledWidth, scaledHeight;
|
||||
if (width >= height) {
|
||||
float scaleFactor = (float) maxDimension / width;
|
||||
scaledWidth = 200;
|
||||
scaledHeight = (int) (scaleFactor * height);
|
||||
} else {
|
||||
float scaleFactor = (float) maxDimension / height;
|
||||
scaledWidth = (int) (scaleFactor * width);
|
||||
scaledHeight = 200;
|
||||
}
|
||||
Bitmap thumbnail = Bitmap.createScaledBitmap(original, scaledWidth, scaledHeight, true);
|
||||
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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.activityanim;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
public class PictureData {
|
||||
int resourceId;
|
||||
String description;
|
||||
Bitmap thumbnail;
|
||||
|
||||
public PictureData(int resourceId, String description, Bitmap thumbnail) {
|
||||
this.resourceId = resourceId;
|
||||
this.description = description;
|
||||
this.thumbnail = thumbnail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* 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.activityanim;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* This sub-activity shows a zoomed-in view of a specific photo, along with the
|
||||
* picture's text description. Most of the logic is for the animations that will
|
||||
* be run when the activity is being launched and exited. When launching,
|
||||
* the large version of the picture will resize from the thumbnail version in the
|
||||
* main activity, colorizing it from the thumbnail's grayscale version at the
|
||||
* same time. Meanwhile, the black background of the activity will fade in and
|
||||
* the description will eventually slide into place. The exit animation runs all
|
||||
* of this in reverse.
|
||||
*
|
||||
*/
|
||||
public class PictureDetailsActivity extends Activity {
|
||||
|
||||
private static final TimeInterpolator sDecelerator = new DecelerateInterpolator();
|
||||
private static final TimeInterpolator sAccelerator = new AccelerateInterpolator();
|
||||
private static final String PACKAGE_NAME = "com.example.android.activityanim";
|
||||
private static final int ANIM_DURATION = 500;
|
||||
|
||||
private BitmapDrawable mBitmapDrawable;
|
||||
private ColorMatrix colorizerMatrix = new ColorMatrix();
|
||||
ColorDrawable mBackground;
|
||||
int mLeftDelta;
|
||||
int mTopDelta;
|
||||
float mWidthScale;
|
||||
float mHeightScale;
|
||||
private ImageView mImageView;
|
||||
private TextView mTextView;
|
||||
private FrameLayout mTopLevelLayout;
|
||||
private ShadowLayout mShadowLayout;
|
||||
private int mOriginalOrientation;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.picture_info);
|
||||
mImageView = (ImageView) findViewById(R.id.imageView);
|
||||
mTopLevelLayout = (FrameLayout) findViewById(R.id.topLevelLayout);
|
||||
mShadowLayout = (ShadowLayout) findViewById(R.id.shadowLayout);
|
||||
mTextView = (TextView) findViewById(R.id.description);
|
||||
|
||||
// Retrieve the data we need for the picture/description to display and
|
||||
// the thumbnail to animate it from
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
Bitmap bitmap = BitmapUtils.getBitmap(getResources(),
|
||||
bundle.getInt(PACKAGE_NAME + ".resourceId"));
|
||||
String description = bundle.getString(PACKAGE_NAME + ".description");
|
||||
final int thumbnailTop = bundle.getInt(PACKAGE_NAME + ".top");
|
||||
final int thumbnailLeft = bundle.getInt(PACKAGE_NAME + ".left");
|
||||
final int thumbnailWidth = bundle.getInt(PACKAGE_NAME + ".width");
|
||||
final int thumbnailHeight = bundle.getInt(PACKAGE_NAME + ".height");
|
||||
mOriginalOrientation = bundle.getInt(PACKAGE_NAME + ".orientation");
|
||||
|
||||
mBitmapDrawable = new BitmapDrawable(getResources(), bitmap);
|
||||
mImageView.setImageDrawable(mBitmapDrawable);
|
||||
mTextView.setText(description);
|
||||
|
||||
mBackground = new ColorDrawable(Color.BLACK);
|
||||
mTopLevelLayout.setBackground(mBackground);
|
||||
|
||||
// Only run the animation if we're coming from the parent activity, not if
|
||||
// we're recreated automatically by the window manager (e.g., device rotation)
|
||||
if (savedInstanceState == null) {
|
||||
ViewTreeObserver observer = mImageView.getViewTreeObserver();
|
||||
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
mImageView.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
|
||||
// Figure out where the thumbnail and full size versions are, relative
|
||||
// to the screen and each other
|
||||
int[] screenLocation = new int[2];
|
||||
mImageView.getLocationOnScreen(screenLocation);
|
||||
mLeftDelta = thumbnailLeft - screenLocation[0];
|
||||
mTopDelta = thumbnailTop - screenLocation[1];
|
||||
|
||||
// Scale factors to make the large version the same size as the thumbnail
|
||||
mWidthScale = (float) thumbnailWidth / mImageView.getWidth();
|
||||
mHeightScale = (float) thumbnailHeight / mImageView.getHeight();
|
||||
|
||||
runEnterAnimation();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The enter animation scales the picture in from its previous thumbnail
|
||||
* size/location, colorizing it in parallel. In parallel, the background of the
|
||||
* activity is fading in. When the pictue is in place, the text description
|
||||
* drops down.
|
||||
*/
|
||||
public void runEnterAnimation() {
|
||||
final long duration = (long) (ANIM_DURATION * ActivityAnimations.sAnimatorScale);
|
||||
|
||||
// Set starting values for properties we're going to animate. These
|
||||
// values scale and position the full size version down to the thumbnail
|
||||
// size/location, from which we'll animate it back up
|
||||
mImageView.setPivotX(0);
|
||||
mImageView.setPivotY(0);
|
||||
mImageView.setScaleX(mWidthScale);
|
||||
mImageView.setScaleY(mHeightScale);
|
||||
mImageView.setTranslationX(mLeftDelta);
|
||||
mImageView.setTranslationY(mTopDelta);
|
||||
|
||||
// We'll fade the text in later
|
||||
mTextView.setAlpha(0);
|
||||
|
||||
// Animate scale and translation to go from thumbnail to full size
|
||||
mImageView.animate().setDuration(duration).
|
||||
scaleX(1).scaleY(1).
|
||||
translationX(0).translationY(0).
|
||||
setInterpolator(sDecelerator).
|
||||
withEndAction(new Runnable() {
|
||||
public void run() {
|
||||
// Animate the description in after the image animation
|
||||
// is done. Slide and fade the text in from underneath
|
||||
// the picture.
|
||||
mTextView.setTranslationY(-mTextView.getHeight());
|
||||
mTextView.animate().setDuration(duration/2).
|
||||
translationY(0).alpha(1).
|
||||
setInterpolator(sDecelerator);
|
||||
}
|
||||
});
|
||||
|
||||
// Fade in the black background
|
||||
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mBackground, "alpha", 0, 255);
|
||||
bgAnim.setDuration(duration);
|
||||
bgAnim.start();
|
||||
|
||||
// Animate a color filter to take the image from grayscale to full color.
|
||||
// This happens in parallel with the image scaling and moving into place.
|
||||
ObjectAnimator colorizer = ObjectAnimator.ofFloat(PictureDetailsActivity.this,
|
||||
"saturation", 0, 1);
|
||||
colorizer.setDuration(duration);
|
||||
colorizer.start();
|
||||
|
||||
// Animate a drop-shadow of the image
|
||||
ObjectAnimator shadowAnim = ObjectAnimator.ofFloat(mShadowLayout, "shadowDepth", 0, 1);
|
||||
shadowAnim.setDuration(duration);
|
||||
shadowAnim.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* The exit animation is basically a reverse of the enter animation, except that if
|
||||
* the orientation has changed we simply scale the picture back into the center of
|
||||
* the screen.
|
||||
*
|
||||
* @param endAction This action gets run after the animation completes (this is
|
||||
* when we actually switch activities)
|
||||
*/
|
||||
public void runExitAnimation(final Runnable endAction) {
|
||||
final long duration = (long) (ANIM_DURATION * ActivityAnimations.sAnimatorScale);
|
||||
|
||||
// No need to set initial values for the reverse animation; the image is at the
|
||||
// starting size/location that we want to start from. Just animate to the
|
||||
// thumbnail size/location that we retrieved earlier
|
||||
|
||||
// Caveat: configuration change invalidates thumbnail positions; just animate
|
||||
// the scale around the center. Also, fade it out since it won't match up with
|
||||
// whatever's actually in the center
|
||||
final boolean fadeOut;
|
||||
if (getResources().getConfiguration().orientation != mOriginalOrientation) {
|
||||
mImageView.setPivotX(mImageView.getWidth() / 2);
|
||||
mImageView.setPivotY(mImageView.getHeight() / 2);
|
||||
mLeftDelta = 0;
|
||||
mTopDelta = 0;
|
||||
fadeOut = true;
|
||||
} else {
|
||||
fadeOut = false;
|
||||
}
|
||||
|
||||
// First, slide/fade text out of the way
|
||||
mTextView.animate().translationY(-mTextView.getHeight()).alpha(0).
|
||||
setDuration(duration/2).setInterpolator(sAccelerator).
|
||||
withEndAction(new Runnable() {
|
||||
public void run() {
|
||||
// Animate image back to thumbnail size/location
|
||||
mImageView.animate().setDuration(duration).
|
||||
scaleX(mWidthScale).scaleY(mHeightScale).
|
||||
translationX(mLeftDelta).translationY(mTopDelta).
|
||||
withEndAction(endAction);
|
||||
if (fadeOut) {
|
||||
mImageView.animate().alpha(0);
|
||||
}
|
||||
// Fade out background
|
||||
ObjectAnimator bgAnim = ObjectAnimator.ofInt(mBackground, "alpha", 0);
|
||||
bgAnim.setDuration(duration);
|
||||
bgAnim.start();
|
||||
|
||||
// Animate the shadow of the image
|
||||
ObjectAnimator shadowAnim = ObjectAnimator.ofFloat(mShadowLayout,
|
||||
"shadowDepth", 1, 0);
|
||||
shadowAnim.setDuration(duration);
|
||||
shadowAnim.start();
|
||||
|
||||
// Animate a color filter to take the image back to grayscale,
|
||||
// in parallel with the image scaling and moving into place.
|
||||
ObjectAnimator colorizer =
|
||||
ObjectAnimator.ofFloat(PictureDetailsActivity.this,
|
||||
"saturation", 1, 0);
|
||||
colorizer.setDuration(duration);
|
||||
colorizer.start();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriding this method allows us to run our exit animation first, then exiting
|
||||
* the activity when it is complete.
|
||||
*/
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
runExitAnimation(new Runnable() {
|
||||
public void run() {
|
||||
// *Now* go ahead and exit the activity
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called by the colorizing animator. It sets a saturation factor that is then
|
||||
* passed onto a filter on the picture's drawable.
|
||||
* @param value
|
||||
*/
|
||||
public void setSaturation(float value) {
|
||||
colorizerMatrix.setSaturation(value);
|
||||
ColorMatrixColorFilter colorizerFilter = new ColorMatrixColorFilter(colorizerMatrix);
|
||||
mBitmapDrawable.setColorFilter(colorizerFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
|
||||
// override transitions to skip the standard window animations
|
||||
overridePendingTransition(0, 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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.activityanim;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BlurMaskFilter;
|
||||
import android.graphics.BlurMaskFilter.Blur;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Style;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
/**
|
||||
* This custom layout paints a drop shadow behind all children. The size and opacity
|
||||
* of the drop shadow is determined by a "depth" factor that can be set and animated.
|
||||
*/
|
||||
public class ShadowLayout extends RelativeLayout {
|
||||
|
||||
Paint mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
float mShadowDepth;
|
||||
Bitmap mShadowBitmap;
|
||||
static final int BLUR_RADIUS = 6;
|
||||
static final RectF sShadowRectF = new RectF(0, 0, 200, 200);
|
||||
static final Rect sShadowRect = new Rect(0, 0, 200 + 2 * BLUR_RADIUS, 200 + 2 * BLUR_RADIUS);
|
||||
static RectF tempShadowRectF = new RectF(0, 0, 0, 0);
|
||||
|
||||
public ShadowLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public ShadowLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ShadowLayout(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the constructors - sets up the drawing parameters for the drop shadow.
|
||||
*/
|
||||
private void init() {
|
||||
mShadowPaint.setColor(Color.BLACK);
|
||||
mShadowPaint.setStyle(Style.FILL);
|
||||
setWillNotDraw(false);
|
||||
mShadowBitmap = Bitmap.createBitmap(sShadowRect.width(),
|
||||
sShadowRect.height(), Bitmap.Config.ARGB_8888);
|
||||
Canvas c = new Canvas(mShadowBitmap);
|
||||
mShadowPaint.setMaskFilter(new BlurMaskFilter(BLUR_RADIUS, Blur.NORMAL));
|
||||
c.translate(BLUR_RADIUS, BLUR_RADIUS);
|
||||
c.drawRoundRect(sShadowRectF, sShadowRectF.width() / 40,
|
||||
sShadowRectF.height() / 40, mShadowPaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* The "depth" factor determines the offset distance and opacity of the shadow (shadows that
|
||||
* are further away from the source are offset greater and are more translucent).
|
||||
* @param depth
|
||||
*/
|
||||
public void setShadowDepth(float depth) {
|
||||
if (depth != mShadowDepth) {
|
||||
mShadowDepth = depth;
|
||||
mShadowPaint.setAlpha((int) (100 + 150 * (1 - mShadowDepth)));
|
||||
invalidate(); // We need to redraw when the shadow attributes change
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overriding onDraw allows us to draw shadows behind every child of this container.
|
||||
* onDraw() is called to draw a layout's content before the children are drawn, so the
|
||||
* shadows will be drawn first, behind the children (which is what we want).
|
||||
*/
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
for (int i = 0; i < getChildCount(); ++i) {
|
||||
View child = getChildAt(i);
|
||||
if (child.getVisibility() != View.VISIBLE || child.getAlpha() == 0) {
|
||||
continue;
|
||||
}
|
||||
int depthFactor = (int) (80 * mShadowDepth);
|
||||
canvas.save();
|
||||
canvas.translate(child.getLeft() + depthFactor,
|
||||
child.getTop() + depthFactor);
|
||||
canvas.concat(child.getMatrix());
|
||||
tempShadowRectF.right = child.getWidth();
|
||||
tempShadowRectF.bottom = child.getHeight();
|
||||
canvas.drawBitmap(mShadowBitmap, sShadowRect, tempShadowRectF, mShadowPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|