upload android base code part7
|
@ -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>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 562 KiB |
After Width: | Height: | Size: 1.1 MiB |
After Width: | Height: | Size: 918 KiB |
After Width: | Height: | Size: 520 KiB |
After Width: | Height: | Size: 482 KiB |
After Width: | Height: | Size: 337 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 240 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -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>
|
|
@ -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" />
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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>
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 265 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -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>
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|