upload android base code part7

This commit is contained in:
August 2018-08-08 18:09:17 +08:00
parent 4e516ec6ed
commit 841ae54672
25229 changed files with 1709508 additions and 0 deletions

View file

@ -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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.bitmapallocation"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="15"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.android.bitmapallocation.BitmapAllocation"
android:label="@string/title_activity_bitmap_allocation" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,38 @@
<!-- 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<CheckBox
android:id="@+id/checkbox"
android:text="@string/reuse_bitmap"
android:checked="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/loadDuration"
android:textSize="30sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/imageview"
android:adjustViewBounds="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View file

@ -0,0 +1,19 @@
<!-- 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>
<style name="AppTheme" parent="android:Theme.Holo.Light" />
</resources>

View file

@ -0,0 +1,19 @@
<!-- 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>
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
</resources>

View file

@ -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">BitmapAllocation</string>
<string name="title_activity_bitmap_allocation">BitmapAllocation</string>
<string name="reuse_bitmap">Reuse Bitmap</string>
</resources>

View file

@ -0,0 +1,19 @@
<!-- 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>
<style name="AppTheme" parent="android:Theme.Light" />
</resources>

View file

@ -0,0 +1,99 @@
/*
* 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.bitmapallocation;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
/**
* This example shows how to speed up bitmap loading and reduce garbage collection
* by reusing existing bitmaps.
*
* Watch the associated video for this demo on the DevBytes channel of developer.android.com,
* or on YouTube at https://www.youtube.com/watch?v=rsQet4nBVi8.
*/
public class BitmapAllocation extends Activity {
// There are some assumptions in this demo app that don't carry over well to the real world:
// it assumes that all bitmaps are the same size and that loading all bitmaps as the activity
// starts is good enough. A real application would be take a more flexible and robust
// approach. But these assumptions are good enough for the purposes of this tutorial,
// which is about reusing existing bitmaps of the same size.
int mCurrentIndex = 0;
Bitmap mCurrentBitmap = null;
BitmapFactory.Options mBitmapOptions;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmap_allocation);
final int[] imageIDs = {R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d,
R.drawable.e, R.drawable.f};
final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
final TextView durationTextview = (TextView) findViewById(R.id.loadDuration);
final ImageView imageview = (ImageView) findViewById(R.id.imageview);
// Create bitmap to be re-used, based on the size of one of the bitmaps
mBitmapOptions = new BitmapFactory.Options();
mBitmapOptions.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.a, mBitmapOptions);
mCurrentBitmap = Bitmap.createBitmap(mBitmapOptions.outWidth,
mBitmapOptions.outHeight, Bitmap.Config.ARGB_8888);
mBitmapOptions.inJustDecodeBounds = false;
mBitmapOptions.inBitmap = mCurrentBitmap;
mBitmapOptions.inSampleSize = 1;
BitmapFactory.decodeResource(getResources(), R.drawable.a, mBitmapOptions);
imageview.setImageBitmap(mCurrentBitmap);
// When the user clicks on the image, load the next one in the list
imageview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCurrentIndex = (mCurrentIndex + 1) % imageIDs.length;
BitmapFactory.Options bitmapOptions = null;
if (checkbox.isChecked()) {
// Re-use the bitmap by using BitmapOptions.inBitmap
bitmapOptions = mBitmapOptions;
bitmapOptions.inBitmap = mCurrentBitmap;
}
long startTime = System.currentTimeMillis();
mCurrentBitmap = BitmapFactory.decodeResource(getResources(),
imageIDs[mCurrentIndex], bitmapOptions);
imageview.setImageBitmap(mCurrentBitmap);
// One way you can see the difference between reusing and not is through the
// timing reported here. But you can also see a huge impact in the garbage
// collector if you look at logcat with and without reuse. Avoiding garbage
// collection when possible, especially for large items like bitmaps,
// is always a good idea.
durationTextview.setText("Load took " +
(System.currentTimeMillis() - startTime));
}
});
}
}

View file

@ -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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.bitmapscaling"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.android.bitmapscaling.BitmapScaling"
android:label="@string/title_activity_bitmap_scaling" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:text="@string/original_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/originalImageHolder"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:text="@string/scaled_images"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/scaledImageContainer"
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View file

@ -0,0 +1,19 @@
<!-- 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>
<style name="AppTheme" parent="android:Theme.Holo.Light" />
</resources>

View file

@ -0,0 +1,19 @@
<!-- 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>
<style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
</resources>

View file

@ -0,0 +1,22 @@
<!-- 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">BitmapScaling</string>
<string name="title_activity_bitmap_scaling">BitmapScaling</string>
<string name="original_image">Original Image</string>
<string name="scaled_images">Scaled Images</string>
</resources>

View file

@ -0,0 +1,19 @@
<!-- 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>
<style name="AppTheme" parent="android:Theme.Light" />
</resources>

View file

@ -0,0 +1,75 @@
/*
* 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.bitmapscaling;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
/**
* This example shows how the use of BitmapOptions affects the resulting size of a loaded
* bitmap. Sub-sampling can speed up load times and reduce the need for large bitmaps
* in memory if your target bitmap size is much smaller, although it's good to understand
* that you can't get specific Bitmap sizes, but rather power-of-two reductions in sizes.
*
* Watch the associated video for this demo on the DevBytes channel of developer.android.com
* or on YouTube at https://www.youtube.com/watch?v=12cB7gnL6po.
*/
public class BitmapScaling extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmap_scaling);
LinearLayout container = (LinearLayout) findViewById(R.id.scaledImageContainer);
ImageView originalImageView = (ImageView) findViewById(R.id.originalImageHolder);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.jellybean_statue);
originalImageView.setImageBitmap(bitmap);
for (int i = 2; i < 10; ++i) {
addScaledImageView(bitmap, i, container);
}
}
private void addScaledImageView(Bitmap original, int sampleSize, LinearLayout container) {
// inSampleSize tells the loader how much to scale the final image, which it does at
// load time by simply reading less pixels for every pixel value in the final bitmap.
// Note that it only scales by powers of two, so a value of two results in a bitmap
// 1/2 the size of the original and a value of four results in a bitmap 1/4 the original
// size. Intermediate values are rounded down, so a value of three results in a bitmap 1/2
// the original size.
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inSampleSize = sampleSize;
Bitmap scaledBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.jellybean_statue, bitmapOptions);
ImageView scaledImageView = new ImageView(this);
scaledImageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
scaledImageView.setImageBitmap(scaledBitmap);
container.addView(scaledImageView);
}
}

