Major update to HoneycombGallery
* Add action bar and icon theming * Add contextual action bar and photo sharing * Add notifications (with large icons too) * Add fullscreening (lights-out mode) * Add a picture frame Change-Id: I07a1da435d5adc7bc76c7ac2cc087ff2efd74156
@@ -162,7 +162,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/HoneycombGallery samples/${PLATFORM_NAME}/HoneycombGallery
|
||||
development/samples/JetBoy samples/${PLATFORM_NAME}/JetBoy
|
||||
development/samples/LunarLander samples/${PLATFORM_NAME}/LunarLander
|
||||
development/samples/MultiResolution samples/${PLATFORM_NAME}/MultiResolution
|
||||
|
||||
@@ -6,7 +6,7 @@ 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_PACKAGE_NAME := HoneycombGallery
|
||||
|
||||
LOCAL_SDK_VERSION := current
|
||||
|
||||
|
||||
@@ -19,20 +19,28 @@
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-sdk android:minSdkVersion="11" />
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<application android:label="@string/app_name"
|
||||
android:icon="@drawable/icon"
|
||||
android:logo="@drawable/logo"
|
||||
android:theme="@android:style/Theme.Holo.Light"
|
||||
android:theme="@style/AppTheme.Light"
|
||||
android:hardwareAccelerated="true"
|
||||
android:debuggable="true">
|
||||
|
||||
<activity android:name=".MainActivity" android:label="@string/app_name">
|
||||
<activity android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="com.example.android.hcgallery.action.DIALOG" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- CameraSample -->
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
<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>
|
||||
Honeycomb, including:</p>
|
||||
|
||||
<p>The application includes the following classes:<p>
|
||||
<ul>
|
||||
<li><a href="../../../guide/topics/fundamentals/fragments.html">Fragments</a></li>
|
||||
<li>The <a href="../../../guide/topics/ui/actionbar.html">action bar</a>
|
||||
and contextual action bar</li>
|
||||
<li>Drag and drop</li>
|
||||
<li>The new <a href="../../../reference/android/animation/package-summary.html"><code>android.animation</code></a>
|
||||
framework</li>
|
||||
<li>Custom notifications</li>
|
||||
<li><a href="../../../reference/android/widget/StackView.html"><code>StackView</code></a>
|
||||
and other adapter-based app widgets</li>
|
||||
</ul>
|
||||
|
||||
<p>The image gallery shows how all these pieces can work together in one application.</p>
|
||||
|
||||
<p>The application includes the following key 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>
|
||||
A fragment responsible for containing the "content" of the application.
|
||||
Displays images, receives drag/drop events from other fragments, and can
|
||||
invoke the contextual action bar using
|
||||
<a href="../../../reference/android/view/ActionMode.html">action modes</a>.</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
|
||||
@@ -19,7 +33,7 @@ can work together in one application.</p>
|
||||
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).
|
||||
a separate 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
|
||||
|
||||
|
Before Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1013 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
@@ -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.
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_pressed="true" android:drawable="@drawable/btn_notification_ic_example_pressed" />
|
||||
<item android:drawable="@drawable/btn_notification_ic_example_default" />
|
||||
</selector>
|
||||
21
samples/Honeycomb-Gallery/res/drawable/picture_frame.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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.
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:drawable="@drawable/picture_frame_selected" />
|
||||
<item android:state_pressed="true" android:drawable="@drawable/picture_frame_pressed" />
|
||||
<item android:drawable="@drawable/picture_frame_default" />
|
||||
</selector>
|
||||
@@ -15,13 +15,16 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<view xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
class="com.example.android.hcgallery.FitCenterFrameLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="12dp">
|
||||
android:padding="24dp"
|
||||
android:clickable="true">
|
||||
<ImageView android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter"
|
||||
android:layout_gravity="center" />
|
||||
</FrameLayout>
|
||||
android:background="@drawable/picture_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:duplicateParentState="true"/>
|
||||
</view>
|
||||
|
||||
60
samples/Honeycomb-Gallery/res/layout/notification.xml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?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:id="@+id/notificationbg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:paddingLeft="16dip"
|
||||
android:layout_width="0dip"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/notification_title"
|
||||
style="@android:style/TextAppearance.StatusBar.EventContent.Title"
|
||||
android:focusable="true"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:layout_gravity="left"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView android:id="@+id/notification_subtitle"
|
||||
style="@android:style/TextAppearance.StatusBar.EventContent"
|
||||
android:layout_gravity="left"
|
||||
android:maxLines="2"
|
||||
android:scrollHorizontally="true"
|
||||
android:ellipsize="end"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/notification_text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/notification_button"
|
||||
android:src="@drawable/btn_notification_ic_example"
|
||||
android:background="@null"
|
||||
android:layout_weight="0"
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -18,16 +18,23 @@
|
||||
<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:icon="?attr/menuIconCamera"
|
||||
android:showAsAction="ifRoom" />
|
||||
<item android:id="@+id/toggleTitles"
|
||||
android:icon="@drawable/ic_menu_toggle"
|
||||
android:icon="?attr/menuIconToggle"
|
||||
android:title="Toggle Titles"
|
||||
android:showAsAction="ifRoom|withText" />
|
||||
<!-- Example of items in the overflow menu -->
|
||||
<item android:id="@+id/toggleTheme"
|
||||
android:title="Day/Night"
|
||||
android:showAsAction="ifRoom|withText" />
|
||||
android:showAsAction="never" />
|
||||
<item android:id="@+id/showDialog"
|
||||
android:title="Show a dialog"
|
||||
android:showAsAction="ifRoom|withText" />
|
||||
android:title="Show a dialog"
|
||||
android:showAsAction="never" />
|
||||
<item android:id="@+id/showStandardNotification"
|
||||
android:title="Show a basic notification"
|
||||
android:showAsAction="never" />
|
||||
<item android:id="@+id/showCustomNotification"
|
||||
android:title="Show a custom notification"
|
||||
android:showAsAction="never" />
|
||||
</menu>
|
||||
|
||||
23
samples/Honeycomb-Gallery/res/menu/photo_context_menu.xml
Normal file
@@ -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.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/share"
|
||||
android:title="Share"
|
||||
android:icon="?attr/menuIconShare"
|
||||
android:showAsAction="always|withText" />
|
||||
</menu>
|
||||
24
samples/Honeycomb-Gallery/res/values/attrs.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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>
|
||||
<declare-styleable name="AppTheme">
|
||||
<attr name="listDragShadowBackground" format="reference" />
|
||||
<attr name="menuIconCamera" format="reference" />
|
||||
<attr name="menuIconToggle" format="reference" />
|
||||
<attr name="menuIconShare" format="reference" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -17,4 +17,5 @@
|
||||
<resources>
|
||||
<color name="actionbar_background_light">#ccffffff</color>
|
||||
<color name="actionbar_background_dark">#cc000000</color>
|
||||
<color name="drag_active_color">#80cccccc</color>
|
||||
</resources>
|
||||
|
||||
@@ -15,10 +15,14 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
<resources>
|
||||
<string name="app_name">Honeycomb Example</string>
|
||||
<string name="app_name">Honeycomb Gallery</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>
|
||||
|
||||
<string name="notification_text">Example notification text</string>
|
||||
|
||||
<string name="photo_selection_cab_title">Photo selection</string>
|
||||
</resources>
|
||||
|
||||
45
samples/Honeycomb-Gallery/res/values/styles.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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>
|
||||
<style name="ActionBar" parent="@android:style/Widget.Holo.ActionBar" />
|
||||
|
||||
<style name="ActionBar.Light" parent="@style/ActionBar">
|
||||
<item name="android:background">@color/actionbar_background_light</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionBar.Dark" parent="@style/ActionBar">
|
||||
<item name="android:background">@color/actionbar_background_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Light" parent="@android:style/Theme.Holo.Light">
|
||||
<item name="android:actionBarStyle">@style/ActionBar.Light</item>
|
||||
<item name="android:windowActionBarOverlay">true</item>
|
||||
<item name="listDragShadowBackground">@android:color/background_light</item>
|
||||
<item name="menuIconCamera">@drawable/ic_menu_camera_holo_light</item>
|
||||
<item name="menuIconToggle">@drawable/ic_menu_toggle_holo_light</item>
|
||||
<item name="menuIconShare">@drawable/ic_menu_share_holo_light</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.Dark" parent="@android:style/Theme.Holo">
|
||||
<item name="android:actionBarStyle">@style/ActionBar.Dark</item>
|
||||
<item name="android:windowActionBarOverlay">true</item>
|
||||
<item name="listDragShadowBackground">@android:color/background_dark</item>
|
||||
<item name="menuIconCamera">@drawable/ic_menu_camera_holo_dark</item>
|
||||
<item name="menuIconToggle">@drawable/ic_menu_toggle_holo_dark</item>
|
||||
<item name="menuIconShare">@drawable/ic_menu_share_holo_dark</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -16,29 +16,45 @@
|
||||
|
||||
package com.example.android.hcgallery;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ClipData.Item;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.ActionMode;
|
||||
import android.view.DragEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class ContentFragment extends Fragment {
|
||||
private View mContentView;
|
||||
|
||||
// The bitmap currently used by ImageView
|
||||
private Bitmap mBitmap = null;
|
||||
|
||||
// Current action mode (contextual action bar, a.k.a. CAB)
|
||||
private ActionMode mCurrentActionMode;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
@@ -47,47 +63,86 @@ public class ContentFragment extends Fragment {
|
||||
@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);
|
||||
mContentView = inflater.inflate(R.layout.content_welcome, null);
|
||||
final ImageView imageView = (ImageView) mContentView.findViewById(R.id.image);
|
||||
mContentView.setDrawingCacheEnabled(false);
|
||||
|
||||
view.setOnDragListener(new View.OnDragListener() {
|
||||
mContentView.setOnDragListener(new View.OnDragListener() {
|
||||
public boolean onDrag(View v, DragEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case DragEvent.ACTION_DRAG_ENTERED:
|
||||
view.setBackgroundColor(Color.LTGRAY);
|
||||
break;
|
||||
case DragEvent.ACTION_DRAG_EXITED:
|
||||
view.setBackgroundColor(Color.TRANSPARENT);
|
||||
break;
|
||||
case DragEvent.ACTION_DRAG_STARTED:
|
||||
return processDragStarted(event);
|
||||
case DragEvent.ACTION_DROP:
|
||||
view.setBackgroundColor(Color.TRANSPARENT);
|
||||
return processDrop(event, imageView);
|
||||
case DragEvent.ACTION_DRAG_ENTERED:
|
||||
mContentView.setBackgroundColor(
|
||||
getResources().getColor(R.color.drag_active_color));
|
||||
break;
|
||||
|
||||
case DragEvent.ACTION_DRAG_EXITED:
|
||||
mContentView.setBackgroundColor(Color.TRANSPARENT);
|
||||
break;
|
||||
|
||||
case DragEvent.ACTION_DRAG_STARTED:
|
||||
return processDragStarted(event);
|
||||
|
||||
case DragEvent.ACTION_DROP:
|
||||
mContentView.setBackgroundColor(Color.TRANSPARENT);
|
||||
return processDrop(event, imageView);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
view.setOnClickListener(new OnClickListener() {
|
||||
// Keep the action bar visibility in sync with the system status bar. That is, when entering
|
||||
// 'lights out mode,' hide the action bar, and when exiting this mode, show the action bar.
|
||||
|
||||
|
||||
public void onClick(View v) {
|
||||
ActionBar bar = getActivity().getActionBar();
|
||||
if (bar != null) {
|
||||
if (bar.isShowing()) {
|
||||
bar.hide();
|
||||
} else {
|
||||
bar.show();
|
||||
final Activity activity = getActivity();
|
||||
mContentView.setOnSystemUiVisibilityChangeListener(
|
||||
new View.OnSystemUiVisibilityChangeListener() {
|
||||
public void onSystemUiVisibilityChange(int visibility) {
|
||||
ActionBar actionBar = activity.getActionBar();
|
||||
if (actionBar != null) {
|
||||
mContentView.setSystemUiVisibility(visibility);
|
||||
if (visibility == View.STATUS_BAR_VISIBLE) {
|
||||
actionBar.show();
|
||||
} else {
|
||||
actionBar.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Show/hide the system status bar when single-clicking a photo. This is also called
|
||||
// 'lights out mode.' Activating and deactivating this mode also invokes the listener
|
||||
// defined above, which will show or hide the action bar accordingly.
|
||||
|
||||
mContentView.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
if (mContentView.getSystemUiVisibility() == View.STATUS_BAR_VISIBLE) {
|
||||
mContentView.setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
|
||||
} else {
|
||||
mContentView.setSystemUiVisibility(View.STATUS_BAR_VISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
return view;
|
||||
|
||||
// When long-pressing a photo, activate the action mode for selection, showing the
|
||||
// contextual action bar (CAB).
|
||||
|
||||
mContentView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
public boolean onLongClick(View view) {
|
||||
if (mCurrentActionMode != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mCurrentActionMode = getActivity().startActionMode(
|
||||
mContentSelectionActionModeCallback);
|
||||
mContentView.setSelected(true);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return mContentView;
|
||||
}
|
||||
|
||||
boolean processDragStarted(DragEvent event) {
|
||||
boolean processDragStarted(DragEvent event) {
|
||||
// Determine whether to continue processing drag and drop based on the
|
||||
// plain text mime type.
|
||||
ClipDescription clipDesc = event.getClipDescription();
|
||||
@@ -97,7 +152,7 @@ public class ContentFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean processDrop(DragEvent event, ImageView imageView) {
|
||||
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();
|
||||
@@ -130,16 +185,115 @@ public class ContentFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateContentAndRecycleBitmap(int category, int position) {
|
||||
// Get the bitmap that needs to be drawn and update the ImageView
|
||||
Bitmap next = Directory.getCategory(category).getEntry(position)
|
||||
.getBitmap(getResources());
|
||||
((ImageView) getView().findViewById(R.id.image)).setImageBitmap(next);
|
||||
void updateContentAndRecycleBitmap(int category, int position) {
|
||||
if (mCurrentActionMode != null) {
|
||||
mCurrentActionMode.finish();
|
||||
}
|
||||
|
||||
if (mBitmap != null) {
|
||||
// This is an advanced call and should be used if you
|
||||
// are working with a lot of bitmaps. The bitmap is dead
|
||||
// after this call.
|
||||
mBitmap.recycle();
|
||||
}
|
||||
|
||||
// Get the bitmap that needs to be drawn and update the ImageView
|
||||
mBitmap = Directory.getCategory(category).getEntry(position)
|
||||
.getBitmap(getResources());
|
||||
((ImageView) getView().findViewById(R.id.image)).setImageBitmap(mBitmap);
|
||||
}
|
||||
|
||||
void shareCurrentPhoto() {
|
||||
File externalCacheDir = getActivity().getExternalCacheDir();
|
||||
if (externalCacheDir == null) {
|
||||
Toast.makeText(getActivity(), "Error writing to USB/external storage.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent media scanning of the cache directory.
|
||||
final File noMediaFile = new File(externalCacheDir, ".nomedia");
|
||||
try {
|
||||
noMediaFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
// Write the bitmap to temporary storage in the external storage directory (e.g. SD card).
|
||||
// We perform the actual disk write operations on a separate thread using the
|
||||
// {@link AsyncTask} class, thus avoiding the possibility of stalling the main (UI) thread.
|
||||
|
||||
final File tempFile = new File(externalCacheDir, "tempfile.jpg");
|
||||
|
||||
new AsyncTask<Void, Void, Boolean>() {
|
||||
/**
|
||||
* Compress and write the bitmap to disk on a separate thread.
|
||||
* @return TRUE if the write was successful, FALSE otherwise.
|
||||
*/
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
try {
|
||||
FileOutputStream fo = new FileOutputStream(tempFile, false);
|
||||
if (!mBitmap.compress(Bitmap.CompressFormat.JPEG, 60, fo)) {
|
||||
Toast.makeText(getActivity(), "Error writing bitmap data.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
Toast.makeText(getActivity(), "Error writing to USB/external storage.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After doInBackground completes (either successfully or in failure), we invoke an
|
||||
* intent to share the photo. This code is run on the main (UI) thread.
|
||||
*/
|
||||
protected void onPostExecute(Boolean result) {
|
||||
if (result != Boolean.TRUE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
||||
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(tempFile));
|
||||
shareIntent.setType("image/jpeg");
|
||||
startActivity(Intent.createChooser(shareIntent, "Share photo"));
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback for the 'photo selected' {@link ActionMode}. In this action mode, we can
|
||||
* provide contextual actions for the selected photo. We currently only provide the 'share'
|
||||
* action, but we could also add clipboard functions such as cut/copy/paste here as well.
|
||||
*/
|
||||
private ActionMode.Callback mContentSelectionActionModeCallback = new ActionMode.Callback() {
|
||||
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
|
||||
actionMode.setTitle(R.string.photo_selection_cab_title);
|
||||
|
||||
MenuInflater inflater = getActivity().getMenuInflater();
|
||||
inflater.inflate(R.menu.photo_context_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
|
||||
switch (menuItem.getItemId()) {
|
||||
case R.id.share:
|
||||
shareCurrentPhoto();
|
||||
actionMode.finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onDestroyActionMode(ActionMode actionMode) {
|
||||
mContentView.setSelected(false);
|
||||
mCurrentActionMode = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
/**
|
||||
* A simple layout that fits and centers each child view, maintaining aspect ratio.
|
||||
*/
|
||||
public class FitCenterFrameLayout extends ViewGroup {
|
||||
public FitCenterFrameLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FitCenterFrameLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// We purposely disregard child measurements.
|
||||
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
|
||||
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
|
||||
setMeasuredDimension(width, height);
|
||||
|
||||
int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
|
||||
int childHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.UNSPECIFIED);
|
||||
|
||||
int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
getChildAt(i).measure(childWidthSpec, childHeightSpec);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
final int childCount = getChildCount();
|
||||
|
||||
final int parentLeft = getPaddingLeft();
|
||||
final int parentTop = getPaddingTop();
|
||||
final int parentRight = r - l - getPaddingRight();
|
||||
final int parentBottom = b - t - getPaddingBottom();
|
||||
|
||||
final int parentWidth = parentRight - parentLeft;
|
||||
final int parentHeight = parentBottom - parentTop;
|
||||
|
||||
int unpaddedWidth, unpaddedHeight, parentUnpaddedWidth, parentUnpaddedHeight;
|
||||
int childPaddingLeft, childPaddingTop, childPaddingRight, childPaddingBottom;
|
||||
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
final View child = getChildAt(i);
|
||||
if (child.getVisibility() == GONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fit and center the child within the parent. Make sure not to consider padding
|
||||
// as part of the child's aspect ratio.
|
||||
|
||||
childPaddingLeft = child.getPaddingLeft();
|
||||
childPaddingTop = child.getPaddingTop();
|
||||
childPaddingRight = child.getPaddingRight();
|
||||
childPaddingBottom = child.getPaddingBottom();
|
||||
|
||||
unpaddedWidth = child.getMeasuredWidth() - childPaddingLeft - childPaddingRight;
|
||||
unpaddedHeight = child.getMeasuredHeight() - childPaddingTop - childPaddingBottom;
|
||||
|
||||
parentUnpaddedWidth = parentWidth - childPaddingLeft - childPaddingRight;
|
||||
parentUnpaddedHeight = parentHeight - childPaddingTop - childPaddingBottom;
|
||||
|
||||
if (parentUnpaddedWidth * unpaddedHeight > parentUnpaddedHeight * unpaddedWidth) {
|
||||
// The child view should be left/right letterboxed.
|
||||
final int scaledChildWidth = unpaddedWidth * parentUnpaddedHeight
|
||||
/ unpaddedHeight + childPaddingLeft + childPaddingRight;
|
||||
child.layout(
|
||||
parentLeft + (parentWidth - scaledChildWidth) / 2,
|
||||
parentTop,
|
||||
parentRight - (parentWidth - scaledChildWidth) / 2,
|
||||
parentBottom);
|
||||
} else {
|
||||
// The child view should be top/bottom letterboxed.
|
||||
final int scaledChildHeight = unpaddedHeight * parentUnpaddedWidth
|
||||
/ unpaddedWidth + childPaddingTop + childPaddingBottom;
|
||||
child.layout(
|
||||
parentLeft,
|
||||
parentTop + (parentHeight - scaledChildHeight) / 2,
|
||||
parentRight,
|
||||
parentTop + (parentHeight + scaledChildHeight) / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,15 @@ import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -39,9 +44,13 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class MainActivity extends Activity implements ActionBar.TabListener {
|
||||
|
||||
private static final int NOTIFICATION_DEFAULT = 1;
|
||||
private static final String ACTION_DIALOG = "com.example.android.hcgallery.action.DIALOG";
|
||||
|
||||
private View mActionBarView;
|
||||
private Animator mCurrentTitlesAnimator;
|
||||
private String[] mToggleLabels = {"Show Titles", "Hide Titles"};
|
||||
@@ -51,26 +60,18 @@ public class MainActivity extends Activity implements ActionBar.TabListener {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if(savedInstanceState != null && savedInstanceState.getInt("theme", -1) != -1) {
|
||||
mThemeId = savedInstanceState.getInt("theme");
|
||||
this.setTheme(mThemeId);
|
||||
}
|
||||
|
||||
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
Directory.initializeDirectory();
|
||||
|
||||
ActionBar bar = getActionBar();
|
||||
|
||||
if (mThemeId == android.R.style.Theme_Holo_Light || mThemeId == -1) {
|
||||
bar.setBackgroundDrawable(
|
||||
new ColorDrawable(getResources().getColor(R.color.actionbar_background_light)));
|
||||
} else {
|
||||
bar.setBackgroundDrawable(
|
||||
new ColorDrawable(getResources().getColor(R.color.actionbar_background_dark)));
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < Directory.getCategoryCount(); i++) {
|
||||
bar.addTab(bar.newTab().setText(Directory.getCategory(i).getName())
|
||||
@@ -122,21 +123,30 @@ public class MainActivity extends Activity implements ActionBar.TabListener {
|
||||
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;
|
||||
if (mThemeId == R.style.AppTheme_Dark) {
|
||||
mThemeId = R.style.AppTheme_Light;
|
||||
} else {
|
||||
mThemeId = android.R.style.Theme_Holo;
|
||||
mThemeId = R.style.AppTheme_Dark;
|
||||
}
|
||||
this.recreate();
|
||||
return true;
|
||||
|
||||
case R.id.showDialog:
|
||||
showDialog();
|
||||
showDialog("This is indeed an awesome dialog.");
|
||||
return true;
|
||||
|
||||
case R.id.showStandardNotification:
|
||||
showNotification(false);
|
||||
return true;
|
||||
|
||||
case R.id.showCustomNotification:
|
||||
showNotification(true);
|
||||
return true;
|
||||
|
||||
default:
|
||||
@@ -225,21 +235,84 @@ public class MainActivity extends Activity implements ActionBar.TabListener {
|
||||
mCurrentTitlesAnimator = objectAnimator;
|
||||
|
||||
invalidateOptionsMenu();
|
||||
|
||||
// Manually trigger onNewIntent to check for ACTION_DIALOG.
|
||||
onNewIntent(getIntent());
|
||||
}
|
||||
|
||||
void showDialog() {
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
if (ACTION_DIALOG.equals(intent.getAction())) {
|
||||
showDialog(intent.getStringExtra(Intent.EXTRA_TEXT));
|
||||
}
|
||||
}
|
||||
|
||||
void showDialog(String text) {
|
||||
// DialogFragment.show() will take care of adding the fragment
|
||||
// in a transaction. We also want to remove any currently showing
|
||||
// dialog, so make our own transaction and take care of that here.
|
||||
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
||||
|
||||
DialogFragment newFragment = MyDialogFragment.newInstance("The Dialog Of Awesome");
|
||||
DialogFragment newFragment = MyDialogFragment.newInstance(text);
|
||||
|
||||
// Create and show the dialog.
|
||||
// Show the dialog.
|
||||
newFragment.show(ft, "dialog");
|
||||
}
|
||||
|
||||
void showNotification(boolean custom) {
|
||||
final Resources res = getResources();
|
||||
final NotificationManager notificationManager = (NotificationManager) getSystemService(
|
||||
NOTIFICATION_SERVICE);
|
||||
|
||||
Notification.Builder builder = new Notification.Builder(this)
|
||||
.setSmallIcon(R.drawable.ic_stat_notify_example)
|
||||
.setAutoCancel(true)
|
||||
.setTicker(getString(R.string.notification_text))
|
||||
.setContentIntent(getDialogPendingIntent("Tapped the notification entry."));
|
||||
|
||||
if (custom) {
|
||||
// Sets a custom content view for the notification, including an image button.
|
||||
RemoteViews layout = new RemoteViews(getPackageName(), R.layout.notification);
|
||||
layout.setTextViewText(R.id.notification_title, getString(R.string.app_name));
|
||||
layout.setOnClickPendingIntent(R.id.notification_button,
|
||||
getDialogPendingIntent("Tapped the 'dialog' button in the notification."));
|
||||
builder.setContent(layout);
|
||||
|
||||
// Notifications in Android 3.0 now have a standard mechanism for displaying large
|
||||
// bitmaps such as contact avatars. Here, we load an example image and resize it to the
|
||||
// appropriate size for large bitmaps in notifications.
|
||||
Bitmap largeIconTemp = BitmapFactory.decodeResource(res,
|
||||
R.drawable.notification_default_largeicon);
|
||||
Bitmap largeIcon = Bitmap.createScaledBitmap(
|
||||
largeIconTemp,
|
||||
res.getDimensionPixelSize(android.R.dimen.notification_large_icon_width),
|
||||
res.getDimensionPixelSize(android.R.dimen.notification_large_icon_height),
|
||||
false);
|
||||
largeIconTemp.recycle();
|
||||
|
||||
builder.setLargeIcon(largeIcon);
|
||||
|
||||
} else {
|
||||
builder
|
||||
.setNumber(7) // An example number.
|
||||
.setContentTitle(getString(R.string.app_name))
|
||||
.setContentText(getString(R.string.notification_text));
|
||||
}
|
||||
|
||||
notificationManager.notify(NOTIFICATION_DEFAULT, builder.getNotification());
|
||||
}
|
||||
|
||||
PendingIntent getDialogPendingIntent(String dialogText) {
|
||||
return PendingIntent.getActivity(
|
||||
this,
|
||||
dialogText.hashCode(), // Otherwise previous PendingIntents with the same
|
||||
// requestCode may be overwritten.
|
||||
new Intent(ACTION_DIALOG)
|
||||
.putExtra(Intent.EXTRA_TEXT, dialogText)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
|
||||
0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
menu.getItem(1).setTitle(mToggleLabels[mLabelIndex]);
|
||||
@@ -261,24 +334,19 @@ public class MainActivity extends Activity implements ActionBar.TabListener {
|
||||
public static MyDialogFragment newInstance(String title) {
|
||||
MyDialogFragment frag = new MyDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("title", title);
|
||||
args.putString("text", title);
|
||||
frag.setArguments(args);
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
String title = getArguments().getString("title");
|
||||
String text = getArguments().getString("text");
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(title)
|
||||
.setPositiveButton("OK",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
}
|
||||
}
|
||||
)
|
||||
.setNegativeButton("Cancel",
|
||||
.setTitle("A Dialog of Awesome")
|
||||
.setMessage(text)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.ListFragment;
|
||||
import android.content.ClipData;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
@@ -28,6 +30,7 @@ import android.graphics.Paint;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextPaint;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
@@ -53,47 +56,40 @@ public class TitlesFragment extends ListFragment {
|
||||
populateTitles(mCategory);
|
||||
ListView lv = getListView();
|
||||
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
|
||||
selectPosition(mCurPosition);
|
||||
lv.setCacheColorHint(Color.WHITE);
|
||||
lv.setCacheColorHint(Color.TRANSPARENT);
|
||||
lv.setOnItemLongClickListener(new OnItemLongClickListener() {
|
||||
|
||||
public boolean onItemLongClick(AdapterView<?> av, View v, int pos,
|
||||
long id) {
|
||||
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, title), null, 0);
|
||||
v.startDrag(data, new MyDragShadowBuilder(v), null, 0);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
selectPosition(mCurPosition);
|
||||
}
|
||||
|
||||
private static class MyDragShadowBuilder extends View.DragShadowBuilder {
|
||||
private static Drawable mShadow;
|
||||
private static String mLabel;
|
||||
private static int mViewHeight;
|
||||
|
||||
public MyDragShadowBuilder(View v, String label) {
|
||||
private class MyDragShadowBuilder extends View.DragShadowBuilder {
|
||||
private Drawable mShadow;
|
||||
|
||||
public MyDragShadowBuilder(View v) {
|
||||
super(v);
|
||||
mShadow = new ColorDrawable(Color.BLUE);
|
||||
|
||||
final TypedArray a = v.getContext().obtainStyledAttributes(R.styleable.AppTheme);
|
||||
mShadow = a.getDrawable(R.styleable.AppTheme_listDragShadowBackground);
|
||||
mShadow.setCallback(v);
|
||||
mShadow.setBounds(0, 0, v.getWidth(), v.getHeight());
|
||||
mLabel = label;
|
||||
mViewHeight = v.getHeight();
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawShadow(Canvas canvas) {
|
||||
super.onDrawShadow(canvas);
|
||||
mShadow.draw(canvas);
|
||||
Paint paint = new TextPaint();
|
||||
paint.setTextSize(20);
|
||||
paint.setColor(Color.LTGRAY);
|
||||
paint.setTypeface(Typeface.DEFAULT_BOLD);
|
||||
paint.setAntiAlias(true);
|
||||
canvas.drawText(mLabel, 20, (float) (mViewHeight * .6), paint);
|
||||
getView().draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,13 +112,13 @@ public class TitlesFragment extends ListFragment {
|
||||
ContentFragment frag = (ContentFragment) getFragmentManager()
|
||||
.findFragmentById(R.id.frag_content);
|
||||
frag.updateContentAndRecycleBitmap(mCategory, position);
|
||||
mCurPosition = position;
|
||||
}
|
||||
|
||||
public void selectPosition(int position) {
|
||||
ListView lv = getListView();
|
||||
lv.setItemChecked(position, true);
|
||||
updateImage(position);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||