OSDN Git Service

Added Honeycomb Gallery sample application.
authorAlexander Lucas <alexlucas@google.com>
Wed, 12 Jan 2011 01:24:40 +0000 (17:24 -0800)
committerAlexander Lucas <alexlucas@google.com>
Thu, 20 Jan 2011 01:02:48 +0000 (17:02 -0800)
Change-Id: I1eefc2837016a7973544f0c57a8464466e7dcef9

54 files changed:
build/sdk.atree
samples/Honeycomb-Gallery/Android.mk [new file with mode: 0644]
samples/Honeycomb-Gallery/AndroidManifest.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/_index.html [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-hdpi/android_logo.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_camera.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_toggle.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-hdpi/icon.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-hdpi/logo.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-ldpi/icon.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_camera.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_toggle.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-mdpi/icon.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-mdpi/logo.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/big_droid.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/blue_balloon.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/blue_bike.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/chrome_wheel.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/cupcake.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/donut.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/eclair.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/froyo.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/green_balloon.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/punk_droid.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/rainbow_bike.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/red_balloon.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/stargazer_droid.JPG [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable-nodpi/widget_preview.png [new file with mode: 0644]
samples/Honeycomb-Gallery/res/drawable/widget_item_background.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout-port/main.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/action_bar_custom.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/camera_sample.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/content_welcome.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/main.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/title_list_item.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/widget_item.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/layout/widget_layout.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/menu/camera_menu.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/menu/main_menu.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/values-port/dimens.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/values/dimens.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/values/strings.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/res/xml/widget_info.xml [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/CameraFragment.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/CameraSample.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/ContentFragment.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/Directory.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/DirectoryCategory.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/DirectoryEntry.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/MainActivity.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/TitlesFragment.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetItem.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetProvider.java [new file with mode: 0644]
samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetService.java [new file with mode: 0644]

index af93765..6459d02 100644 (file)
@@ -160,6 +160,7 @@ development/samples/ContactManager           samples/${PLATFORM_NAME}/ContactMan
 development/samples/CrossCompatibility       samples/${PLATFORM_NAME}/CrossCompatibility
 development/samples/CubeLiveWallpaper        samples/${PLATFORM_NAME}/CubeLiveWallpaper
 development/samples/Home                     samples/${PLATFORM_NAME}/Home
+development/samples/Honeycomb-Gallery        samples/${PLATFORM_NAME}/Honeycomb-Gallery
 development/samples/JetBoy                   samples/${PLATFORM_NAME}/JetBoy
 development/samples/LunarLander              samples/${PLATFORM_NAME}/LunarLander
 development/samples/MultiResolution          samples/${PLATFORM_NAME}/MultiResolution
diff --git a/samples/Honeycomb-Gallery/Android.mk b/samples/Honeycomb-Gallery/Android.mk
new file mode 100644 (file)
index 0000000..01788af
--- /dev/null
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := samples
+
+# Only compile source java files in this apk.
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Honeycomb-Gallery
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
+# Use the following include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/samples/Honeycomb-Gallery/AndroidManifest.xml b/samples/Honeycomb-Gallery/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..4776020
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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.hcgallery" android:versionCode="1"
+    android:versionName="1.0">
+
+    <uses-sdk android:minSdkVersion="Honeycomb" />
+
+    <uses-permission android:name="android.permission.CAMERA" />
+
+    <application android:label="@string/app_name"
+        android:icon="@drawable/icon"
+        android:logo="@drawable/logo"
+        android:theme="@android:style/Theme.Holo.Light"
+        android:hardwareAccelerated="true"
+        android:debuggable="true">
+
+        <activity android:name=".MainActivity" android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <!-- CameraSample -->
+        <activity android:name=".CameraSample"
+            android:label="@string/camera_sample"
+            android:screenOrientation="landscape" />
+
+        <!-- StackView widget sample code -->
+        <receiver android:name=".widget.WidgetProvider"
+            android:label="@string/app_widget_name">
+            <intent-filter>
+                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+            </intent-filter>
+            <meta-data android:name="android.appwidget.provider"
+                android:resource="@xml/widget_info" />
+        </receiver>
+        <service android:name=".widget.WidgetService"
+            android:exported="true"
+            android:permission="android.permission.BIND_REMOTEVIEWS" />
+
+      </application>
+</manifest>
diff --git a/samples/Honeycomb-Gallery/_index.html b/samples/Honeycomb-Gallery/_index.html
new file mode 100644 (file)
index 0000000..5160527
--- /dev/null
@@ -0,0 +1,37 @@
+<p>This is a demo application highlighting how to use some of the new APIs in
+Honeycomb, including Fragments, the Action Bar, drag'n drop, transition
+animations, and a stack widget.  The image gallery shows how all these pieces
+can work together in one application.</p>
+
+<p>The application includes the following classes:<p>
+<ul>
+  <li><a href="src/com/example/android/hcgallery/ContentFragment.html">ContentFragment</a>
+    A fragment responsible for containing the "content" of the application.
+    Displays images, receives drag/drop events from other fragments.</li>
+  <li><a href="src/com/example/android/hcgallery/TitlesFragment.html">TitlesFragment</a>
+      Shows a ListView of photos to display in the ContentFragment. Photos can
+      be chosen either by tapping on the listview, or dragging them from the
+      list to the content area. The list of photos displayed depends on the
+      category selected in the ActionBar.</li>
+  <li><a href="src/com/example/android/hcgallery/MainActivity.html">MainActivity</a>
+      This is the main entry point of the application. MainActivity is
+      responsible for initialization of the ActionBar, TitlesFragment, and
+      ContentFragment. MainActivity is also responsible for keeping track of
+      the currently selected theme and currently selected photo when the
+      activity is recreated, such as when the screen is rotated or an intent to
+      a seperate activity is fired (such as the included Camera sample).
+      MainActivity also contains code demonstrating how to animate
+      showing/hiding fragments (in this case, the TitlesFragment) and the
+      ActionBar, demonstrating how to smoothly transition between states
+      in your application.</li>
+  <li><a href="src/com/example/android/hcgallery/widget/WidgetProvider.html">WidgetProvider</a>
+      The WidgetProvider class is an implementation of the AppWidgetProvider
+      class, which is a view that can be embedded in other applications.
+      This class is responsible for handling when the instance of this widget
+      is enabled, disabled, created, deleted, or updated.</li>
+  <li><a href="src/com/example/android/hcgallery/widget/WidgetService.html">WidgetService</a>
+      The WidgetService is an implementation of the RemoteViewsService class,
+      which is used to populate the collection view (in this case, a stack
+      widget)</li> </ul>
+
+<img alt="Screenshot" src="../images/hcgallery.png" />
diff --git a/samples/Honeycomb-Gallery/res/drawable-hdpi/android_logo.png b/samples/Honeycomb-Gallery/res/drawable-hdpi/android_logo.png
new file mode 100644 (file)
index 0000000..f8be345
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-hdpi/android_logo.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_camera.png b/samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_camera.png
new file mode 100644 (file)
index 0000000..d03cbf9
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_camera.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_toggle.png b/samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_toggle.png
new file mode 100644 (file)
index 0000000..a4b50d9
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-hdpi/ic_menu_toggle.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-hdpi/icon.png b/samples/Honeycomb-Gallery/res/drawable-hdpi/icon.png
new file mode 100644 (file)
index 0000000..404a2a4
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-hdpi/icon.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-hdpi/logo.png b/samples/Honeycomb-Gallery/res/drawable-hdpi/logo.png
new file mode 100644 (file)
index 0000000..5af2f75
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-hdpi/logo.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-ldpi/icon.png b/samples/Honeycomb-Gallery/res/drawable-ldpi/icon.png
new file mode 100644 (file)
index 0000000..add2163
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-ldpi/icon.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_camera.png b/samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_camera.png
new file mode 100644 (file)
index 0000000..a8f2f41
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_camera.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_toggle.png b/samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_toggle.png
new file mode 100644 (file)
index 0000000..9a77dc7
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-mdpi/ic_menu_toggle.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-mdpi/icon.png b/samples/Honeycomb-Gallery/res/drawable-mdpi/icon.png
new file mode 100644 (file)
index 0000000..0e62f31
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-mdpi/icon.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-mdpi/logo.png b/samples/Honeycomb-Gallery/res/drawable-mdpi/logo.png
new file mode 100644 (file)
index 0000000..43642eb
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-mdpi/logo.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/big_droid.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/big_droid.JPG
new file mode 100644 (file)
index 0000000..2bb450c
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/big_droid.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/blue_balloon.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/blue_balloon.JPG
new file mode 100644 (file)
index 0000000..f116574
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/blue_balloon.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/blue_bike.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/blue_bike.JPG
new file mode 100644 (file)
index 0000000..f424815
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/blue_bike.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/chrome_wheel.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/chrome_wheel.JPG
new file mode 100644 (file)
index 0000000..a748593
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/chrome_wheel.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/cupcake.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/cupcake.JPG
new file mode 100644 (file)
index 0000000..ba902c6
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/cupcake.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/donut.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/donut.JPG
new file mode 100644 (file)
index 0000000..5f5ee46
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/donut.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/eclair.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/eclair.JPG
new file mode 100644 (file)
index 0000000..656e6cb
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/eclair.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/froyo.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/froyo.JPG
new file mode 100644 (file)
index 0000000..f6c5f06
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/froyo.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/green_balloon.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/green_balloon.JPG
new file mode 100644 (file)
index 0000000..171e3a3
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/green_balloon.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/punk_droid.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/punk_droid.JPG
new file mode 100644 (file)
index 0000000..090779b
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/punk_droid.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/rainbow_bike.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/rainbow_bike.JPG
new file mode 100644 (file)
index 0000000..87be337
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/rainbow_bike.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/red_balloon.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/red_balloon.JPG
new file mode 100644 (file)
index 0000000..3e5e95c
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/red_balloon.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/stargazer_droid.JPG b/samples/Honeycomb-Gallery/res/drawable-nodpi/stargazer_droid.JPG
new file mode 100644 (file)
index 0000000..e336b32
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/stargazer_droid.JPG differ
diff --git a/samples/Honeycomb-Gallery/res/drawable-nodpi/widget_preview.png b/samples/Honeycomb-Gallery/res/drawable-nodpi/widget_preview.png
new file mode 100644 (file)
index 0000000..b2a1342
Binary files /dev/null and b/samples/Honeycomb-Gallery/res/drawable-nodpi/widget_preview.png differ
diff --git a/samples/Honeycomb-Gallery/res/drawable/widget_item_background.xml b/samples/Honeycomb-Gallery/res/drawable/widget_item_background.xml
new file mode 100644 (file)
index 0000000..aad4da3
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+    <gradient android:startColor="#ff666666" android:endColor="#ff333333" android:angle="270" />
+</shape>
diff --git a/samples/Honeycomb-Gallery/res/layout-port/main.xml b/samples/Honeycomb-Gallery/res/layout-port/main.xml
new file mode 100644 (file)
index 0000000..ea63a67
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/frags">
+
+    <fragment class="com.example.android.hcgallery.TitlesFragment"
+            android:id="@+id/frag_title"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/titles_size"/>
+
+    <fragment class="com.example.android.hcgallery.ContentFragment"
+            android:id="@+id/frag_content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/samples/Honeycomb-Gallery/res/layout/action_bar_custom.xml b/samples/Honeycomb-Gallery/res/layout/action_bar_custom.xml
new file mode 100644 (file)
index 0000000..5f111d9
--- /dev/null
@@ -0,0 +1,24 @@
+<!--
+  Copyright (C) 2011 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"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <TextView
+      android:layout_width="match_parent"
+      android:layout_height="match_parent">Hello Action Bar</TextView>
+</LinearLayout>
diff --git a/samples/Honeycomb-Gallery/res/layout/camera_sample.xml b/samples/Honeycomb-Gallery/res/layout/camera_sample.xml
new file mode 100644 (file)
index 0000000..dcb8867
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ -->
+
+
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <fragment android:name="com.example.android.hcgallery.CameraFragment"
+        android:id="@+id/camera_frag"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+</FrameLayout>
diff --git a/samples/Honeycomb-Gallery/res/layout/content_welcome.xml b/samples/Honeycomb-Gallery/res/layout/content_welcome.xml
new file mode 100644 (file)
index 0000000..0b92508
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="12dp">
+    <ImageView android:id="@+id/image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scaleType="fitCenter"
+        android:layout_gravity="center" />
+</FrameLayout>
diff --git a/samples/Honeycomb-Gallery/res/layout/main.xml b/samples/Honeycomb-Gallery/res/layout/main.xml
new file mode 100644 (file)
index 0000000..f96382d
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:id="@+id/frags">
+
+    <fragment class="com.example.android.hcgallery.TitlesFragment"
+            android:id="@+id/frag_title"
+            android:visibility="gone"
+            android:layout_width="@dimen/titles_size"
+            android:layout_height="match_parent" />
+
+    <fragment class="com.example.android.hcgallery.ContentFragment"
+            android:id="@+id/frag_content"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/samples/Honeycomb-Gallery/res/layout/title_list_item.xml b/samples/Honeycomb-Gallery/res/layout/title_list_item.xml
new file mode 100644 (file)
index 0000000..cead709
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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.
+ -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:padding="10dp"
+    android:gravity="bottom"
+    android:textAppearance="?android:attr/textAppearanceMedium"
+    android:background="?android:attr/activatedBackgroundIndicator" >
+</TextView>
diff --git a/samples/Honeycomb-Gallery/res/layout/widget_item.xml b/samples/Honeycomb-Gallery/res/layout/widget_item.xml
new file mode 100644 (file)
index 0000000..a1cbe1f
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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.
+ -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/widget_item"
+    android:layout_width="120dp"
+    android:layout_height="120dp"
+    android:gravity="center"
+    android:background="@drawable/widget_item_background"
+    android:textColor="#ffffff"
+    android:textStyle="bold"
+    android:textSize="44sp" />
diff --git a/samples/Honeycomb-Gallery/res/layout/widget_layout.xml b/samples/Honeycomb-Gallery/res/layout/widget_layout.xml
new file mode 100644 (file)
index 0000000..9874650
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <StackView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/stack_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:loopViews="true" />
+    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/empty_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:background="@drawable/widget_item_background"
+        android:textColor="#ffffff"
+        android:textStyle="bold"
+        android:text="@string/widget_empty_view_text"
+        android:textSize="20sp" />
+</FrameLayout>
diff --git a/samples/Honeycomb-Gallery/res/menu/camera_menu.xml b/samples/Honeycomb-Gallery/res/menu/camera_menu.xml
new file mode 100644 (file)
index 0000000..55184dd
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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/switch_cam" android:title="Switch Camera" />
+</menu>
diff --git a/samples/Honeycomb-Gallery/res/menu/main_menu.xml b/samples/Honeycomb-Gallery/res/menu/main_menu.xml
new file mode 100644 (file)
index 0000000..2a42679
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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/camera"
+        android:title="Camera"
+        android:icon="@drawable/ic_menu_camera"
+        android:showAsAction="ifRoom" />
+    <item android:id="@+id/toggleTitles"
+        android:icon="@drawable/ic_menu_toggle"
+        android:title="Toggle Titles"
+        android:showAsAction="ifRoom|withText" />
+    <item android:id="@+id/toggleTheme"
+        android:title="Day/Night"
+        android:showAsAction="ifRoom|withText" />
+</menu>
diff --git a/samples/Honeycomb-Gallery/res/values-port/dimens.xml b/samples/Honeycomb-Gallery/res/values-port/dimens.xml
new file mode 100644 (file)
index 0000000..fc41ac9
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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="titles_size">200dp</dimen>
+</resources>
diff --git a/samples/Honeycomb-Gallery/res/values/dimens.xml b/samples/Honeycomb-Gallery/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..1f49654
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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="titles_size">300dp</dimen>
+</resources>
diff --git a/samples/Honeycomb-Gallery/res/values/strings.xml b/samples/Honeycomb-Gallery/res/values/strings.xml
new file mode 100644 (file)
index 0000000..a6c3b57
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2010 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">Honeycomb Example</string>
+    <string name="camera_sample">Camera Example</string>
+    <string name="clip_label">Clip Label</string>
+
+    <string name="app_widget_name">Honeycomb Example Widget</string>
+    <string name="widget_empty_view_text">Touch to show data</string>
+</resources>
diff --git a/samples/Honeycomb-Gallery/res/xml/widget_info.xml b/samples/Honeycomb-Gallery/res/xml/widget_info.xml
new file mode 100644 (file)
index 0000000..db95f9c
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2011 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.
+ -->
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+    android:minWidth="150dp"
+    android:minHeight="150dp"
+    android:updatePeriodMillis="3600000"
+    android:initialLayout="@layout/widget_layout"
+    android:previewImage="@drawable/widget_preview"
+    android:autoAdvanceViewId="@id/stack_view" />
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/CameraFragment.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/CameraFragment.java
new file mode 100644 (file)
index 0000000..6eef985
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+import java.io.IOException;
+import java.util.List;
+
+import android.app.Fragment;
+import android.app.Activity;
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
+import android.hardware.Camera.Size;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class CameraFragment extends Fragment {
+
+    private Preview mPreview;
+    Camera mCamera;
+    int mNumberOfCameras;
+    int cameraCurrentlyLocked;
+
+    // The first rear facing camera
+    int defaultCameraId;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Add an up arrow to the "home" button, indicating that the button will go "up"
+        // one activity in the app's Activity heirarchy.
+        Activity activity = this.getActivity();
+        ActionBar actionBar = activity.getActionBar();
+        actionBar.setDisplayHomeAsUpEnabled(true);
+
+        // Create a RelativeLayout container that will hold a SurfaceView,
+        // and set it as the content of our activity.
+        mPreview = new Preview(this.getActivity());
+
+        // Find the total number of cameras available
+        mNumberOfCameras = Camera.getNumberOfCameras();
+
+        // Find the ID of the default camera
+        CameraInfo cameraInfo = new CameraInfo();
+        for (int i = 0; i < mNumberOfCameras; i++) {
+            Camera.getCameraInfo(i, cameraInfo);
+            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
+                defaultCameraId = i;
+            }
+        }
+        setHasOptionsMenu(mNumberOfCameras > 1);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return mPreview;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        // Open the default i.e. the first rear facing camera.
+        mCamera = Camera.open(defaultCameraId);
+        cameraCurrentlyLocked = defaultCameraId;
+        mPreview.setCamera(mCamera);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        // Because the Camera object is a shared resource, it's very
+        // important to release it when the activity is paused.
+        if (mCamera != null) {
+            mPreview.setCamera(null);
+            mCamera.release();
+            mCamera = null;
+        }
+    }
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        if (mNumberOfCameras > 1) {
+            // Inflate our menu which can gather user input for switching camera
+            inflater.inflate(R.menu.camera_menu, menu);
+        } else {
+            super.onCreateOptionsMenu(menu, inflater);
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle item selection
+        switch (item.getItemId()) {
+        case R.id.switch_cam:
+            // Release this camera -> cameraCurrentlyLocked
+            if (mCamera != null) {
+                mCamera.stopPreview();
+                mPreview.setCamera(null);
+                mCamera.release();
+                mCamera = null;
+            }
+
+            // Acquire the next camera and request Preview to reconfigure
+            // parameters.
+            mCamera = Camera
+                    .open((cameraCurrentlyLocked + 1) % mNumberOfCameras);
+            cameraCurrentlyLocked = (cameraCurrentlyLocked + 1)
+                    % mNumberOfCameras;
+            mPreview.switchCamera(mCamera);
+
+            // Start the preview
+            mCamera.startPreview();
+            return true;
+        case android.R.id.home:
+            Intent intent = new Intent(this.getActivity(), MainActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
+            startActivity(intent);
+
+        default:
+            return super.onOptionsItemSelected(item);
+        }
+    }
+}
+
+// ----------------------------------------------------------------------
+
+/**
+ * A simple wrapper around a Camera and a SurfaceView that renders a centered
+ * preview of the Camera to the surface. We need to center the SurfaceView
+ * because not all devices have cameras that support preview sizes at the same
+ * aspect ratio as the device's display.
+ */
+class Preview extends ViewGroup implements SurfaceHolder.Callback {
+    private final String TAG = "Preview";
+
+    SurfaceView mSurfaceView;
+    SurfaceHolder mHolder;
+    Size mPreviewSize;
+    List<Size> mSupportedPreviewSizes;
+    Camera mCamera;
+
+    Preview(Context context) {
+        super(context);
+
+        mSurfaceView = new SurfaceView(context);
+        addView(mSurfaceView);
+
+        // Install a SurfaceHolder.Callback so we get notified when the
+        // underlying surface is created and destroyed.
+        mHolder = mSurfaceView.getHolder();
+        mHolder.addCallback(this);
+        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+    }
+
+    public void setCamera(Camera camera) {
+        mCamera = camera;
+        if (mCamera != null) {
+            mSupportedPreviewSizes = mCamera.getParameters()
+                    .getSupportedPreviewSizes();
+            requestLayout();
+        }
+    }
+
+    public void switchCamera(Camera camera) {
+        setCamera(camera);
+        try {
+            camera.setPreviewDisplay(mHolder);
+        } catch (IOException exception) {
+            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+        }
+        Camera.Parameters parameters = camera.getParameters();
+        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+        requestLayout();
+
+        camera.setParameters(parameters);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // We purposely disregard child measurements because act as a
+        // wrapper to a SurfaceView that centers the camera preview instead
+        // of stretching it.
+        final int width = resolveSize(getSuggestedMinimumWidth(),
+                widthMeasureSpec);
+        final int height = resolveSize(getSuggestedMinimumHeight(),
+                heightMeasureSpec);
+        setMeasuredDimension(width, height);
+
+        if (mSupportedPreviewSizes != null) {
+            mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width,
+                    height);
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        if (changed && getChildCount() > 0) {
+            final View child = getChildAt(0);
+
+            final int width = r - l;
+            final int height = b - t;
+
+            int previewWidth = width;
+            int previewHeight = height;
+            if (mPreviewSize != null) {
+                previewWidth = mPreviewSize.width;
+                previewHeight = mPreviewSize.height;
+            }
+
+            // Center the child SurfaceView within the parent.
+            if (width * previewHeight > height * previewWidth) {
+                final int scaledChildWidth = previewWidth * height
+                        / previewHeight;
+                child.layout((width - scaledChildWidth) / 2, 0,
+                        (width + scaledChildWidth) / 2, height);
+            } else {
+                final int scaledChildHeight = previewHeight * width
+                        / previewWidth;
+                child.layout(0, (height - scaledChildHeight) / 2, width,
+                        (height + scaledChildHeight) / 2);
+            }
+        }
+    }
+
+    public void surfaceCreated(SurfaceHolder holder) {
+        // The Surface has been created, acquire the camera and tell it where
+        // to draw.
+        try {
+            if (mCamera != null) {
+                mCamera.setPreviewDisplay(holder);
+            }
+        } catch (IOException exception) {
+            Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
+        }
+    }
+
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        // Surface will be destroyed when we return, so stop the preview.
+        if (mCamera != null) {
+            mCamera.stopPreview();
+        }
+    }
+
+    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
+        final double ASPECT_TOLERANCE = 0.1;
+        double targetRatio = (double) w / h;
+        if (sizes == null)
+            return null;
+
+        Size optimalSize = null;
+        double minDiff = Double.MAX_VALUE;
+
+        int targetHeight = h;
+
+        // Try to find an size match aspect ratio and size
+        for (Size size : sizes) {
+            double ratio = (double) size.width / size.height;
+            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
+                continue;
+            if (Math.abs(size.height - targetHeight) < minDiff) {
+                optimalSize = size;
+                minDiff = Math.abs(size.height - targetHeight);
+            }
+        }
+
+        // Cannot find the one match the aspect ratio, ignore the requirement
+        if (optimalSize == null) {
+            minDiff = Double.MAX_VALUE;
+            for (Size size : sizes) {
+                if (Math.abs(size.height - targetHeight) < minDiff) {
+                    optimalSize = size;
+                    minDiff = Math.abs(size.height - targetHeight);
+                }
+            }
+        }
+        return optimalSize;
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        // Now that the size is known, set up the camera parameters and begin
+        // the preview.
+        Camera.Parameters parameters = mCamera.getParameters();
+        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
+        requestLayout();
+
+        mCamera.setParameters(parameters);
+        mCamera.startPreview();
+    }
+
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/CameraSample.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/CameraSample.java
new file mode 100644 (file)
index 0000000..2243858
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CameraSample extends Activity {
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        int themeId = this.getIntent().getExtras().getInt("theme");
+        this.setTheme(themeId);
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.camera_sample);
+    }
+
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/ContentFragment.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/ContentFragment.java
new file mode 100644 (file)
index 0000000..c4b34bf
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+import java.util.StringTokenizer;
+
+import android.app.ActionBar;
+import android.app.Fragment;
+import android.content.ClipData;
+import android.content.ClipDescription;
+import android.content.ClipData.Item;
+import android.os.Bundle;
+import android.view.DragEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.ImageView;
+
+public class ContentFragment extends Fragment {
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.content_welcome, null);
+        final ImageView imageView = (ImageView) view.findViewById(R.id.image);
+        view.setDrawingCacheEnabled(false);
+
+        view.setOnDragListener(new View.OnDragListener() {
+            public boolean onDrag(View v, DragEvent event) {
+                switch (event.getAction()) {
+                case DragEvent.ACTION_DRAG_STARTED:
+                    return processDragStarted(event);
+                case DragEvent.ACTION_DROP:
+                    return processDrop(event, imageView);
+                }
+                return false;
+            }
+        });
+
+        view.setOnClickListener(new OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                ActionBar bar = ContentFragment.this.getActivity()
+                        .getActionBar();
+                if (bar != null) {
+                    if (bar.isShowing()) {
+                        bar.hide();
+                    } else {
+                        bar.show();
+                    }
+                }
+            }
+        });
+        return view;
+    }
+
+   boolean processDragStarted(DragEvent event) {
+        // Determine whether to continue processing drag and drop based on the
+        // plain text mime type.
+        ClipDescription clipDesc = event.getClipDescription();
+        if (clipDesc != null) {
+            return clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
+        }
+        return false;
+    }
+
+   boolean processDrop(DragEvent event, ImageView imageView) {
+        // Attempt to parse clip data with expected format: category||entry_id.
+        // Ignore event if data does not conform to this format.
+        ClipData data = event.getClipData();
+        if (data != null) {
+            if (data.getItemCount() > 0) {
+                Item item = data.getItemAt(0);
+                String textData = (String) item.getText();
+                if (textData != null) {
+                    StringTokenizer tokenizer = new StringTokenizer(textData, "||");
+                    if (tokenizer.countTokens() != 2) {
+                        return false;
+                    }
+                    int category = -1;
+                    int entryId = -1;
+                    try {
+                        category = Integer.parseInt(tokenizer.nextToken());
+                        entryId = Integer.parseInt(tokenizer.nextToken());
+                    } catch (NumberFormatException exception) {
+                        return false;
+                    }
+                    imageView.setImageBitmap(
+                        Directory.getCategory(category)
+                                 .getEntry(entryId)
+                                 .getBitmap(getResources()));
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/Directory.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/Directory.java
new file mode 100644 (file)
index 0000000..570c788
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+public class Directory {
+    private static DirectoryCategory[] categories;
+
+    public static void initializeDirectory() {
+        categories = new DirectoryCategory[] {
+                new DirectoryCategory("Balloons", new DirectoryEntry[] {
+                        new DirectoryEntry("Green Balloon", R.drawable.green_balloon),
+                        new DirectoryEntry("Red Balloon", R.drawable.red_balloon),
+                        new DirectoryEntry("Blue Balloon", R.drawable.blue_balloon)}),
+                new DirectoryCategory("Bikes", new DirectoryEntry[] {
+                        new DirectoryEntry("Old school huffy", R.drawable.blue_bike),
+                        new DirectoryEntry("New Bikes", R.drawable.rainbow_bike),
+                        new DirectoryEntry("Chrome Fast", R.drawable.chrome_wheel)}),
+                new DirectoryCategory("Androids", new DirectoryEntry[] {
+                        new DirectoryEntry("Steampunk Android", R.drawable.punk_droid),
+                        new DirectoryEntry("Stargazing Android", R.drawable.stargazer_droid),
+                        new DirectoryEntry("Big Android", R.drawable.big_droid) }),
+                new DirectoryCategory("Pastries", new DirectoryEntry[] {
+                        new DirectoryEntry("Cupcake", R.drawable.cupcake),
+                        new DirectoryEntry("Donut", R.drawable.donut),
+                        new DirectoryEntry("Eclair", R.drawable.eclair),
+                        new DirectoryEntry("Froyo", R.drawable.froyo), }), };
+
+    }
+
+    public static int getCategoryCount() {
+        return categories.length;
+    }
+
+    public static DirectoryCategory getCategory(int i) {
+        return categories[i];
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/DirectoryCategory.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/DirectoryCategory.java
new file mode 100644 (file)
index 0000000..926f6e5
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+public class DirectoryCategory {
+    private String name;
+    private DirectoryEntry[] entries;
+
+    public DirectoryCategory(String name, DirectoryEntry[] entries) {
+        this.name = name;
+        this.entries = entries;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public int getEntryCount() {
+        return entries.length;
+    }
+
+    public DirectoryEntry getEntry(int i) {
+        return entries[i];
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/DirectoryEntry.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/DirectoryEntry.java
new file mode 100644 (file)
index 0000000..ecfd4c3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
+
+public class DirectoryEntry {
+    private String name;
+    private int resID;
+
+    public DirectoryEntry(String name, int resID) {
+        this.name = name;
+        this.resID = resID;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Drawable getDrawable(Resources res) {
+        return res.getDrawable(resID);
+    }
+
+    public Bitmap getBitmap(Resources res) {
+        return BitmapFactory.decodeResource(res, resID);
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/MainActivity.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/MainActivity.java
new file mode 100644 (file)
index 0000000..ec8ea49
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.animation.ValueAnimator;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class MainActivity extends Activity implements ActionBar.TabListener {
+
+    private View mActionBarView;
+    private Animator mCurrentTitlesAnimator;
+    private String[] mToggleLabels = {"Show Titles", "Hide Titles"};
+    private int mLabelIndex = 1;
+    private int mThemeId = -1;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        if(savedInstanceState != null && savedInstanceState.getInt("theme", -1) != -1) {
+            mThemeId = savedInstanceState.getInt("theme");
+            this.setTheme(mThemeId);
+        }
+        setContentView(R.layout.main);
+
+        Directory.initializeDirectory();
+
+        ActionBar bar = getActionBar();
+
+        int i;
+        for (i = 0; i < Directory.getCategoryCount(); i++)
+            bar.addTab(bar.newTab().setText(Directory.getCategory(i).getName())
+                    .setTabListener(this));
+
+        mActionBarView = getLayoutInflater().inflate(
+                R.layout.action_bar_custom, null);
+
+        bar.setCustomView(mActionBarView);
+        bar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_USE_LOGO);
+        bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
+        bar.setDisplayShowHomeEnabled(true);
+
+        // If category is not saved to the savedInstanceState,
+        // 0 is returned by default.
+        if(savedInstanceState != null) {
+            int category = savedInstanceState.getInt("category");
+            bar.selectTab(bar.getTabAt(category));
+        }
+    }
+
+    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
+        TitlesFragment titleFrag = (TitlesFragment) getFragmentManager()
+                .findFragmentById(R.id.frag_title);
+        titleFrag.populateTitles(tab.getPosition());
+
+        titleFrag.selectPosition(0);
+    }
+
+    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
+    }
+
+    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.main_menu, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+        case R.id.camera:
+            Intent intent = new Intent(this, CameraSample.class);
+            intent.putExtra("theme", mThemeId);
+            startActivity(intent);
+            return true;
+        case R.id.toggleTitles:
+            toggleVisibleTitles();
+            return true;
+        case R.id.toggleTheme:
+            if (mThemeId == android.R.style.Theme_Holo) {
+                mThemeId = android.R.style.Theme_Holo_Light;
+            } else {
+                mThemeId = android.R.style.Theme_Holo;
+            }
+            this.recreate();
+        default:
+            return super.onOptionsItemSelected(item);
+        }
+    }
+
+    public void toggleVisibleTitles() {
+        // Use these for custom animations.
+        final FragmentManager fm = getFragmentManager();
+        final TitlesFragment f = (TitlesFragment) fm
+                .findFragmentById(R.id.frag_title);
+        final View titlesView = f.getView();
+        mLabelIndex = 1 - mLabelIndex;
+
+        // Determine if we're in portrait, and whether we're showing or hiding the titles
+        // with this toggle.
+        final boolean isPortrait = getResources().getConfiguration().orientation ==
+                Configuration.ORIENTATION_PORTRAIT;
+
+        final boolean shouldShow = f.isHidden() || mCurrentTitlesAnimator != null;
+
+        // Cancel the current titles animation if there is one.
+        if (mCurrentTitlesAnimator != null)
+            mCurrentTitlesAnimator.cancel();
+
+        // Begin setting up the object animator. We'll animate the bottom or right edge of the
+        // titles view, as well as its alpha for a fade effect.
+        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(
+                titlesView,
+                PropertyValuesHolder.ofInt(
+                        isPortrait ? "bottom" : "right",
+                        shouldShow ? getResources().getDimensionPixelSize(R.dimen.titles_size)
+                                   : 0),
+                PropertyValuesHolder.ofFloat("alpha", shouldShow ? 1 : 0)
+        );
+
+        // At each step of the animation, we'll perform layout by calling setLayoutParams.
+        final ViewGroup.LayoutParams lp = titlesView.getLayoutParams();
+        objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                // *** WARNING ***: triggering layout at each animation frame highly impacts
+                // performance so you should only do this for simple layouts. More complicated
+                // layouts can be better served with individual animations on child views to
+                // avoid the performance penalty of layout.
+                if (isPortrait) {
+                    lp.height = (Integer) valueAnimator.getAnimatedValue();
+                } else {
+                    lp.width = (Integer) valueAnimator.getAnimatedValue();
+                }
+                titlesView.setLayoutParams(lp);
+            }
+        });
+
+        if (shouldShow) {
+            fm.beginTransaction().show(f).commit();
+            objectAnimator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animator) {
+                    mCurrentTitlesAnimator = null;
+                }
+            });
+
+        } else {
+            objectAnimator.addListener(new AnimatorListenerAdapter() {
+                boolean canceled;
+
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    canceled = true;
+                    super.onAnimationCancel(animation);
+                }
+
+                @Override
+                public void onAnimationEnd(Animator animator) {
+                    if (canceled)
+                        return;
+                    mCurrentTitlesAnimator = null;
+                    fm.beginTransaction().hide(f).commit();
+                }
+            });
+        }
+
+        // Start the animation.
+        objectAnimator.start();
+        mCurrentTitlesAnimator = objectAnimator;
+
+        invalidateOptionsMenu();
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        menu.getItem(1).setTitle(mToggleLabels[mLabelIndex]);
+        return true;
+    }
+
+    @Override
+    public void onSaveInstanceState (Bundle outState) {
+        super.onSaveInstanceState(outState);
+        ActionBar bar = getActionBar();
+        int category = bar.getSelectedTab().getPosition();
+        outState.putInt("category", category);
+        outState.putInt("theme", mThemeId);
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/TitlesFragment.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/TitlesFragment.java
new file mode 100644 (file)
index 0000000..2267681
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2011 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.hcgallery;
+
+import android.app.ListFragment;
+import android.content.ClipData;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.AdapterView.OnItemLongClickListener;
+
+public class TitlesFragment extends ListFragment {
+    private int mCategory = 0;
+    private int mCurPosition = 0;
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        //Current position should survive screen rotations.
+        if (savedInstanceState != null) {
+            mCategory = savedInstanceState.getInt("category");
+            mCurPosition = savedInstanceState.getInt("listPosition");
+        }
+
+        populateTitles(mCategory);
+        ListView lv = getListView();
+        lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+        selectPosition(mCurPosition);
+        lv.setCacheColorHint(Color.WHITE);
+
+        lv.setOnItemLongClickListener(new OnItemLongClickListener() {
+
+            @Override
+            public boolean onItemLongClick(AdapterView<?> av, View v, int pos,
+                    long id) {
+                final String title = (String) ((TextView) v).getText();
+
+                // Set up clip data with the category||entry_id format.
+                final String textData = String.format("%d||%d", mCategory, pos);
+                ClipData data = ClipData.newPlainText(title, textData);
+                v.startDrag(data, new MyDragShadowBuilder(v), null, 0);
+                return true;
+            }
+        });
+    }
+
+    private static class MyDragShadowBuilder extends View.DragShadowBuilder {
+        private static Drawable shadow;
+
+        public MyDragShadowBuilder(View v) {
+            super(v);
+            shadow = new ColorDrawable(Color.BLUE);
+            shadow.setBounds(0, 0, v.getWidth(), v.getHeight());
+        }
+
+        @Override
+        public void onDrawShadow(Canvas canvas) {
+            shadow.draw(canvas);
+        }
+    }
+
+    public void populateTitles(int category) {
+        DirectoryCategory cat = Directory.getCategory(category);
+        String[] items = new String[cat.getEntryCount()];
+        for (int i = 0; i < cat.getEntryCount(); i++)
+            items[i] = cat.getEntry(i).getName();
+        setListAdapter(new ArrayAdapter<String>(getActivity(),
+                R.layout.title_list_item, items));
+        mCategory = category;
+    }
+
+    @Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        updateImage(position);
+    }
+
+    private void updateImage(int position) {
+        ImageView iv = (ImageView) getFragmentManager().findFragmentById(
+                R.id.frag_content).getView().findViewById(R.id.image);
+        iv.setImageDrawable(Directory.getCategory(mCategory).getEntry(position)
+                .getDrawable(getResources()));
+        mCurPosition = position;
+    }
+
+    public void selectPosition(int position) {
+        ListView lv = getListView();
+        lv.setItemChecked(position, true);
+        updateImage(position);
+
+    }
+
+    @Override
+    public void onSaveInstanceState (Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putInt("listPosition", mCurPosition);
+        outState.putInt("category", mCategory);
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetItem.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetItem.java
new file mode 100644 (file)
index 0000000..4c4b230
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 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.hcgallery.widget;
+
+public class WidgetItem {
+    public String text;
+
+    public WidgetItem(String text) {
+        this.text = text;
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetProvider.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetProvider.java
new file mode 100644 (file)
index 0000000..07a984d
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2007 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.hcgallery.widget;
+
+import com.example.android.hcgallery.R;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.widget.RemoteViews;
+import android.widget.Toast;
+
+public class WidgetProvider extends AppWidgetProvider {
+    public static String TOAST_ACTION = "com.example.android.widget.action.TOAST";
+
+    @Override
+    public void onDeleted(Context context, int[] appWidgetIds) {
+        super.onDeleted(context, appWidgetIds);
+    }
+
+    @Override
+    public void onDisabled(Context context) {
+        super.onDisabled(context);
+    }
+
+    @Override
+    public void onEnabled(Context context) {
+        super.onEnabled(context);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+
+        AppWidgetManager mgr = AppWidgetManager.getInstance(context);
+        if (intent.getAction().equals(TOAST_ACTION)) {
+            int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
+                    AppWidgetManager.INVALID_APPWIDGET_ID);
+            int viewIndex = intent.getIntExtra("numberToToast", 0);
+            Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show();
+        }
+        super.onReceive(context, intent);
+    }
+
+    @Override
+    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+        // update each of the widgets with the remote adapter
+        for (int i = 0; i < appWidgetIds.length; ++i) {
+
+            // Here we setup the intent which points to the StackViewService which will
+            // provide the views for this collection.
+            Intent intent = new Intent(context, WidgetService.class);
+            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
+            // When intents are compared, the extras are ignored, so we need to embed the extras
+            // into the data so that the extras will not be ignored.
+            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
+            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
+            rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
+
+            // The empty view is displayed when the collection has no items. It should be a sibling
+            // of the collection view.
+            rv.setEmptyView(R.id.stack_view, R.id.empty_view);
+
+            // Here we setup the a pending intent template. Individuals items of a collection
+            // cannot setup their own pending intents, instead, the collection as a whole can
+            // setup a pending intent template, and the individual items can set a fillInIntent
+            // to create unique before on an item to item basis.
+            Intent toastIntent = new Intent(context, WidgetProvider.class);
+            toastIntent.setAction(WidgetProvider.TOAST_ACTION);
+            toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
+            toastIntent.setData(Uri.parse("widgetid" + appWidgetIds[i]));
+            PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
+                    PendingIntent.FLAG_UPDATE_CURRENT);
+            rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
+
+            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
+        }
+        super.onUpdate(context, appWidgetManager, appWidgetIds);
+    }
+}
diff --git a/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetService.java b/samples/Honeycomb-Gallery/src/com/example/android/hcgallery/widget/WidgetService.java
new file mode 100644 (file)
index 0000000..e7aaa6b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2007 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.hcgallery.widget;
+
+import com.example.android.hcgallery.R;
+
+import java.util.ArrayList;
+import java.util.List;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+public class WidgetService extends RemoteViewsService {
+
+    private class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
+        private static final int mCount = 10;
+        private List<WidgetItem> mWidgetItems = new ArrayList<WidgetItem>();
+        private Context mContext;
+        private int mAppWidgetId;
+
+        public StackRemoteViewsFactory(Context context, Intent intent) {
+            mContext = context;
+            mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
+                    AppWidgetManager.INVALID_APPWIDGET_ID);
+        }
+
+        public void onCreate() {
+            // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
+            // for example downloading or creating content etc, should be deferred to getViewAt() or
+            // onDataSetChanged(). Taking more than 20 seconds in this call will result in an ANR.
+            for (int i = 0; i < mCount; i++) {
+                mWidgetItems.add(new WidgetItem(i + "!"));
+            }
+
+            // We sleep for 3 seconds here to show how the empty view appears in the interim.
+            // The empty view is set in the WidgetProvider and should be a sibling of the
+            // collection view.
+            try {
+                Thread.sleep(3000);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+
+        public void onDestroy() {
+            // In onDestroy() you should tear down anything that was setup for your data source,
+            // eg. cursors, connections, etc.
+            mWidgetItems.clear();
+        }
+
+        public int getCount() {
+            return mCount;
+        }
+
+        public RemoteViews getViewAt(int position) {
+            // position will always range from 0 to getCount() - 1.
+
+            // We construct a remote views item based on our widget item xml file, and set the
+            // text based on the position.
+            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
+            rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
+
+            // Next, we set an intent so that clicking on this view will result in a toast message
+            Bundle extras = new Bundle();
+            extras.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
+            extras.putInt("numberToToast", position);
+            Intent fillInIntent = new Intent();
+            fillInIntent.putExtras(extras);
+            rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
+
+            // You can do heaving lifting in here, synchronously. For example, if you need to
+            // process an image, fetch something from the network, etc., it is ok to do it here,
+            // synchronously. A loading view will show up in lieu of the actual contents in the
+            // interim.
+            try {
+                Log.d("WidgetService/getViewAt", "Loading view " + position);
+                // Simulating a time-consuming operation.  NO NEED to include this call in your app!
+                Thread.sleep(500);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+
+            // Return our remote views object.
+            return rv;
+        }
+
+        public RemoteViews getLoadingView() {
+            // You can create a custom loading view (for instance when getViewAt() is slow. If you
+            // return null here, you will get the default loading view.
+            return null;
+        }
+
+        public int getViewTypeCount() {
+            return 1;
+        }
+
+        public long getItemId(int position) {
+            return position;
+        }
+
+        public boolean hasStableIds() {
+            return true;
+        }
+
+        public void onDataSetChanged() {
+            // This is triggered when you call AppWidgetManager notifyAppWidgetViewDataChanged
+            // on the collection view corresponding to this factory. You can do heaving lifting in
+            // here, synchronously. For example, if you need to process an image, fetch something
+            // from the network, etc., it is ok to do it here, synchronously. The widget will remain
+            // in its current state while work is being done here, so you don't need to worry about
+            // locking up the widget.
+        }
+    }
+
+    public RemoteViewsFactory onGetViewFactory(Intent intent) {
+        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
+    }
+}