View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.foldinglayout"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-sdk android:minSdkVersion="17"
android:targetSdkVersion="18"/>
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name=".FoldingLayoutActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.android.foldinglayout.FoldingLayout
android:layout_weight="1"
android:id="@+id/fold_view"
android:layout_width="match_parent"
android:layout_height="0dp">
<ImageView
android:id="@+id/image_view"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:scaleType="fitXY"/>
</com.example.android.foldinglayout.FoldingLayout>
<SeekBar
android:id="@+id/anchor_seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"/>
</LinearLayout>

View file

@ -0,0 +1,18 @@
<!-- 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.
-->
<Spinner xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/num_of_folds_array" />

View file

@ -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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/toggle_orientation"
android:showAsAction="never"
android:title="@string/vertical"/>
<item
android:id="@+id/num_of_folds"
android:showAsAction="ifRoom"
android:actionLayout="@layout/spinner"/>
<item
android:title="@string/sepia_effect_off"
android:id="@+id/sepia"
android:checkable="true"/>
<item
android:title="@string/camera_feed"
android:id="@+id/camera_feed"/>
<item
android:id="@+id/animate_fold"
android:showAsAction="never"
android:title="@string/animate"/>
</menu>

View file

@ -0,0 +1,32 @@
<!-- 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/toggle_orientation"
android:showAsAction="never"
android:title="@string/vertical"/>
<item
android:id="@+id/num_of_folds"
android:showAsAction="ifRoom"
android:actionLayout="@layout/spinner"/>
<item
android:id="@+id/animate_fold"
android:showAsAction="never"
android:title="@string/animate"/>
</menu>

View file

@ -0,0 +1,42 @@
<!-- 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">FoldingLayout</string>
<string name="title_activity_fold">FoldActivity</string>
<string name="horizontal">Horizontal</string>
<string name="vertical">Vertical</string>
<string name="num_of_folds">Number Of Folds</string>
<string name="animate">Animate</string>
<string name="camera_feed">Camera Feed</string>
<string name="static_image">Static Image</string>
<string name="sepia_effect_off">Sepia Off</string>
<string-array name="num_of_folds_array">
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>1</item>
</string-array>
</resources>

View file

@ -0,0 +1,546 @@
/*
* 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.foldinglayout;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* The folding layout where the number of folds, the anchor point and the
* orientation of the fold can be specified. Each of these parameters can
* be modified individually and updates and resets the fold to a default
* (unfolded) state. The fold factor varies between 0 (completely unfolded
* flat image) to 1.0 (completely folded, non-visible image).
*
* This layout throws an exception if there is more than one child added to the view.
* For more complicated view hierarchy's inside the folding layout, the views should all
* be nested inside 1 parent layout.
*
* This layout folds the contents of its child in real time. By applying matrix
* transformations when drawing to canvas, the contents of the child may change as
* the fold takes place. It is important to note that there are jagged edges about
* the perimeter of the layout as a result of applying transformations to a rectangle.
* This can be avoided by having the child of this layout wrap its content inside a
* 1 pixel transparent border. This will cause an anti-aliasing like effect and smoothen
* out the edges.
*
*/
public class FoldingLayout extends ViewGroup {
public static enum Orientation {
VERTICAL,
HORIZONTAL
}
private final String FOLDING_VIEW_EXCEPTION_MESSAGE = "Folding Layout can only 1 child at " +
"most";
private final float SHADING_ALPHA = 0.8f;
private final float SHADING_FACTOR = 0.5f;
private final int DEPTH_CONSTANT = 1500;
private final int NUM_OF_POLY_POINTS = 8;
private Rect[] mFoldRectArray;
private Matrix [] mMatrix;
private Orientation mOrientation = Orientation.HORIZONTAL;
private float mAnchorFactor = 0;
private float mFoldFactor = 0;
private int mNumberOfFolds = 2;
private boolean mIsHorizontal = true;
private int mOriginalWidth = 0;
private int mOriginalHeight = 0;
private float mFoldMaxWidth = 0;
private float mFoldMaxHeight = 0;
private float mFoldDrawWidth = 0;
private float mFoldDrawHeight = 0;
private boolean mIsFoldPrepared = false;
private boolean mShouldDraw = true;
private Paint mSolidShadow;
private Paint mGradientShadow;
private LinearGradient mShadowLinearGradient;
private Matrix mShadowGradientMatrix;
private float [] mSrc;
private float [] mDst;
private OnFoldListener mFoldListener;
private float mPreviousFoldFactor = 0;
private Bitmap mFullBitmap;
private Rect mDstRect;
public FoldingLayout(Context context) {
super(context);
}
public FoldingLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FoldingLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected boolean addViewInLayout(View child, int index, LayoutParams params,
boolean preventRequestLayout) {
throwCustomException(getChildCount());
boolean returnValue = super.addViewInLayout(child, index, params, preventRequestLayout);
return returnValue;
}
@Override
public void addView(View child, int index, LayoutParams params) {
throwCustomException(getChildCount());
super.addView(child, index, params);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View child = getChildAt(0);
measureChild(child,widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
View child = getChildAt(0);
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
updateFold();
}
/**
* The custom exception to be thrown so as to limit the number of views in this
* layout to at most one.
*/
private class NumberOfFoldingLayoutChildrenException extends RuntimeException {
public NumberOfFoldingLayoutChildrenException(String message) {
super(message);
}
}
/** Throws an exception if the number of views added to this layout exceeds one.*/
private void throwCustomException (int numOfChildViews) {
if (numOfChildViews == 1) {
throw new NumberOfFoldingLayoutChildrenException(FOLDING_VIEW_EXCEPTION_MESSAGE);
}
}
public void setFoldListener(OnFoldListener foldListener) {
mFoldListener = foldListener;
}
/**
* Sets the fold factor of the folding view and updates all the corresponding
* matrices and values to account for the new fold factor. Once that is complete,
* it redraws itself with the new fold. */
public void setFoldFactor(float foldFactor) {
if (foldFactor != mFoldFactor) {
mFoldFactor = foldFactor;
calculateMatrices();
invalidate();
}
}
public void setOrientation(Orientation orientation) {
if (orientation != mOrientation) {
mOrientation = orientation;
updateFold();
}
}
public void setAnchorFactor(float anchorFactor) {
if (anchorFactor != mAnchorFactor) {
mAnchorFactor = anchorFactor;
updateFold();
}
}
public void setNumberOfFolds(int numberOfFolds) {
if (numberOfFolds != mNumberOfFolds) {
mNumberOfFolds = numberOfFolds;
updateFold();
}
}
public float getAnchorFactor() {
return mAnchorFactor;
}
public Orientation getOrientation() {
return mOrientation;
}
public float getFoldFactor() {
return mFoldFactor;
}
public int getNumberOfFolds() {
return mNumberOfFolds;
}
private void updateFold() {
prepareFold(mOrientation, mAnchorFactor, mNumberOfFolds);
calculateMatrices();
invalidate();
}
/**
* This method is called in order to update the fold's orientation, anchor
* point and number of folds. This creates the necessary setup in order to
* prepare the layout for a fold with the specified parameters. Some of the
* dimensions required for the folding transformation are also acquired here.
*
* After this method is called, it will be in a completely unfolded state by default.
*/
private void prepareFold(Orientation orientation, float anchorFactor, int numberOfFolds) {
mSrc = new float[NUM_OF_POLY_POINTS];
mDst = new float[NUM_OF_POLY_POINTS];
mDstRect = new Rect();
mFoldFactor = 0;
mPreviousFoldFactor = 0;
mIsFoldPrepared = false;
mSolidShadow = new Paint();
mGradientShadow = new Paint();
mOrientation = orientation;
mIsHorizontal = (orientation == Orientation.HORIZONTAL);
if (mIsHorizontal) {
mShadowLinearGradient = new LinearGradient(0, 0, SHADING_FACTOR, 0, Color.BLACK,
Color.TRANSPARENT, TileMode.CLAMP);
} else {
mShadowLinearGradient = new LinearGradient(0, 0, 0, SHADING_FACTOR, Color.BLACK,
Color.TRANSPARENT, TileMode.CLAMP);
}
mGradientShadow.setStyle(Style.FILL);
mGradientShadow.setShader(mShadowLinearGradient);
mShadowGradientMatrix = new Matrix();
mAnchorFactor = anchorFactor;
mNumberOfFolds = numberOfFolds;
mOriginalWidth = getMeasuredWidth();
mOriginalHeight = getMeasuredHeight();
mFoldRectArray = new Rect[mNumberOfFolds];
mMatrix = new Matrix [mNumberOfFolds];
for (int x = 0; x < mNumberOfFolds; x++) {
mMatrix[x] = new Matrix();
}
int h = mOriginalHeight;
int w = mOriginalWidth;
if (FoldingLayoutActivity.IS_JBMR2) {
mFullBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(mFullBitmap);
getChildAt(0).draw(canvas);
}
int delta = Math.round(mIsHorizontal ? ((float) w) / ((float) mNumberOfFolds) :
((float) h) /((float) mNumberOfFolds));
/* Loops through the number of folds and segments the full layout into a number
* of smaller equal components. If the number of folds is odd, then one of the
* components will be smaller than all the rest. Note that deltap below handles
* the calculation for an odd number of folds.*/
for (int x = 0; x < mNumberOfFolds; x++) {
if (mIsHorizontal) {
int deltap = (x + 1) * delta > w ? w - x * delta : delta;
mFoldRectArray[x] = new Rect(x * delta, 0, x * delta + deltap, h);
} else {
int deltap = (x + 1) * delta > h ? h - x * delta : delta;
mFoldRectArray[x] = new Rect(0, x * delta, w, x * delta + deltap);
}
}
if (mIsHorizontal) {
mFoldMaxHeight = h;
mFoldMaxWidth = delta;
} else {
mFoldMaxHeight = delta;
mFoldMaxWidth = w;
}
mIsFoldPrepared = true;
}
/*
* Calculates the transformation matrices used to draw each of the separate folding
* segments from this view.
*/
private void calculateMatrices() {
mShouldDraw = true;
if (!mIsFoldPrepared) {
return;
}
/** If the fold factor is 1 than the folding view should not be seen
* and the canvas can be left completely empty. */
if (mFoldFactor == 1) {
mShouldDraw = false;
return;
}
if (mFoldFactor == 0 && mPreviousFoldFactor > 0) {
mFoldListener.onEndFold();
}
if (mPreviousFoldFactor == 0 && mFoldFactor > 0) {
mFoldListener.onStartFold();
}
mPreviousFoldFactor = mFoldFactor;
/* Reset all the transformation matrices back to identity before computing
* the new transformation */
for (int x = 0; x < mNumberOfFolds; x++) {
mMatrix[x].reset();
}
float cTranslationFactor = 1 - mFoldFactor;
float translatedDistance = mIsHorizontal ? mOriginalWidth * cTranslationFactor :
mOriginalHeight * cTranslationFactor;
float translatedDistancePerFold = Math.round(translatedDistance / mNumberOfFolds);
/* For an odd number of folds, the rounding error may cause the
* translatedDistancePerFold to be grater than the max fold width or height. */
mFoldDrawWidth = mFoldMaxWidth < translatedDistancePerFold ?
translatedDistancePerFold : mFoldMaxWidth;
mFoldDrawHeight = mFoldMaxHeight < translatedDistancePerFold ?
translatedDistancePerFold : mFoldMaxHeight;
float translatedDistanceFoldSquared = translatedDistancePerFold * translatedDistancePerFold;
/* Calculate the depth of the fold into the screen using pythagorean theorem. */
float depth = mIsHorizontal ?
(float)Math.sqrt((double)(mFoldDrawWidth * mFoldDrawWidth -
translatedDistanceFoldSquared)) :
(float)Math.sqrt((double)(mFoldDrawHeight * mFoldDrawHeight -
translatedDistanceFoldSquared));
/* The size of some object is always inversely proportional to the distance
* it is away from the viewpoint. The constant can be varied to to affect the
* amount of perspective. */
float scaleFactor = DEPTH_CONSTANT / (DEPTH_CONSTANT + depth);
float scaledWidth, scaledHeight, bottomScaledPoint, topScaledPoint, rightScaledPoint,
leftScaledPoint;
if (mIsHorizontal) {
scaledWidth = mFoldDrawWidth * cTranslationFactor;
scaledHeight = mFoldDrawHeight * scaleFactor;
} else {
scaledWidth = mFoldDrawWidth * scaleFactor;
scaledHeight = mFoldDrawHeight * cTranslationFactor;
}
topScaledPoint = (mFoldDrawHeight - scaledHeight) / 2.0f;
bottomScaledPoint = topScaledPoint + scaledHeight;
leftScaledPoint = (mFoldDrawWidth - scaledWidth) / 2.0f;
rightScaledPoint = leftScaledPoint + scaledWidth;
float anchorPoint = mIsHorizontal ? mAnchorFactor * mOriginalWidth :
mAnchorFactor * mOriginalHeight;
/* The fold along which the anchor point is located. */
float midFold = mIsHorizontal ? (anchorPoint / mFoldDrawWidth) : anchorPoint /
mFoldDrawHeight;
mSrc[0] = 0;
mSrc[1] = 0;
mSrc[2] = 0;
mSrc[3] = mFoldDrawHeight;
mSrc[4] = mFoldDrawWidth;
mSrc[5] = 0;
mSrc[6] = mFoldDrawWidth;
mSrc[7] = mFoldDrawHeight;
/* Computes the transformation matrix for each fold using the values calculated above. */
for (int x = 0; x < mNumberOfFolds; x++) {
boolean isEven = (x % 2 == 0);
if (mIsHorizontal) {
mDst[0] = (anchorPoint > x * mFoldDrawWidth) ? anchorPoint + (x - midFold) *
scaledWidth : anchorPoint - (midFold - x) * scaledWidth;
mDst[1] = isEven ? 0 : topScaledPoint;
mDst[2] = mDst[0];
mDst[3] = isEven ? mFoldDrawHeight: bottomScaledPoint;
mDst[4] = (anchorPoint > (x + 1) * mFoldDrawWidth) ? anchorPoint + (x + 1 - midFold)
* scaledWidth : anchorPoint - (midFold - x - 1) * scaledWidth;
mDst[5] = isEven ? topScaledPoint : 0;
mDst[6] = mDst[4];
mDst[7] = isEven ? bottomScaledPoint : mFoldDrawHeight;
} else {
mDst[0] = isEven ? 0 : leftScaledPoint;
mDst[1] = (anchorPoint > x * mFoldDrawHeight) ? anchorPoint + (x - midFold) *
scaledHeight : anchorPoint - (midFold - x) * scaledHeight;
mDst[2] = isEven ? leftScaledPoint: 0;
mDst[3] = (anchorPoint > (x + 1) * mFoldDrawHeight) ? anchorPoint + (x + 1 -
midFold) * scaledHeight : anchorPoint - (midFold - x - 1) * scaledHeight;
mDst[4] = isEven ? mFoldDrawWidth : rightScaledPoint;
mDst[5] = mDst[1];
mDst[6] = isEven ? rightScaledPoint : mFoldDrawWidth;
mDst[7] = mDst[3];
}
/* Pixel fractions are present for odd number of folds which need to be
* rounded off here.*/
for (int y = 0; y < 8; y ++) {
mDst[y] = Math.round(mDst[y]);
}
/* If it so happens that any of the folds have reached a point where
* the width or height of that fold is 0, then nothing needs to be
* drawn onto the canvas because the view is essentially completely
* folded.*/
if (mIsHorizontal) {
if (mDst[4] <= mDst[0] || mDst[6] <= mDst[2]) {
mShouldDraw = false;
return;
}
} else {
if (mDst[3] <= mDst[1] || mDst[7] <= mDst[5]) {
mShouldDraw = false;
return;
}
}
/* Sets the shadow and bitmap transformation matrices.*/
mMatrix[x].setPolyToPoly(mSrc, 0, mDst, 0, NUM_OF_POLY_POINTS / 2);
}
/* The shadows on the folds are split into two parts: Solid shadows and gradients.
* Every other fold has a solid shadow which overlays the whole fold. Similarly,
* the folds in between these alternating folds also have an overlaying shadow.
* However, it is a gradient that takes up part of the fold as opposed to a solid
* shadow overlaying the whole fold.*/
/* Solid shadow paint object. */
int alpha = (int) (mFoldFactor * 255 * SHADING_ALPHA);
mSolidShadow.setColor(Color.argb(alpha, 0, 0, 0));
if (mIsHorizontal) {
mShadowGradientMatrix.setScale(mFoldDrawWidth, 1);
mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
} else {
mShadowGradientMatrix.setScale(1, mFoldDrawHeight);
mShadowLinearGradient.setLocalMatrix(mShadowGradientMatrix);
}
mGradientShadow.setShader(mShadowLinearGradient);
mGradientShadow.setAlpha(alpha);
}
@Override
protected void dispatchDraw(Canvas canvas) {
/** If prepareFold has not been called or if preparation has not completed yet,
* then no custom drawing will take place so only need to invoke super's
* onDraw and return. */
if (!mIsFoldPrepared || mFoldFactor == 0) {
super.dispatchDraw(canvas);
return;
}
if (!mShouldDraw) {
return;
}
Rect src;
/* Draws the bitmaps and shadows on the canvas with the appropriate transformations. */
for (int x = 0; x < mNumberOfFolds; x++) {
src = mFoldRectArray[x];
/* The canvas is saved and restored for every individual fold*/
canvas.save();
/* Concatenates the canvas with the transformation matrix for the
* the segment of the view corresponding to the actual image being
* displayed. */
canvas.concat(mMatrix[x]);
if (FoldingLayoutActivity.IS_JBMR2) {
mDstRect.set(0, 0, src.width(), src.height());
canvas.drawBitmap(mFullBitmap, src, mDstRect, null);
} else {
/* The same transformation matrix is used for both the shadow and the image
* segment. The canvas is clipped to account for the size of each fold and
* is translated so they are drawn in the right place. The shadow is then drawn on
* top of the different folds using the sametransformation matrix.*/
canvas.clipRect(0, 0, src.right - src.left, src.bottom - src.top);
if (mIsHorizontal) {
canvas.translate(-src.left, 0);
} else {
canvas.translate(0, -src.top);
}
super.dispatchDraw(canvas);
if (mIsHorizontal) {
canvas.translate(src.left, 0);
} else {
canvas.translate(0, src.top);
}
}
/* Draws the shadows corresponding to this specific fold. */
if (x % 2 == 0) {
canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mSolidShadow);
} else {
canvas.drawRect(0, 0, mFoldDrawWidth, mFoldDrawHeight, mGradientShadow);
}
canvas.restore();
}
}
}

View file

@ -0,0 +1,429 @@
/*
* 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.foldinglayout;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Build;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.TextureView;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Spinner;
import com.example.android.foldinglayout.FoldingLayout.Orientation;
import java.io.IOException;
/**
* This application creates a paper like folding effect of some view.
* The number of folds, orientation (vertical or horizontal) of the fold, and the
* anchor point about which the view will fold can be set to achieve different
* folding effects.
*
* Using bitmap and canvas scaling techniques, the foldingLayout can be scaled so as
* to depict a paper-like folding effect. The addition of shadows on the separate folds
* adds a sense of realism to the visual effect.
*
* This application shows folding of a TextureView containing a live camera feed,
* as well as the folding of an ImageView with a static image. The TextureView experiences
* jagged edges as a result of scaling operations on rectangles. The ImageView however
* contains a 1 pixel transparent border around its contents which can be used to avoid
* this unwanted artifact.
*/
public class FoldingLayoutActivity extends Activity {
private final int ANTIALIAS_PADDING = 1;
private final int FOLD_ANIMATION_DURATION = 1000;
/* A bug was introduced in Android 4.3 that ignores changes to the Canvas state
* between multiple calls to super.dispatchDraw() when running with hardware acceleration.
* To account for this bug, a slightly different approach was taken to fold a
* static image whereby a bitmap of the original contents is captured and drawn
* in segments onto the canvas. However, this method does not permit the folding
* of a TextureView hosting a live camera feed which continuously updates.
* Furthermore, the sepia effect was removed from the bitmap variation of the
* demo to simplify the logic when running with this workaround."
*/
static final boolean IS_JBMR2 = Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN_MR2;
private FoldingLayout mFoldLayout;
private SeekBar mAnchorSeekBar;
private Orientation mOrientation = Orientation.HORIZONTAL;
private int mTranslation = 0;
private int mNumberOfFolds = 2;
private int mParentPositionY = -1;
private int mTouchSlop = -1;
private float mAnchorFactor = 0;
private boolean mDidLoadSpinner = true;
private boolean mDidNotStartScroll = true;
private boolean mIsCameraFeed = false;
private boolean mIsSepiaOn = true;
private GestureDetector mScrollGestureDetector;
private ItemSelectedListener mItemSelectedListener;
private Camera mCamera;
private TextureView mTextureView;
private ImageView mImageView;
private Paint mSepiaPaint;
private Paint mDefaultPaint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fold);
mImageView = (ImageView)findViewById(R.id.image_view);
mImageView.setPadding(ANTIALIAS_PADDING, ANTIALIAS_PADDING, ANTIALIAS_PADDING,
ANTIALIAS_PADDING);
mImageView.setScaleType(ImageView.ScaleType.FIT_XY);
mImageView.setImageDrawable(getResources().getDrawable(R.drawable.image));
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
mAnchorSeekBar = (SeekBar)findViewById(R.id.anchor_seek_bar);
mFoldLayout = (FoldingLayout)findViewById(R.id.fold_view);
mFoldLayout.setBackgroundColor(Color.BLACK);
mFoldLayout.setFoldListener(mOnFoldListener);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
mAnchorSeekBar.setOnSeekBarChangeListener(mSeekBarChangeListener);
mScrollGestureDetector = new GestureDetector(this, new ScrollGestureDetector());
mItemSelectedListener = new ItemSelectedListener();
mDefaultPaint = new Paint();
mSepiaPaint = new Paint();
ColorMatrix m1 = new ColorMatrix();
ColorMatrix m2 = new ColorMatrix();
m1.setSaturation(0);
m2.setScale(1f, .95f, .82f, 1.0f);
m1.setConcat(m2, m1);
mSepiaPaint.setColorFilter(new ColorMatrixColorFilter(m1));
}
/**
* This listener, along with the setSepiaLayer method below, show a possible use case
* of the OnFoldListener provided with the FoldingLayout. This is a fun extra addition
* to the demo showing what kind of visual effects can be applied to the child of the
* FoldingLayout by setting the layer type to hardware. With a hardware layer type
* applied to the child, a paint object can also be applied to the same layer. Using
* the concatenation of two different color matrices (above), a color filter was created
* which simulates a sepia effect on the layer.*/
private OnFoldListener mOnFoldListener =
new OnFoldListener() {
@Override
public void onStartFold() {
if (mIsSepiaOn) {
setSepiaLayer(mFoldLayout.getChildAt(0), true);
}
}
@Override
public void onEndFold() {
setSepiaLayer(mFoldLayout.getChildAt(0), false);
}
};
private void setSepiaLayer (View view, boolean isSepiaLayerOn) {
if (!IS_JBMR2) {
if (isSepiaLayerOn) {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
view.setLayerPaint(mSepiaPaint);
} else {
view.setLayerPaint(mDefaultPaint);
}
}
}
/**
* Creates a SurfaceTextureListener in order to prepare a TextureView
* which displays a live, and continuously updated, feed from the Camera.
*/
private TextureView.SurfaceTextureListener mSurfaceTextureListener = new TextureView
.SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
mCamera = Camera.open();
if (mCamera == null && Camera.getNumberOfCameras() > 1) {
mCamera = mCamera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
}
if (mCamera == null) {
return;
}
try {
mCamera.setPreviewTexture(surfaceTexture);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
// Ignored, Camera does all the work for us
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
}
return true;
}
@Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
// Invoked every time there's a new Camera preview frame
}
};
/**
* A listener for scrolling changes in the seekbar. The anchor point of the folding
* view is updated every time the seekbar stops tracking touch events. Every time the
* anchor point is updated, the folding view is restored to a default unfolded state.
*/
private SeekBar.OnSeekBarChangeListener mSeekBarChangeListener = new SeekBar
.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mTranslation = 0;
mAnchorFactor = ((float)mAnchorSeekBar.getProgress())/100.0f;
mFoldLayout.setAnchorFactor(mAnchorFactor);
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (IS_JBMR2) {
getMenuInflater().inflate(R.menu.fold_with_bug, menu);
} else {
getMenuInflater().inflate(R.menu.fold, menu);
}
Spinner s = (Spinner) menu.findItem(R.id.num_of_folds).getActionView();
s.setOnItemSelectedListener(mItemSelectedListener);
return true;
}
@Override
public void onWindowFocusChanged (boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
int[] loc = new int[2];
mFoldLayout.getLocationOnScreen(loc);
mParentPositionY = loc[1];
}
@Override
public boolean onTouchEvent(MotionEvent me) {
return mScrollGestureDetector.onTouchEvent(me);
}
@Override
public boolean onOptionsItemSelected (MenuItem item) {
switch(item.getItemId()) {
case R.id.animate_fold:
animateFold();
break;
case R.id.toggle_orientation:
mOrientation = (mOrientation == Orientation.HORIZONTAL) ? Orientation.VERTICAL :
Orientation.HORIZONTAL;
item.setTitle((mOrientation == Orientation.HORIZONTAL) ? R.string.vertical :
R.string.horizontal);
mTranslation = 0;
mFoldLayout.setOrientation(mOrientation);
break;
case R.id.camera_feed:
mIsCameraFeed = !mIsCameraFeed;
item.setTitle(mIsCameraFeed ? R.string.static_image : R.string.camera_feed);
item.setChecked(mIsCameraFeed);
if (mIsCameraFeed) {
mFoldLayout.removeView(mImageView);
mFoldLayout.addView(mTextureView, new ViewGroup.LayoutParams(
mFoldLayout.getWidth(), mFoldLayout.getHeight()));
} else {
mFoldLayout.removeView(mTextureView);
mFoldLayout.addView(mImageView, new ViewGroup.LayoutParams(
mFoldLayout.getWidth(), mFoldLayout.getHeight()));
}
mTranslation = 0;
break;
case R.id.sepia:
mIsSepiaOn = !mIsSepiaOn;
item.setChecked(!mIsSepiaOn);
if (mIsSepiaOn && mFoldLayout.getFoldFactor() != 0) {
setSepiaLayer(mFoldLayout.getChildAt(0), true);
} else {
setSepiaLayer(mFoldLayout.getChildAt(0), false);
}
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
/**
* Animates the folding view inwards (to a completely folded state) from its
* current state and then back out to its original state.
*/
public void animateFold ()
{
float foldFactor = mFoldLayout.getFoldFactor();
ObjectAnimator animator = ObjectAnimator.ofFloat(mFoldLayout, "foldFactor", foldFactor, 1);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setRepeatCount(1);
animator.setDuration(FOLD_ANIMATION_DURATION);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();
}
/**
* Listens for selection events of the spinner located on the action bar. Every
* time a new value is selected, the number of folds in the folding view is updated
* and is also restored to a default unfolded state.
*/
private class ItemSelectedListener implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
mNumberOfFolds = Integer.parseInt(parent.getItemAtPosition(pos).toString());
if (mDidLoadSpinner) {
mDidLoadSpinner = false;
} else {
mTranslation = 0;
mFoldLayout.setNumberOfFolds(mNumberOfFolds);
}
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
/** This class uses user touch events to fold and unfold the folding view. */
private class ScrollGestureDetector extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDown (MotionEvent e) {
mDidNotStartScroll = true;
return true;
}
/**
* All the logic here is used to determine by what factor the paper view should
* be folded in response to the user's touch events. The logic here uses vertical
* scrolling to fold a vertically oriented view and horizontal scrolling to fold
* a horizontally oriented fold. Depending on where the anchor point of the fold is,
* movements towards or away from the anchor point will either fold or unfold
* the paper respectively.
*
* The translation logic here also accounts for the touch slop when a new user touch
* begins, but before a scroll event is first invoked.
*/
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
int touchSlop = 0;
float factor;
if (mOrientation == Orientation.VERTICAL) {
factor = Math.abs((float)(mTranslation) / (float)(mFoldLayout.getHeight()));
if (e2.getY() - mParentPositionY <= mFoldLayout.getHeight()
&& e2.getY() - mParentPositionY >= 0) {
if ((e2.getY() - mParentPositionY) > mFoldLayout.getHeight() * mAnchorFactor) {
mTranslation -= (int)distanceY;
touchSlop = distanceY < 0 ? -mTouchSlop : mTouchSlop;
} else {
mTranslation += (int)distanceY;
touchSlop = distanceY < 0 ? mTouchSlop : -mTouchSlop;
}
mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
if (mTranslation < -mFoldLayout.getHeight()) {
mTranslation = -mFoldLayout.getHeight();
}
}
} else {
factor = Math.abs(((float)mTranslation) / ((float) mFoldLayout.getWidth()));
if (e2.getRawX() > mFoldLayout.getWidth() * mAnchorFactor) {
mTranslation -= (int)distanceX;
touchSlop = distanceX < 0 ? -mTouchSlop : mTouchSlop;
} else {
mTranslation += (int)distanceX;
touchSlop = distanceX < 0 ? mTouchSlop : -mTouchSlop;
}
mTranslation = mDidNotStartScroll ? mTranslation + touchSlop : mTranslation;
if (mTranslation < -mFoldLayout.getWidth()) {
mTranslation = -mFoldLayout.getWidth();
}
}
mDidNotStartScroll = false;
if (mTranslation > 0) {
mTranslation = 0;
}
mFoldLayout.setFoldFactor(factor);
return true;
}
}
}

View file

@ -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.foldinglayout;
/**
* This interface listens for when the folding layout begins folding (enters
* a folded state from a completely unfolded state), or ends folding (enters a
* completely unfolded state from a folded state).
*/
public interface OnFoldListener {
public void onStartFold();
public void onEndFold();
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.imagepixelization"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="11"
android:targetSdkVersion="17"/>
<application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
<activity android:name=".ImagePixelization"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,42 @@
<!-- 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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical">
<ImageView
android:id="@+id/pixelView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_above="@+id/seekbar"
android:scaleType="fitXY"/>
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:max="@integer/seek_max"
android:progress="0"
android:layout_alignParentBottom = "true"/>
</RelativeLayout>

View file

@ -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.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/builtin_pixelation_checkbox"
android:showAsAction="never"
android:title="@string/builtin_pixelization"
android:checkable="true" />
<item android:id="@+id/checkbox"
android:showAsAction="never"
android:title="@string/async_task"
android:checkable="true" />
<item android:id="@+id/animate"
android:showAsAction="never"
android:title="@string/animate_pixelation"/>
</menu>

View file

@ -0,0 +1,20 @@
<!-- 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>
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View file

@ -0,0 +1,19 @@
<!-- 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>
<integer name="seek_max">1000</integer>
</resources>

View file

@ -0,0 +1,22 @@
<!-- 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" >ImagePixelization</string>
<string name="animate_pixelation">Animate</string>
<string name="async_task">Using AyncTask</string>
<string name="builtin_pixelization">Built-in Pixelization</string>
</resources>

View file

@ -0,0 +1,315 @@
/*
* 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.imagepixelization;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.SeekBar;
import java.util.Arrays;
/**
* This application shows three different graphics/animation concepts.
*
* A pixelization effect is applied to an image with varying pixelization
* factors to achieve an image that is pixelized to varying degrees. In
* order to optimize the amount of image processing performed on the image
* being pixelized, the pixelization effect only takes place if a predefined
* amount of time has elapsed since the main image was last pixelized. The
* effect is also applied when the user stops moving the seekbar.
*
* This application also shows how to use a ValueAnimator to achieve a
* smooth self-animating seekbar.
*
* Lastly, this application shows a use case of AsyncTask where some
* computation heavy processing can be moved onto a background thread,
* so as to keep the UI completely responsive to user input.
*/
public class ImagePixelization extends Activity {
final private static int SEEKBAR_ANIMATION_DURATION = 10000;
final private static int TIME_BETWEEN_TASKS = 400;
final private static int SEEKBAR_STOP_CHANGE_DELTA = 5;
final private static float PROGRESS_TO_PIXELIZATION_FACTOR = 4000.0f;
Bitmap mImageBitmap;
ImageView mImageView;
SeekBar mSeekBar;
boolean mIsChecked = false;
boolean mIsBuiltinPixelizationChecked = false;
int mLastProgress = 0;
long mLastTime = 0;
Bitmap mPixelatedBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_image_pixelization);
mImageView = (ImageView) findViewById(R.id.pixelView);
mSeekBar = (SeekBar)findViewById(R.id.seekbar);
mImageBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image);
mImageView.setImageBitmap(mImageBitmap);
mSeekBar.setOnSeekBarChangeListener(mOnSeekBarChangeListener);
}
private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener =
new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (Math.abs(mSeekBar.getProgress() - mLastProgress) > SEEKBAR_STOP_CHANGE_DELTA) {
invokePixelization();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
checkIfShouldPixelize();
}
};
/**
* Checks if enough time has elapsed since the last pixelization call was invoked.
* This prevents too many pixelization processes from being invoked at the same time
* while previous ones have not yet completed.
*/
public void checkIfShouldPixelize() {
if ((System.currentTimeMillis() - mLastTime) > TIME_BETWEEN_TASKS) {
invokePixelization();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.image_pixelization, menu);
return true;
}
@Override
public boolean onOptionsItemSelected (MenuItem item) {
switch (item.getItemId()){
case R.id.animate:
ObjectAnimator animator = ObjectAnimator.ofInt(mSeekBar, "progress", 0,
mSeekBar.getMax());
animator.setInterpolator(new LinearInterpolator());
animator.setDuration(SEEKBAR_ANIMATION_DURATION);
animator.start();
break;
case R.id.checkbox:
if (mIsChecked) {
item.setChecked(false);
mIsChecked = false;
} else {
item.setChecked(true);
mIsChecked = true;
}
break;
case R.id.builtin_pixelation_checkbox:
mIsBuiltinPixelizationChecked = !mIsBuiltinPixelizationChecked;
item.setChecked(mIsBuiltinPixelizationChecked);
break;
default:
break;
}
return true;
}
/**
* A simple pixelization algorithm. This uses a box blur algorithm where all the
* pixels within some region are averaged, and that average pixel value is then
* applied to all the pixels within that region. A higher pixelization factor
* imposes a smaller number of regions of greater size. Similarly, a smaller
* pixelization factor imposes a larger number of regions of smaller size.
*/
public BitmapDrawable customImagePixelization(float pixelizationFactor, Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
if (mPixelatedBitmap == null || !(width == mPixelatedBitmap.getWidth() && height ==
mPixelatedBitmap.getHeight())) {
mPixelatedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
}
int xPixels = (int) (pixelizationFactor * ((float)width));
xPixels = xPixels > 0 ? xPixels : 1;
int yPixels = (int) (pixelizationFactor * ((float)height));
yPixels = yPixels > 0 ? yPixels : 1;
int pixel = 0, red = 0, green = 0, blue = 0, numPixels = 0;
int[] bitmapPixels = new int[width * height];
bitmap.getPixels(bitmapPixels, 0, width, 0, 0, width, height);
int[] pixels = new int[yPixels * xPixels];
int maxX, maxY;
for (int y = 0; y < height; y+=yPixels) {
for (int x = 0; x < width; x+=xPixels) {
numPixels = red = green = blue = 0;
maxX = Math.min(x + xPixels, width);
maxY = Math.min(y + yPixels, height);
for (int i = x; i < maxX; i++) {
for (int j = y; j < maxY; j++) {
pixel = bitmapPixels[j * width + i];
red += Color.red(pixel);
green += Color.green(pixel);
blue += Color.blue(pixel);
numPixels ++;
}
}
pixel = Color.rgb(red / numPixels, green / numPixels, blue / numPixels);
Arrays.fill(pixels, pixel);
int w = Math.min(xPixels, width - x);
int h = Math.min(yPixels, height - y);
mPixelatedBitmap.setPixels(pixels, 0 , w, x , y, w, h);
}
}
return new BitmapDrawable(getResources(), mPixelatedBitmap);
}
/**
* This method of image pixelization utilizes the bitmap scaling operations built
* into the framework. By downscaling the bitmap and upscaling it back to its
* original size (while setting the filter flag to false), the same effect can be
* achieved with much better performance.
*/
public BitmapDrawable builtInPixelization(float pixelizationFactor, Bitmap bitmap) {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
int downScaleFactorWidth = (int)(pixelizationFactor * width);
downScaleFactorWidth = downScaleFactorWidth > 0 ? downScaleFactorWidth : 1;
int downScaleFactorHeight = (int)(pixelizationFactor * height);
downScaleFactorHeight = downScaleFactorHeight > 0 ? downScaleFactorHeight : 1;
int downScaledWidth = width / downScaleFactorWidth;
int downScaledHeight = height / downScaleFactorHeight;
Bitmap pixelatedBitmap = Bitmap.createScaledBitmap(bitmap, downScaledWidth,
downScaledHeight, false);
/* Bitmap's createScaledBitmap method has a filter parameter that can be set to either
* true or false in order to specify either bilinear filtering or point sampling
* respectively when the bitmap is scaled up or now.
*
* Similarly, a BitmapDrawable also has a flag to specify the same thing. When the
* BitmapDrawable is applied to an ImageView that has some scaleType, the filtering
* flag is taken into consideration. However, for optimization purposes, this flag was
* ignored in BitmapDrawables before Jelly Bean MR1.
*
* Here, it is important to note that prior to JBMR1, two bitmap scaling operations
* are required to achieve the pixelization effect. Otherwise, a BitmapDrawable
* can be created corresponding to the downscaled bitmap such that when it is
* upscaled to fit the ImageView, the upscaling operation is a lot faster since
* it uses internal optimizations to fit the ImageView.
* */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), pixelatedBitmap);
bitmapDrawable.setFilterBitmap(false);
return bitmapDrawable;
} else {
Bitmap upscaled = Bitmap.createScaledBitmap(pixelatedBitmap, width, height, false);
return new BitmapDrawable(getResources(), upscaled);
}
}
/**
* Invokes pixelization either on the main thread or on a background thread
* depending on whether or not the checkbox was checked.
*/
public void invokePixelization () {
mLastTime = System.currentTimeMillis();
mLastProgress = mSeekBar.getProgress();
if (mIsChecked) {
PixelizeImageAsyncTask asyncPixelateTask = new PixelizeImageAsyncTask();
asyncPixelateTask.execute(mSeekBar.getProgress() / PROGRESS_TO_PIXELIZATION_FACTOR,
mImageBitmap);
} else {
mImageView.setImageDrawable(pixelizeImage(mSeekBar.getProgress()
/ PROGRESS_TO_PIXELIZATION_FACTOR, mImageBitmap));
}
}
/**
* Selects either the custom pixelization algorithm that sets and gets bitmap
* pixels manually or the one that uses built-in bitmap operations.
*/
public BitmapDrawable pixelizeImage(float pixelizationFactor, Bitmap bitmap) {
if (mIsBuiltinPixelizationChecked) {
return builtInPixelization(pixelizationFactor, bitmap);
} else {
return customImagePixelization(pixelizationFactor, bitmap);
}
}
/**
* Implementation of the AsyncTask class showing how to run the
* pixelization algorithm in the background, and retrieving the
* pixelated image from the resulting operation.
*/
private class PixelizeImageAsyncTask extends AsyncTask<Object, Void, BitmapDrawable> {
@Override
protected BitmapDrawable doInBackground(Object... params) {
float pixelizationFactor = (Float)params[0];
Bitmap originalBitmap = (Bitmap)params[1];
return pixelizeImage(pixelizationFactor, originalBitmap);
}
@Override
protected void onPostExecute(BitmapDrawable result) {
mImageView.setImageDrawable(result);
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
}