ActionBarSherlock 4.0.2

This commit is contained in:
Dominik 2012-04-20 12:14:21 +02:00
parent 784c3156df
commit da96aacf55
69 changed files with 2922 additions and 180 deletions

View File

@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="60" android:versionName="4.0.2" package="com.actionbarsherlock">
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.actionbarsherlock"
android:versionCode="50"
android:versionName="4.0.0">
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="15" />
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="15"/>
</manifest>

View File

@ -5,11 +5,11 @@ This folder contains the main library which should be linked against as an
Android library project in your application.
For more information see the "Including In Your Project" section of the
[download page][1].
[usage page][1].
[1]: http://actionbarsherlock.com/download.html
[1]: http://actionbarsherlock.com/usage.html

View File

@ -11,7 +11,7 @@
<parent>
<groupId>com.actionbarsherlock</groupId>
<artifactId>parent</artifactId>
<version>4.0.0</version>
<version>4.0.2</version>
<relativePath>../pom.xml</relativePath>
</parent>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 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_activated="true" android:drawable="@drawable/abs__list_activated_holo" />
<item android:drawable="@android:color/transparent" />
</selector>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2008 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_activated="true" android:drawable="@drawable/abs__list_activated_holo" />
<item android:drawable="@android:color/transparent" />
</selector>

View File

@ -14,8 +14,7 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/abs__btn_cab_done_pressed_holo_dark" />
<item android:state_focused="true" android:state_enabled="true"

View File

@ -14,8 +14,7 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/abs__btn_cab_done_pressed_holo_light" />
<item android:state_focused="true" android:state_enabled="true"

View File

@ -14,8 +14,7 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
<item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/abs__list_selector_disabled_holo_dark" />

View File

@ -14,8 +14,7 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
<item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/abs__list_selector_disabled_holo_light" />

View File

@ -14,8 +14,7 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:drawable="@android:color/transparent" />

View File

@ -14,8 +14,7 @@
limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_mediumAnimTime">
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:drawable="@android:color/transparent" />

View File

@ -18,6 +18,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:divider="?attr/dividerVertical"
android:divider="?attr/actionBarDivider"
android:dividerPadding="12dip"
android:gravity="center_vertical" />

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 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.
*/
-->
<com.actionbarsherlock.internal.widget.IcsLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/abs__activity_chooser_view_content"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
style="?attr/activityChooserViewStyle">
<FrameLayout
android:id="@+id/abs__expand_activities_button"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:focusable="true"
android:addStatesFromChildren="true"
android:background="?attr/actionBarItemBackground">
<ImageView android:id="@+id/abs__image"
android:layout_width="56dip"
android:layout_height="36dip"
android:layout_gravity="center"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"
android:scaleType="fitCenter"
android:adjustViewBounds="true" />
</FrameLayout>
<FrameLayout
android:id="@+id/abs__default_activity_button"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:focusable="true"
android:addStatesFromChildren="true"
android:background="?attr/actionBarItemBackground">
<ImageView android:id="@+id/abs__image"
android:layout_width="56dip"
android:layout_height="36dip"
android:layout_gravity="center"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"
android:scaleType="fitCenter"
android:adjustViewBounds="true" />
</FrameLayout>
</com.actionbarsherlock.internal.widget.IcsLinearLayout>

View File

@ -0,0 +1,53 @@
<?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/abs__list_item"
android:layout_width="match_parent"
android:layout_height="?attr/dropdownListPreferredItemHeight"
android:paddingLeft="16dip"
android:paddingRight="16dip"
android:minWidth="196dip"
android:background="?attr/activatedBackgroundIndicator"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:duplicateParentState="true" >
<ImageView
android:id="@+id/abs__icon"
android:layout_width="32dip"
android:layout_height="32dip"
android:layout_gravity="center_vertical"
android:layout_marginRight="8dip"
android:duplicateParentState="true" />
<TextView
android:id="@+id/abs__title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textAppearance="?attr/textAppearanceLargePopupMenu"
android:duplicateParentState="true"
android:singleLine="true"
android:ellipsize="marquee"
android:fadingEdge="horizontal" />
</LinearLayout>
</LinearLayout>

View File

@ -19,10 +19,10 @@ This is an optimized layout for a screen with the Action Bar enabled.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:fitsSystemWindows="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
android:fitsSystemWindows="true">
<com.actionbarsherlock.internal.widget.ActionBarContainer
android:id="@+id/abs__action_bar_container"
android:layout_width="fill_parent"

View File

@ -19,38 +19,41 @@ This is an optimized layout for a screen with
the Action Bar enabled overlaying application content.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout android:id="@+id/abs__content"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.actionbarsherlock.internal.widget.ActionBarContainer android:id="@+id/abs__action_bar_container"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
style="?attr/actionBarStyle"
android:gravity="top">
<com.actionbarsherlock.internal.widget.ActionBarView
android:id="@+id/abs__action_bar"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="?attr/actionBarStyle" />
<com.actionbarsherlock.internal.widget.ActionBarContextView
android:id="@+id/abs__action_context_bar"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
style="?attr/actionModeStyle" />
</com.actionbarsherlock.internal.widget.ActionBarContainer>
<ImageView android:src="?attr/windowContentOverlay"
android:scaleType="fitXY"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/abs__action_bar_container" />
<com.actionbarsherlock.internal.widget.ActionBarContainer android:id="@+id/abs__split_action_bar"
android:layout_width="fill_parent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
style="?attr/actionBarSplitStyle"
android:visibility="gone"
android:gravity="center"/>
</RelativeLayout>
</FrameLayout>

View File

@ -21,6 +21,8 @@ enabled.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.actionbarsherlock.internal.nineoldandroids.widget.NineFrameLayout
android:id="@+id/abs__content"

View File

@ -10,6 +10,10 @@
<item name="actionBarSize">?android:attr/actionBarSize</item>
<!-- Needed for our bug-fix dropdown list navigation layout. :( -->
<item name="dropdownListPreferredItemHeight">48dp</item>
<!-- Needed for our ShareActionProvider implementation. -->
<item name="android:actionBarWidgetTheme">@style/Theme.Sherlock</item>
<!-- For crazy people who use IcsSpinner. -->
<item name="dropDownListViewStyle">?android:attr/dropDownListViewStyle</item>
</style>
<style name="Theme.Sherlock.NoActionBar">

View File

@ -60,6 +60,8 @@
<attr name="actionModeSplitBackground" format="reference" />
<!-- Drawable to use for the close action mode button -->
<attr name="actionModeCloseDrawable" format="reference" />
<!-- Drawable to use for the Share action button in WebView selection action modes -->
<attr name="actionModeShareDrawable" format="reference" />
<!-- PopupWindow style to use for action modes when showing as a window overlay. -->
<attr name="actionModePopupWindowStyle" format="reference" />
@ -133,6 +135,15 @@
<attr name="windowActionModeOverlay" format="boolean"/>
<attr name="windowSplitActionBar" format="boolean" />
<attr name="listPopupWindowStyle" format="reference" />
<!-- Default ActivityChooserView style. -->
<attr name="activityChooserViewStyle" format="reference" />
<!-- Drawable used as a background for activated items. -->
<attr name="activatedBackgroundIndicator" format="reference" />
<!-- Specified if we are forcing an action item overflow menu. -->
<attr name="absForceOverflow" format="boolean" />
@ -234,6 +245,20 @@
<attr name="android:minWidth" />
</declare-styleable>
<declare-styleable name="SherlockActivityChooserView">
<!-- The maximal number of items initially shown in the activity list. -->
<attr name="initialActivityCount" format="string" />
<!-- The drawable to show in the button for expanding the activities overflow popup.
<strong>Note:</strong> Clients would like to set this drawable
as a clue about the action the chosen activity will perform. For
example, if share activity is to be chosen the drawable should
give a clue that sharing is to be performed.
-->
<attr name="expandActivityOverflowButtonDrawable" format="reference" />
<attr name="android:background" />
</declare-styleable>
<!-- Base attributes that are available to all groups. -->
<declare-styleable name="SherlockMenuGroup">

View File

@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
<resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Content description for the action bar "home" affordance. [CHAR LIMIT=NONE] -->
<string name="abs__action_bar_home_description">Navigate home</string>
<!-- Content description for the action bar "up" affordance. [CHAR LIMIT=NONE] -->
@ -26,4 +26,17 @@
<!-- Label for the "Done" button on the far left of action mode toolbars. -->
<string name="abs__action_mode_done">Done</string>
<!-- Title for a button to expand the list of activities in ActivityChooserView [CHAR LIMIT=25] -->
<string name="abs__activity_chooser_view_see_all">See all...</string>
<!-- Title default for a dialog showing possible activities in ActivityChooserView [CHAR LIMIT=25] -->
<string name="abs__activity_chooser_view_dialog_title_default">Select activity</string>
<!-- Title for a dialog showing possible activities for sharing in ShareActionProvider [CHAR LIMIT=25] -->
<string name="abs__share_action_provider_share_with">Share with...</string>
<!-- Description of the shwoing of a popup window with activities to choose from. [CHAR LIMIT=NONE] -->
<string name="abs__activitychooserview_choose_application">Choose an application</string>
<!-- Description of the choose target button in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] -->
<string name="abs__shareactionprovider_share_with">Share with</string>
<!-- Description of a share target (both in the list of such or the default share button) in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] -->
<string name="abs__shareactionprovider_share_with_application">Share with <xliff:g id="application_name" example="Bluetooth">%s</xliff:g></string>
</resources>

View File

@ -74,7 +74,7 @@
<style name="Widget.Sherlock.ActionBar.TabView" parent="Widget">
<item name="android:gravity">center_horizontal</item>
<item name="android:background">@drawable/abs__tab_indicator_holo</item>
<item name="android:background">@drawable/abs__tab_indicator_ab_holo</item>
<item name="android:paddingLeft">16dip</item>
<item name="android:paddingRight">16dip</item>
</style>
@ -112,7 +112,7 @@
<item name="android:background">?attr/actionBarItemBackground</item>
<item name="android:minHeight">?attr/actionBarSize</item>
<item name="android:minWidth">56dip</item>
<item name="android:minWidth">@dimen/abs__action_button_min_width</item>
<item name="android:gravity">center</item>
<item name="android:paddingLeft">12dip</item>
<item name="android:paddingRight">12dip</item>
@ -156,20 +156,51 @@
</style>
<style name="Widget.Sherlock.PopupMenu" parent="Widget">
<style name="Widget.Sherlock.ListPopupWindow" parent="Widget">
<item name="android:dropDownSelector">@drawable/abs__list_selector_holo_dark</item>
<item name="android:popupBackground">@drawable/abs__menu_dropdown_panel_holo_dark</item>
<item name="android:dropDownVerticalOffset">0dip</item>
<item name="android:dropDownHorizontalOffset">0dip</item>
<item name="android:dropDownWidth">wrap_content</item>
</style>
<style name="Widget.Sherlock.Light.PopupMenu" parent="Widget">
<style name="Widget.Sherlock.Light.ListPopupWindow" parent="Widget">
<item name="android:dropDownSelector">@drawable/abs__list_selector_holo_light</item>
<item name="android:popupBackground">@drawable/abs__menu_dropdown_panel_holo_light</item>
<item name="android:dropDownVerticalOffset">0dip</item>
<item name="android:dropDownHorizontalOffset">0dip</item>
<item name="android:dropDownWidth">wrap_content</item>
</style>
<style name="Widget.Sherlock.PopupMenu" parent="Widget.Sherlock.ListPopupWindow">
</style>
<style name="Widget.Sherlock.Light.PopupMenu" parent="Widget.Sherlock.Light.ListPopupWindow">
</style>
<style name="Sherlock.__Widget.ActivityChooserView" parent="Widget">
<item name="android:gravity">center</item>
<item name="android:background">@drawable/abs__ab_share_pack_holo_dark</item>
<item name="android:divider">?attr/dividerVertical</item>
<item name="android:showDividers">middle</item>
<item name="android:dividerPadding">6dip</item>
</style>
<style name="Widget.Sherlock.ActivityChooserView" parent="Sherlock.__Widget.ActivityChooserView">
</style>
<style name="Widget.Sherlock.Light.ActivityChooserView" parent="Widget.Sherlock.ActivityChooserView">
<item name="android:background">@drawable/abs__ab_share_pack_holo_light</item>
</style>
<style name="Widget.Sherlock.Button.Small" parent="Widget">
<item name="android:textAppearance">?attr/textAppearanceSmall</item>
<item name="android:textColor">@color/abs__primary_text_holo_dark</item>
<item name="android:minHeight">48dip</item>
<item name="android:minWidth">48dip</item>
</style>
<style name="Widget.Sherlock.Light.Button.Small" parent="Widget">
<item name="android:textAppearance">?attr/textAppearanceSmall</item>
<item name="android:textColor">@color/abs__primary_text_holo_light</item>
<item name="android:minHeight">48dip</item>
<item name="android:minWidth">48dip</item>
</style>
<style name="Sherlock.__Widget.Holo.Spinner" parent="Widget">
@ -341,4 +372,13 @@
<item name="android:textSize">22sp</item>
<item name="android:textColor">@color/abs__holo_blue_light</item>
</style>
<style name="Sherlock.__TextAppearance.Small" parent="Widget">
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Sherlock.Small" parent="Sherlock.__TextAppearance.Small">
</style>
<style name="TextAppearance.Sherlock.Light.Small" parent="TextAppearance.Sherlock.Small">
</style>
</resources>

View File

@ -37,6 +37,12 @@
<item name="actionBarDivider">?attr/dividerVertical</item>
<item name="actionBarItemBackground">@drawable/abs__item_background_holo_dark</item>
<item name="buttonStyleSmall">@style/Widget.Sherlock.Button.Small</item>
<item name="activatedBackgroundIndicator">@drawable/abs__activated_background_holo_dark</item>
<item name="actionModeShareDrawable">@drawable/abs__ic_menu_share_holo_dark</item>
<item name="activityChooserViewStyle">@style/Widget.Sherlock.ActivityChooserView</item>
<item name="homeAsUpIndicator">@drawable/abs__ic_ab_back_holo_dark</item>
<item name="dividerVertical">@drawable/abs__list_divider_holo_dark</item>
@ -51,10 +57,12 @@
<!-- Internal --><item name="dropdownListPreferredItemHeight">48dip</item>
<item name="dropDownListViewStyle">@style/Widget.Sherlock.ListView.DropDown</item>
<item name="textAppearanceSmall">@style/TextAppearance.Sherlock.Small</item>
<item name="textAppearanceLargePopupMenu">@style/TextAppearance.Sherlock.Widget.PopupMenu.Large</item>
<item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Sherlock.Widget.PopupMenu.Small</item>
<item name="popupMenuStyle">@style/Widget.Sherlock.PopupMenu</item>
<!-- Internal --><item name="listPopupWindowStyle">@style/Widget.Sherlock.ListPopupWindow</item>
<item name="windowActionBar">true</item>
<item name="windowActionModeOverlay">false</item>
@ -85,6 +93,12 @@
<item name="actionBarDivider">?attr/dividerVertical</item>
<item name="actionBarItemBackground">@drawable/abs__item_background_holo_light</item>
<item name="buttonStyleSmall">@style/Widget.Sherlock.Light.Button.Small</item>
<item name="activatedBackgroundIndicator">@drawable/abs__activated_background_holo_light</item>
<item name="actionModeShareDrawable">@drawable/abs__ic_menu_share_holo_light</item>
<item name="activityChooserViewStyle">@style/Widget.Sherlock.Light.ActivityChooserView</item>
<item name="homeAsUpIndicator">@drawable/abs__ic_ab_back_holo_light</item>
<item name="dividerVertical">@drawable/abs__list_divider_holo_light</item>
@ -99,10 +113,12 @@
<!-- Internal --><item name="dropdownListPreferredItemHeight">48dip</item>
<item name="dropDownListViewStyle">@style/Widget.Sherlock.Light.ListView.DropDown</item>
<item name="textAppearanceSmall">@style/TextAppearance.Sherlock.Light.Small</item>
<item name="textAppearanceLargePopupMenu">@style/TextAppearance.Sherlock.Light.Widget.PopupMenu.Large</item>
<item name="textAppearanceSmallPopupMenu">@style/TextAppearance.Sherlock.Light.Widget.PopupMenu.Small</item>
<item name="popupMenuStyle">@style/Widget.Sherlock.Light.PopupMenu</item>
<!-- Internal --><item name="listPopupWindowStyle">@style/Widget.Sherlock.Light.ListPopupWindow</item>
<item name="windowActionBar">true</item>
<item name="windowActionModeOverlay">false</item>
@ -125,10 +141,12 @@
<item name="actionBarTabTextStyle">@style/Widget.Sherlock.Light.ActionBar.TabText.Inverse</item>
<item name="actionBarDivider">@drawable/abs__list_divider_holo_dark</item>
<item name="actionBarItemBackground">@drawable/abs__item_background_holo_dark</item>
<item name="actionMenuTextColor">?android:attr/textColorPrimaryInverse</item>
<item name="actionMenuTextColor">?attr/textColorPrimaryInverse</item>
<item name="actionModeStyle">@style/Widget.Sherlock.Light.ActionMode.Inverse</item>
<item name="actionModeCloseButtonStyle">@style/Widget.Sherlock.ActionButton.CloseMode</item>
<item name="actionModePopupWindowStyle">@style/Widget.Sherlock.PopupWindow.ActionMode</item>
<item name="actionModeShareDrawable">@drawable/abs__ic_menu_share_holo_dark</item>
</style>

View File

@ -37,7 +37,6 @@ import com.actionbarsherlock.view.MenuItem;
* counterpart and you should refer to its documentation for instruction.</p>
*
* @author Jake Wharton <jakewharton@gmail.com>
* @version 4.0.0
*/
public abstract class ActionBarSherlock {
protected static final String TAG = "ActionBarSherlock";

View File

@ -34,7 +34,9 @@ public class SherlockDialogFragment extends DialogFragment {
if (DEBUG) Log.d(TAG, "[onCreateOptionsMenu] menu: " + menu + ", inflater: " + inflater);
if (menu instanceof MenuMule) {
onCreateOptionsMenu(((MenuMule)menu).unwrap(), mActivity.getSupportMenuInflater());
MenuMule mule = (MenuMule)menu;
mule.mDispatchShow = true;
onCreateOptionsMenu(mule.unwrap(), mActivity.getSupportMenuInflater());
}
}
@ -47,7 +49,9 @@ public class SherlockDialogFragment extends DialogFragment {
if (DEBUG) Log.d(TAG, "[onPrepareOptionsMenu] menu: " + menu);
if (menu instanceof MenuMule) {
onPrepareOptionsMenu(((MenuMule)menu).unwrap());
MenuMule mule = (MenuMule)menu;
mule.mDispatchShow = true;
onPrepareOptionsMenu(mule.unwrap());
}
}

View File

@ -34,7 +34,9 @@ public class SherlockFragment extends Fragment {
if (DEBUG) Log.d(TAG, "[onCreateOptionsMenu] menu: " + menu + ", inflater: " + inflater);
if (menu instanceof MenuMule) {
onCreateOptionsMenu(((MenuMule)menu).unwrap(), mActivity.getSupportMenuInflater());
MenuMule mule = (MenuMule)menu;
mule.mDispatchShow = true;
onCreateOptionsMenu(mule.unwrap(), mActivity.getSupportMenuInflater());
}
}
@ -47,7 +49,9 @@ public class SherlockFragment extends Fragment {
if (DEBUG) Log.d(TAG, "[onPrepareOptionsMenu] menu: " + menu);
if (menu instanceof MenuMule) {
onPrepareOptionsMenu(((MenuMule)menu).unwrap());
MenuMule mule = (MenuMule)menu;
mule.mDispatchShow = true;
onPrepareOptionsMenu(mule.unwrap());
}
}

View File

@ -1,7 +1,6 @@
package com.actionbarsherlock.app;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
@ -30,7 +29,6 @@ public abstract class SherlockFragmentActivity extends FragmentActivity implemen
private boolean mIgnoreNativeCreate = false;
private boolean mIgnoreNativePrepare = false;
private boolean mIgnoreNativeSelected = false;
private Boolean mOverrideNativeCreate = null;
protected final ActionBarSherlock getSherlock() {
if (mSherlock == null) {
@ -138,7 +136,7 @@ public abstract class SherlockFragmentActivity extends FragmentActivity implemen
getSherlock().dispatchInvalidateOptionsMenu();
}
protected void supportInvalidateOptionsMenu() {
public void supportInvalidateOptionsMenu() {
if (DEBUG) Log.d(TAG, "[supportInvalidateOptionsMenu]");
invalidateOptionsMenu();
@ -161,7 +159,7 @@ public abstract class SherlockFragmentActivity extends FragmentActivity implemen
@Override
public final boolean onCreateOptionsMenu(android.view.Menu menu) {
return (mOverrideNativeCreate != null) ? mOverrideNativeCreate.booleanValue() : true;
return true;
}
@Override
@ -229,19 +227,17 @@ public abstract class SherlockFragmentActivity extends FragmentActivity implemen
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
boolean result = onCreateOptionsMenu(menu);
if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] activity create result: " + result);
//Dispatch to parent panel creation for fragment dispatching
if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] dispatching to native with mule");
mOverrideNativeCreate = result;
boolean fragResult = super.onCreatePanelMenu(featureId, new MenuMule(menu));
mOverrideNativeCreate = null;
MenuMule mule = new MenuMule(menu);
super.onCreatePanelMenu(featureId, mule);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
result |= menu.hasVisibleItems();
} else {
result |= fragResult;
}
if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] fragments create result: " + mule.mDispatchShow);
result |= mule.mDispatchShow;
if (DEBUG) Log.d(TAG, "[onCreatePanelMenu] returning " + result);
return result;
}
return false;
@ -257,11 +253,18 @@ public abstract class SherlockFragmentActivity extends FragmentActivity implemen
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
boolean result = onPrepareOptionsMenu(menu);
if (DEBUG) Log.d(TAG, "[onPreparePanel] activity prepare result: " + result);
//Dispatch to parent panel preparation for fragment dispatching
if (DEBUG) Log.d(TAG, "[onPreparePanel] dispatching to native with mule");
super.onPreparePanel(featureId, view, new MenuMule(menu));
MenuMule mule = new MenuMule(menu);
super.onPreparePanel(featureId, view, mule);
if (DEBUG) Log.d(TAG, "[onPreparePanel] fragments prepare result: " + mule.mDispatchShow);
result |= mule.mDispatchShow;
result &= menu.hasVisibleItems();
if (DEBUG) Log.d(TAG, "[onPreparePanel] returning " + result);
return result;
}
return false;
@ -276,13 +279,13 @@ public abstract class SherlockFragmentActivity extends FragmentActivity implemen
if (DEBUG) Log.d(TAG, "[onMenuItemSelected] featureId: " + featureId + ", item: " + item);
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
boolean result = onOptionsItemSelected(item);
if (onOptionsItemSelected(item)) {
return true;
}
//Dispatch to parent panel selection for fragment dispatching
if (DEBUG) Log.d(TAG, "[onMenuItemSelected] dispatching to native with mule");
result |= super.onMenuItemSelected(featureId, new MenuItemMule(item));
return result;
return super.onMenuItemSelected(featureId, new MenuItemMule(item));
}
return false;
}

View File

@ -34,7 +34,9 @@ public class SherlockListFragment extends ListFragment {
if (DEBUG) Log.d(TAG, "[onCreateOptionsMenu] menu: " + menu + ", inflater: " + inflater);
if (menu instanceof MenuMule) {
onCreateOptionsMenu(((MenuMule)menu).unwrap(), mActivity.getSupportMenuInflater());
MenuMule mule = (MenuMule)menu;
mule.mDispatchShow = true;
onCreateOptionsMenu(mule.unwrap(), mActivity.getSupportMenuInflater());
}
}
@ -47,7 +49,9 @@ public class SherlockListFragment extends ListFragment {
if (DEBUG) Log.d(TAG, "[onPrepareOptionsMenu] menu: " + menu);
if (menu instanceof MenuMule) {
onPrepareOptionsMenu(((MenuMule)menu).unwrap());
MenuMule mule = (MenuMule)menu;
mule.mDispatchShow = true;
onPrepareOptionsMenu(mule.unwrap());
}
}

View File

@ -71,6 +71,8 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu
private MenuBuilder mMenu;
/** Map between native options items and sherlock items. */
protected HashMap<android.view.MenuItem, MenuItemImpl> mNativeItemMap;
/** Indication of a long-press on the hardware menu key. */
private boolean mMenuKeyIsLongPress = false;
/** Parent view of the window decoration (action bar, mode, etc.). */
private ViewGroup mDecor;
@ -318,6 +320,10 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu
public boolean dispatchPrepareOptionsMenu(android.view.Menu menu) {
if (DEBUG) Log.d(TAG, "[dispatchPrepareOptionsMenu] android.view.Menu: " + menu);
if (mActionMode != null) {
return false;
}
mMenuIsPrepared = false;
if (!preparePanel()) {
return false;
@ -416,7 +422,12 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu
}
}
if (keyCode == KeyEvent.KEYCODE_MENU && event.getAction() == KeyEvent.ACTION_UP && isReservingOverflow()) {
boolean result = false;
if (keyCode == KeyEvent.KEYCODE_MENU && isReservingOverflow()) {
if (event.getAction() == KeyEvent.ACTION_DOWN && event.isLongPress()) {
mMenuKeyIsLongPress = true;
} else if (event.getAction() == KeyEvent.ACTION_UP) {
if (!mMenuKeyIsLongPress) {
if (mActionMode == null) {
if (wActionBar.isOverflowMenuShowing()) {
wActionBar.hideOverflowMenu();
@ -424,12 +435,14 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu
wActionBar.showOverflowMenu();
}
}
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning true");
return true;
result = true;
}
mMenuKeyIsLongPress = false;
}
}
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning false");
return false;
if (DEBUG) Log.d(TAG, "[dispatchKeyEvent] returning " + result);
return result;
}
@ -964,7 +977,7 @@ public class ActionBarSherlockCompat extends ActionBarSherlock implements MenuBu
@Override
public void run() {
//Invalidate if the panel menu hasn't been created before this.
if (mMenu == null) {
if (!mActivity.isFinishing() && mMenu == null) {
dispatchInvalidateOptionsMenu();
}
}

View File

@ -314,5 +314,15 @@ public class ActionBarSherlockNative extends ActionBarSherlock {
public MenuInflater getMenuInflater() {
return ActionBarSherlockNative.this.getMenuInflater();
}
@Override
public void setTag(Object tag) {
mActionMode.setTag(tag);
}
@Override
public Object getTag() {
return mActionMode.getTag();
}
}
}

View File

@ -335,6 +335,12 @@ public class ActionBarWrapper extends ActionBar implements android.app.ActionBar
@Override
public void onTabSelected(android.app.ActionBar.Tab tab, android.app.FragmentTransaction ft) {
if (mListener != null) {
if (mFragmentTransaction == null && mActivity instanceof SherlockFragmentActivity) {
mFragmentTransaction = ((SherlockFragmentActivity)mActivity).getSupportFragmentManager().beginTransaction()
.disallowAddToBackStack();
}
mListener.onTabSelected(this, mFragmentTransaction);
if (mFragmentTransaction != null) {

View File

@ -947,7 +947,7 @@ public final class AnimatorSet extends Animator {
public Node clone() {
try {
Node node = (Node) super.clone();
node.animation = (Animator) animation.clone();
node.animation = animation.clone();
return node;
} catch (CloneNotSupportedException e) {
throw new AssertionError();

View File

@ -256,7 +256,7 @@ public class PropertyValuesHolder implements Cloneable {
else {
PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName);
pvh.mKeyframeSet = keyframeSet;
pvh.mValueType = ((Keyframe)values[0]).getType();
pvh.mValueType = values[0].getType();
return pvh;
}
}
@ -336,9 +336,9 @@ public class PropertyValuesHolder implements Cloneable {
public void setKeyframes(Keyframe... values) {
int numKeyframes = values.length;
Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)];
mValueType = ((Keyframe)values[0]).getType();
mValueType = values[0].getType();
for (int i = 0; i < numKeyframes; ++i) {
keyframes[i] = (Keyframe)values[i];
keyframes[i] = values[i];
}
mKeyframeSet = new KeyframeSet(keyframes);
}

View File

@ -458,7 +458,7 @@ public class ValueAnimator extends Animator {
mValues = values;
mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
for (int i = 0; i < numValues; ++i) {
PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
PropertyValuesHolder valuesHolder = values[i];
mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
}
// New property/values/target should cause re-initialization prior to starting

View File

@ -0,0 +1,41 @@
package com.actionbarsherlock.internal.nineoldandroids.widget;
import android.content.Context;
import android.widget.HorizontalScrollView;
import com.actionbarsherlock.internal.nineoldandroids.view.animation.AnimatorProxy;
public class NineHorizontalScrollView extends HorizontalScrollView {
private final AnimatorProxy mProxy;
public NineHorizontalScrollView(Context context) {
super(context);
mProxy = AnimatorProxy.NEEDS_PROXY ? AnimatorProxy.wrap(this) : null;
}
@Override
public void setVisibility(int visibility) {
if (mProxy != null) {
if (visibility == GONE) {
clearAnimation();
} else if (visibility == VISIBLE) {
setAnimation(mProxy);
}
}
super.setVisibility(visibility);
}
public float getAlpha() {
if (AnimatorProxy.NEEDS_PROXY) {
return mProxy.getAlpha();
} else {
return super.getAlpha();
}
}
public void setAlpha(float alpha) {
if (AnimatorProxy.NEEDS_PROXY) {
mProxy.setAlpha(alpha);
} else {
super.setAlpha(alpha);
}
}
}

View File

@ -130,7 +130,13 @@ public class ActionMenuPresenter extends BaseMenuPresenter
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB);
} else {
return !ViewConfiguration.get(context).hasPermanentMenuKey();
return !HasPermanentMenuKey.get(context);
}
}
private static class HasPermanentMenuKey {
public static boolean get(Context context) {
return ViewConfiguration.get(context).hasPermanentMenuKey();
}
}
@ -299,7 +305,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
*/
public boolean showOverflowMenu() {
if (mReserveOverflow && !isOverflowMenuShowing() && mMenu != null && mMenuView != null &&
mPostedOpenRunnable == null) {
mPostedOpenRunnable == null && !mMenu.getNonActionItems().isEmpty()) {
OverflowPopup popup = new OverflowPopup(mContext, mMenu, mOverflowButton, true);
mPostedOpenRunnable = new OpenOverflowRunnable(popup);
// Post this for later; we might still need a layout for the anchor to be right.

View File

@ -417,9 +417,9 @@ public class ActionMenuView extends IcsLinearLayout implements MenuBuilder.ItemI
final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
//UNUSED nonOverflowWidth += size;
widthRemaining -= size;
if (hasDividerBeforeChildAt(i)) {
//if (hasDividerBeforeChildAt(i)) {
//UNUSED nonOverflowWidth += dividerWidth;
}
//}
nonOverflowCount++;
}
}

View File

@ -9,11 +9,12 @@ import com.actionbarsherlock.view.ActionProvider;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SubMenu;
public class MenuItemWrapper implements MenuItem, android.view.MenuItem.OnMenuItemClickListener, android.view.MenuItem.OnActionExpandListener {
public class MenuItemWrapper implements MenuItem, android.view.MenuItem.OnMenuItemClickListener {
private final android.view.MenuItem mNativeItem;
private SubMenu mSubMenu = null;
private OnMenuItemClickListener mMenuItemClickListener = null;
private OnActionExpandListener mActionExpandListener = null;
private android.view.MenuItem.OnActionExpandListener mNativeActionExpandListener = null;
public MenuItemWrapper(android.view.MenuItem nativeItem) {
@ -262,24 +263,30 @@ public class MenuItemWrapper implements MenuItem, android.view.MenuItem.OnMenuIt
@Override
public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
mActionExpandListener = listener;
//Register ourselves as the listener to proxy
mNativeItem.setOnActionExpandListener(this);
if (mNativeActionExpandListener == null) {
mNativeActionExpandListener = new android.view.MenuItem.OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(android.view.MenuItem menuItem) {
if (mActionExpandListener != null) {
return mActionExpandListener.onMenuItemActionExpand(MenuItemWrapper.this);
}
return false;
}
@Override
public boolean onMenuItemActionCollapse(android.view.MenuItem menuItem) {
if (mActionExpandListener != null) {
return mActionExpandListener.onMenuItemActionCollapse(MenuItemWrapper.this);
}
return false;
}
};
//Register our inner-class as the listener to proxy method calls
mNativeItem.setOnActionExpandListener(mNativeActionExpandListener);
}
return this;
}
@Override
public boolean onMenuItemActionCollapse(android.view.MenuItem item) {
if (mActionExpandListener != null) {
return mActionExpandListener.onMenuItemActionCollapse(this);
}
return false;
}
@Override
public boolean onMenuItemActionExpand(android.view.MenuItem item) {
if (mActionExpandListener != null) {
return mActionExpandListener.onMenuItemActionExpand(this);
}
return false;
}
}

View File

@ -15,6 +15,7 @@ public class MenuMule implements Menu {
private final com.actionbarsherlock.view.Menu mMenu;
public boolean mDispatchShow = false;
public MenuMule(com.actionbarsherlock.view.Menu menu) {
mMenu = menu;

View File

@ -132,7 +132,7 @@ public class ActionBarView extends AbsActionBarView {
private SpinnerAdapter mSpinnerAdapter;
private OnNavigationListener mCallback;
private Runnable mTabSelector;
//UNUSED private Runnable mTabSelector;
private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
View mExpandedActionView;
@ -250,7 +250,7 @@ public class ActionBarView extends AbsActionBarView {
final int customNavId = a.getResourceId(R.styleable.SherlockActionBar_customNavigationLayout, 0);
if (customNavId != 0) {
mCustomNavView = (View) inflater.inflate(customNavId, this, false);
mCustomNavView = inflater.inflate(customNavId, this, false);
mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
setDisplayOptions(mDisplayOptions | ActionBar.DISPLAY_SHOW_CUSTOM);
}
@ -383,7 +383,7 @@ public class ActionBarView extends AbsActionBarView {
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
removeCallbacks(mTabSelector);
//UNUSED removeCallbacks(mTabSelector);
if (mActionMenuPresenter != null) {
mActionMenuPresenter.hideOverflowMenu();
mActionMenuPresenter.hideSubMenus();
@ -825,7 +825,7 @@ public class ActionBarView extends AbsActionBarView {
this, false);
mTitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_title);
mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.abs__action_bar_subtitle);
mTitleUpView = (View) mTitleLayout.findViewById(R.id.abs__up);
mTitleUpView = mTitleLayout.findViewById(R.id.abs__up);
mTitleLayout.setOnClickListener(mUpClickListener);

View File

@ -18,6 +18,10 @@ public class CapitalizingTextView extends TextView {
private boolean mAllCaps;
public CapitalizingTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CapitalizingTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

View File

@ -10,7 +10,10 @@ import com.actionbarsherlock.internal.nineoldandroids.widget.NineLinearLayout;
/**
* A simple extension of a regular linear layout that supports the divider API
* of Android 4.0+.
* of Android 4.0+. The dividers are added adjacent to the children by changing
* their layout params. If you need to rely on the margins which fall in the
* same orientation as the layout you should wrap the child in a simple
* {@link android.widget.FrameLayout} so it can receive the margin.
*/
public class IcsLinearLayout extends NineLinearLayout {
private static final int[] LinearLayout = new int[] {
@ -42,6 +45,7 @@ public class IcsLinearLayout extends NineLinearLayout {
private Drawable mDivider;
private int mDividerWidth;
private int mDividerHeight;
private int mShowDividers;
private int mDividerPadding;
@ -58,6 +62,29 @@ public class IcsLinearLayout extends NineLinearLayout {
a.recycle();
}
/**
* Set how dividers should be shown between items in this layout
*
* @param showDividers One or more of {@link #SHOW_DIVIDER_BEGINNING},
* {@link #SHOW_DIVIDER_MIDDLE}, or {@link #SHOW_DIVIDER_END},
* or {@link #SHOW_DIVIDER_NONE} to show no dividers.
*/
public void setShowDividers(int showDividers) {
if (showDividers != mShowDividers) {
requestLayout();
invalidate(); //XXX This is required if you are toggling a divider off
}
mShowDividers = showDividers;
}
/**
* @return A flag set indicating how dividers should be shown around items.
* @see #setShowDividers(int)
*/
public int getShowDividers() {
return mShowDividers;
}
/**
* Set a drawable to be used as a divider between items.
* @param divider Drawable that will divide each item.
@ -70,13 +97,39 @@ public class IcsLinearLayout extends NineLinearLayout {
mDivider = divider;
if (divider != null) {
mDividerWidth = divider.getIntrinsicWidth();
mDividerHeight = divider.getIntrinsicHeight();
} else {
mDividerWidth = 0;
mDividerHeight = 0;
}
setWillNotDraw(divider == null);
requestLayout();
}
/**
* Set padding displayed on both ends of dividers.
*
* @param padding Padding value in pixels that will be applied to each end
*
* @see #setShowDividers(int)
* @see #setDividerDrawable(Drawable)
* @see #getDividerPadding()
*/
public void setDividerPadding(int padding) {
mDividerPadding = padding;
}
/**
* Get the padding size used to inset dividers in pixels
*
* @see #setShowDividers(int)
* @see #setDividerDrawable(Drawable)
* @see #setDividerPadding(int)
*/
public int getDividerPadding() {
return mDividerPadding;
}
/**
* Get the width of the current divider drawable.
*
@ -89,9 +142,27 @@ public class IcsLinearLayout extends NineLinearLayout {
@Override
protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
final int index = indexOfChild(child);
final int orientation = getOrientation();
final LayoutParams params = (LayoutParams) child.getLayoutParams();
if (hasDividerBeforeChildAt(index)) {
if (orientation == VERTICAL) {
//Account for the divider by pushing everything up
params.topMargin = mDividerHeight;
} else {
//Account for the divider by pushing everything left
((LayoutParams)child.getLayoutParams()).leftMargin = mDividerWidth;
params.leftMargin = mDividerWidth;
}
}
final int count = getChildCount();
if (index == count - 1) {
if (hasDividerBeforeChildAt(count)) {
if (orientation == VERTICAL) {
params.bottomMargin = mDividerHeight;
} else {
params.rightMargin = mDividerWidth;
}
}
}
super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed);
}
@ -99,13 +170,51 @@ public class IcsLinearLayout extends NineLinearLayout {
@Override
protected void onDraw(Canvas canvas) {
if (mDivider != null) {
if (getOrientation() == VERTICAL) {
drawDividersVertical(canvas);
} else {
drawDividersHorizontal(canvas);
}
}
super.onDraw(canvas);
}
void drawDividersVertical(Canvas canvas) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child != null && child.getVisibility() != GONE) {
if (hasDividerBeforeChildAt(i)) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int left = child.getLeft() - lp.leftMargin;
final int top = child.getTop() - lp.topMargin/* - mDividerHeight*/;
drawHorizontalDivider(canvas, top);
}
}
}
if (hasDividerBeforeChildAt(count)) {
final View child = getChildAt(count - 1);
int bottom = 0;
if (child == null) {
bottom = getHeight() - getPaddingBottom() - mDividerHeight;
} else {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
bottom = child.getBottom()/* + lp.bottomMargin*/;
}
drawHorizontalDivider(canvas, bottom);
}
}
void drawDividersHorizontal(Canvas canvas) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child != null && child.getVisibility() != GONE) {
if (hasDividerBeforeChildAt(i)) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
final int left = child.getLeft() - lp.leftMargin/* - mDividerWidth*/;
drawVerticalDivider(canvas, left);
}
}
@ -118,13 +227,16 @@ public class IcsLinearLayout extends NineLinearLayout {
right = getWidth() - getPaddingRight() - mDividerWidth;
} else {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
right = child.getRight() + lp.rightMargin;
right = child.getRight()/* + lp.rightMargin*/;
}
drawVerticalDivider(canvas, right);
}
}
super.onDraw(canvas);
void drawHorizontalDivider(Canvas canvas, int top) {
mDivider.setBounds(getPaddingLeft() + mDividerPadding, top,
getWidth() - getPaddingRight() - mDividerPadding, top + mDividerHeight);
mDivider.draw(canvas);
}
void drawVerticalDivider(Canvas canvas, int left) {

View File

@ -74,6 +74,10 @@ public class IcsListPopupWindow {
public static final int POSITION_PROMPT_ABOVE = 0;
public static final int POSITION_PROMPT_BELOW = 1;
public IcsListPopupWindow(Context context) {
this(context, null, R.attr.listPopupWindowStyle);
}
public IcsListPopupWindow(Context context, AttributeSet attrs, int defStyleAttr) {
mContext = context;
mPopup = new PopupWindow(context, attrs, defStyleAttr);

View File

@ -78,6 +78,10 @@ public class IcsSpinner extends IcsAbsSpinner implements OnClickListener {
private Rect mTempRect = new Rect();
public IcsSpinner(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.actionDropDownStyle);
}
/**
* Construct a new spinner with the given context's theme, the supplied attribute set,
* and default style.

View File

@ -29,7 +29,6 @@ import android.view.ViewParent;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.BaseAdapter;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@ -37,12 +36,13 @@ import com.actionbarsherlock.R;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.internal.nineoldandroids.animation.Animator;
import com.actionbarsherlock.internal.nineoldandroids.animation.ObjectAnimator;
import com.actionbarsherlock.internal.nineoldandroids.widget.NineHorizontalScrollView;
/**
* This widget implements the dynamic action bar tab behavior that can change
* across different configurations or circumstances.
*/
public class ScrollingTabContainerView extends HorizontalScrollView
public class ScrollingTabContainerView extends NineHorizontalScrollView
implements IcsAdapterView.OnItemSelectedListener {
//UNUSED private static final String TAG = "ScrollingTabContainerView";
Runnable mTabSelector;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,818 @@
/*
* 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.actionbarsherlock.widget;
import android.os.Build;
import com.actionbarsherlock.R;
import com.actionbarsherlock.internal.widget.IcsLinearLayout;
import com.actionbarsherlock.internal.widget.IcsListPopupWindow;
import com.actionbarsherlock.view.ActionProvider;
import com.actionbarsherlock.widget.ActivityChooserModel.ActivityChooserModelClient;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
/**
* This class is a view for choosing an activity for handling a given {@link Intent}.
* <p>
* The view is composed of two adjacent buttons:
* <ul>
* <li>
* The left button is an immediate action and allows one click activity choosing.
* Tapping this button immediately executes the intent without requiring any further
* user input. Long press on this button shows a popup for changing the default
* activity.
* </li>
* <li>
* The right button is an overflow action and provides an optimized menu
* of additional activities. Tapping this button shows a popup anchored to this
* view, listing the most frequently used activities. This list is initially
* limited to a small number of items in frequency used order. The last item,
* "Show all..." serves as an affordance to display all available activities.
* </li>
* </ul>
* </p>
*
* @hide
*/
class ActivityChooserView extends ViewGroup implements ActivityChooserModelClient {
/**
* An adapter for displaying the activities in an {@link AdapterView}.
*/
private final ActivityChooserViewAdapter mAdapter;
/**
* Implementation of various interfaces to avoid publishing them in the APIs.
*/
private final Callbacks mCallbacks;
/**
* The content of this view.
*/
private final IcsLinearLayout mActivityChooserContent;
/**
* Stores the background drawable to allow hiding and latter showing.
*/
private final Drawable mActivityChooserContentBackground;
/**
* The expand activities action button;
*/
private final FrameLayout mExpandActivityOverflowButton;
/**
* The image for the expand activities action button;
*/
private final ImageView mExpandActivityOverflowButtonImage;
/**
* The default activities action button;
*/
private final FrameLayout mDefaultActivityButton;
/**
* The image for the default activities action button;
*/
private final ImageView mDefaultActivityButtonImage;
/**
* The maximal width of the list popup.
*/
private final int mListPopupMaxWidth;
/**
* The ActionProvider hosting this view, if applicable.
*/
ActionProvider mProvider;
/**
* Observer for the model data.
*/
private final DataSetObserver mModelDataSetOberver = new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
mAdapter.notifyDataSetChanged();
}
@Override
public void onInvalidated() {
super.onInvalidated();
mAdapter.notifyDataSetInvalidated();
}
};
private final OnGlobalLayoutListener mOnGlobalLayoutListener = new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (isShowingPopup()) {
if (!isShown()) {
getListPopupWindow().dismiss();
} else {
getListPopupWindow().show();
if (mProvider != null) {
mProvider.subUiVisibilityChanged(true);
}
}
}
}
};
/**
* Popup window for showing the activity overflow list.
*/
private IcsListPopupWindow mListPopupWindow;
/**
* Listener for the dismissal of the popup/alert.
*/
private PopupWindow.OnDismissListener mOnDismissListener;
/**
* Flag whether a default activity currently being selected.
*/
private boolean mIsSelectingDefaultActivity;
/**
* The count of activities in the popup.
*/
private int mInitialActivityCount = ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT;
/**
* Flag whether this view is attached to a window.
*/
private boolean mIsAttachedToWindow;
/**
* String resource for formatting content description of the default target.
*/
private int mDefaultActionButtonContentDescription;
private final Context mContext;
/**
* Create a new instance.
*
* @param context The application environment.
*/
public ActivityChooserView(Context context) {
this(context, null);
}
/**
* Create a new instance.
*
* @param context The application environment.
* @param attrs A collection of attributes.
*/
public ActivityChooserView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* Create a new instance.
*
* @param context The application environment.
* @param attrs A collection of attributes.
* @param defStyle The default style to apply to this view.
*/
public ActivityChooserView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
TypedArray attributesArray = context.obtainStyledAttributes(attrs,
R.styleable.SherlockActivityChooserView, defStyle, 0);
mInitialActivityCount = attributesArray.getInt(
R.styleable.SherlockActivityChooserView_initialActivityCount,
ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_DEFAULT);
Drawable expandActivityOverflowButtonDrawable = attributesArray.getDrawable(
R.styleable.SherlockActivityChooserView_expandActivityOverflowButtonDrawable);
attributesArray.recycle();
LayoutInflater inflater = LayoutInflater.from(mContext);
inflater.inflate(R.layout.abs__activity_chooser_view, this, true);
mCallbacks = new Callbacks();
mActivityChooserContent = (IcsLinearLayout) findViewById(R.id.abs__activity_chooser_view_content);
mActivityChooserContentBackground = mActivityChooserContent.getBackground();
mDefaultActivityButton = (FrameLayout) findViewById(R.id.abs__default_activity_button);
mDefaultActivityButton.setOnClickListener(mCallbacks);
mDefaultActivityButton.setOnLongClickListener(mCallbacks);
mDefaultActivityButtonImage = (ImageView) mDefaultActivityButton.findViewById(R.id.abs__image);
mExpandActivityOverflowButton = (FrameLayout) findViewById(R.id.abs__expand_activities_button);
mExpandActivityOverflowButton.setOnClickListener(mCallbacks);
mExpandActivityOverflowButtonImage =
(ImageView) mExpandActivityOverflowButton.findViewById(R.id.abs__image);
mExpandActivityOverflowButtonImage.setImageDrawable(expandActivityOverflowButtonDrawable);
mAdapter = new ActivityChooserViewAdapter();
mAdapter.registerDataSetObserver(new DataSetObserver() {
@Override
public void onChanged() {
super.onChanged();
updateAppearance();
}
});
Resources resources = context.getResources();
mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
resources.getDimensionPixelSize(R.dimen.abs__config_prefDialogWidth));
}
/**
* {@inheritDoc}
*/
public void setActivityChooserModel(ActivityChooserModel dataModel) {
mAdapter.setDataModel(dataModel);
if (isShowingPopup()) {
dismissPopup();
showPopup();
}
}
/**
* Sets the background for the button that expands the activity
* overflow list.
*
* <strong>Note:</strong> Clients would like to set this drawable
* as a clue about the action the chosen activity will perform. For
* example, if a share activity is to be chosen the drawable should
* give a clue that sharing is to be performed.
*
* @param drawable The drawable.
*/
public void setExpandActivityOverflowButtonDrawable(Drawable drawable) {
mExpandActivityOverflowButtonImage.setImageDrawable(drawable);
}
/**
* Sets the content description for the button that expands the activity
* overflow list.
*
* description as a clue about the action performed by the button.
* For example, if a share activity is to be chosen the content
* description should be something like "Share with".
*
* @param resourceId The content description resource id.
*/
public void setExpandActivityOverflowButtonContentDescription(int resourceId) {
CharSequence contentDescription = mContext.getString(resourceId);
mExpandActivityOverflowButtonImage.setContentDescription(contentDescription);
}
/**
* Set the provider hosting this view, if applicable.
* @hide Internal use only
*/
public void setProvider(ActionProvider provider) {
mProvider = provider;
}
/**
* Shows the popup window with activities.
*
* @return True if the popup was shown, false if already showing.
*/
public boolean showPopup() {
if (isShowingPopup() || !mIsAttachedToWindow) {
return false;
}
mIsSelectingDefaultActivity = false;
showPopupUnchecked(mInitialActivityCount);
return true;
}
/**
* Shows the popup no matter if it was already showing.
*
* @param maxActivityCount The max number of activities to display.
*/
private void showPopupUnchecked(int maxActivityCount) {
if (mAdapter.getDataModel() == null) {
throw new IllegalStateException("No data model. Did you call #setDataModel?");
}
getViewTreeObserver().addOnGlobalLayoutListener(mOnGlobalLayoutListener);
final boolean defaultActivityButtonShown =
mDefaultActivityButton.getVisibility() == VISIBLE;
final int activityCount = mAdapter.getActivityCount();
final int maxActivityCountOffset = defaultActivityButtonShown ? 1 : 0;
if (maxActivityCount != ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED
&& activityCount > maxActivityCount + maxActivityCountOffset) {
mAdapter.setShowFooterView(true);
mAdapter.setMaxActivityCount(maxActivityCount - 1);
} else {
mAdapter.setShowFooterView(false);
mAdapter.setMaxActivityCount(maxActivityCount);
}
IcsListPopupWindow popupWindow = getListPopupWindow();
if (!popupWindow.isShowing()) {
if (mIsSelectingDefaultActivity || !defaultActivityButtonShown) {
mAdapter.setShowDefaultActivity(true, defaultActivityButtonShown);
} else {
mAdapter.setShowDefaultActivity(false, false);
}
final int contentWidth = Math.min(mAdapter.measureContentWidth(), mListPopupMaxWidth);
popupWindow.setContentWidth(contentWidth);
popupWindow.show();
if (mProvider != null) {
mProvider.subUiVisibilityChanged(true);
}
popupWindow.getListView().setContentDescription(mContext.getString(
R.string.abs__activitychooserview_choose_application));
}
}
/**
* Dismisses the popup window with activities.
*
* @return True if dismissed, false if already dismissed.
*/
public boolean dismissPopup() {
if (isShowingPopup()) {
getListPopupWindow().dismiss();
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
}
}
return true;
}
/**
* Gets whether the popup window with activities is shown.
*
* @return True if the popup is shown.
*/
public boolean isShowingPopup() {
return getListPopupWindow().isShowing();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
if (dataModel != null) {
dataModel.registerObserver(mModelDataSetOberver);
}
mIsAttachedToWindow = true;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
if (dataModel != null) {
dataModel.unregisterObserver(mModelDataSetOberver);
}
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.removeGlobalOnLayoutListener(mOnGlobalLayoutListener);
}
mIsAttachedToWindow = false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View child = mActivityChooserContent;
// If the default action is not visible we want to be as tall as the
// ActionBar so if this widget is used in the latter it will look as
// a normal action button.
if (mDefaultActivityButton.getVisibility() != VISIBLE) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
MeasureSpec.EXACTLY);
}
measureChild(child, widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(child.getMeasuredWidth(), child.getMeasuredHeight());
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mActivityChooserContent.layout(0, 0, right - left, bottom - top);
if (getListPopupWindow().isShowing()) {
showPopupUnchecked(mAdapter.getMaxActivityCount());
} else {
dismissPopup();
}
}
public ActivityChooserModel getDataModel() {
return mAdapter.getDataModel();
}
/**
* Sets a listener to receive a callback when the popup is dismissed.
*
* @param listener The listener to be notified.
*/
public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
mOnDismissListener = listener;
}
/**
* Sets the initial count of items shown in the activities popup
* i.e. the items before the popup is expanded. This is an upper
* bound since it is not guaranteed that such number of intent
* handlers exist.
*
* @param itemCount The initial popup item count.
*/
public void setInitialActivityCount(int itemCount) {
mInitialActivityCount = itemCount;
}
/**
* Sets a content description of the default action button. This
* resource should be a string taking one formatting argument and
* will be used for formatting the content description of the button
* dynamically as the default target changes. For example, a resource
* pointing to the string "share with %1$s" will result in a content
* description "share with Bluetooth" for the Bluetooth activity.
*
* @param resourceId The resource id.
*/
public void setDefaultActionButtonContentDescription(int resourceId) {
mDefaultActionButtonContentDescription = resourceId;
}
/**
* Gets the list popup window which is lazily initialized.
*
* @return The popup.
*/
private IcsListPopupWindow getListPopupWindow() {
if (mListPopupWindow == null) {
mListPopupWindow = new IcsListPopupWindow(getContext());
mListPopupWindow.setAdapter(mAdapter);
mListPopupWindow.setAnchorView(ActivityChooserView.this);
mListPopupWindow.setModal(true);
mListPopupWindow.setOnItemClickListener(mCallbacks);
mListPopupWindow.setOnDismissListener(mCallbacks);
}
return mListPopupWindow;
}
/**
* Updates the buttons state.
*/
private void updateAppearance() {
// Expand overflow button.
if (mAdapter.getCount() > 0) {
mExpandActivityOverflowButton.setEnabled(true);
} else {
mExpandActivityOverflowButton.setEnabled(false);
}
// Default activity button.
final int activityCount = mAdapter.getActivityCount();
final int historySize = mAdapter.getHistorySize();
if (activityCount > 0 && historySize > 0) {
mDefaultActivityButton.setVisibility(VISIBLE);
ResolveInfo activity = mAdapter.getDefaultActivity();
PackageManager packageManager = mContext.getPackageManager();
mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
if (mDefaultActionButtonContentDescription != 0) {
CharSequence label = activity.loadLabel(packageManager);
String contentDescription = mContext.getString(
mDefaultActionButtonContentDescription, label);
mDefaultActivityButton.setContentDescription(contentDescription);
}
} else {
mDefaultActivityButton.setVisibility(View.GONE);
}
// Activity chooser content.
if (mDefaultActivityButton.getVisibility() == VISIBLE) {
mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
} else {
mActivityChooserContent.setBackgroundDrawable(null);
}
}
/**
* Interface implementation to avoid publishing them in the APIs.
*/
private class Callbacks implements AdapterView.OnItemClickListener,
View.OnClickListener, View.OnLongClickListener, PopupWindow.OnDismissListener {
// AdapterView#OnItemClickListener
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ActivityChooserViewAdapter adapter = (ActivityChooserViewAdapter) parent.getAdapter();
final int itemViewType = adapter.getItemViewType(position);
switch (itemViewType) {
case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_FOOTER: {
showPopupUnchecked(ActivityChooserViewAdapter.MAX_ACTIVITY_COUNT_UNLIMITED);
} break;
case ActivityChooserViewAdapter.ITEM_VIEW_TYPE_ACTIVITY: {
dismissPopup();
if (mIsSelectingDefaultActivity) {
// The item at position zero is the default already.
if (position > 0) {
mAdapter.getDataModel().setDefaultActivity(position);
}
} else {
// If the default target is not shown in the list, the first
// item in the model is default action => adjust index
position = mAdapter.getShowDefaultActivity() ? position : position + 1;
Intent launchIntent = mAdapter.getDataModel().chooseActivity(position);
if (launchIntent != null) {
mContext.startActivity(launchIntent);
}
}
} break;
default:
throw new IllegalArgumentException();
}
}
// View.OnClickListener
public void onClick(View view) {
if (view == mDefaultActivityButton) {
dismissPopup();
ResolveInfo defaultActivity = mAdapter.getDefaultActivity();
final int index = mAdapter.getDataModel().getActivityIndex(defaultActivity);
Intent launchIntent = mAdapter.getDataModel().chooseActivity(index);
if (launchIntent != null) {
mContext.startActivity(launchIntent);
}
} else if (view == mExpandActivityOverflowButton) {
mIsSelectingDefaultActivity = false;
showPopupUnchecked(mInitialActivityCount);
} else {
throw new IllegalArgumentException();
}
}
// OnLongClickListener#onLongClick
@Override
public boolean onLongClick(View view) {
if (view == mDefaultActivityButton) {
if (mAdapter.getCount() > 0) {
mIsSelectingDefaultActivity = true;
showPopupUnchecked(mInitialActivityCount);
}
} else {
throw new IllegalArgumentException();
}
return true;
}
// PopUpWindow.OnDismissListener#onDismiss
public void onDismiss() {
notifyOnDismissListener();
if (mProvider != null) {
mProvider.subUiVisibilityChanged(false);
}
}
private void notifyOnDismissListener() {
if (mOnDismissListener != null) {
mOnDismissListener.onDismiss();
}
}
}
private static class SetActivated {
public static void invoke(View view, boolean activated) {
view.setActivated(activated);
}
}
private static final boolean IS_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
/**
* Adapter for backing the list of activities shown in the popup.
*/
private class ActivityChooserViewAdapter extends BaseAdapter {
public static final int MAX_ACTIVITY_COUNT_UNLIMITED = Integer.MAX_VALUE;
public static final int MAX_ACTIVITY_COUNT_DEFAULT = 4;
private static final int ITEM_VIEW_TYPE_ACTIVITY = 0;
private static final int ITEM_VIEW_TYPE_FOOTER = 1;
private static final int ITEM_VIEW_TYPE_COUNT = 3;
private ActivityChooserModel mDataModel;
private int mMaxActivityCount = MAX_ACTIVITY_COUNT_DEFAULT;
private boolean mShowDefaultActivity;
private boolean mHighlightDefaultActivity;
private boolean mShowFooterView;
public void setDataModel(ActivityChooserModel dataModel) {
ActivityChooserModel oldDataModel = mAdapter.getDataModel();
if (oldDataModel != null && isShown()) {
oldDataModel.unregisterObserver(mModelDataSetOberver);
}
mDataModel = dataModel;
if (dataModel != null && isShown()) {
dataModel.registerObserver(mModelDataSetOberver);
}
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (mShowFooterView && position == getCount() - 1) {
return ITEM_VIEW_TYPE_FOOTER;
} else {
return ITEM_VIEW_TYPE_ACTIVITY;
}
}
@Override
public int getViewTypeCount() {
return ITEM_VIEW_TYPE_COUNT;
}
public int getCount() {
int count = 0;
int activityCount = mDataModel.getActivityCount();
if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
activityCount--;
}
count = Math.min(activityCount, mMaxActivityCount);
if (mShowFooterView) {
count++;
}
return count;
}
public Object getItem(int position) {
final int itemViewType = getItemViewType(position);
switch (itemViewType) {
case ITEM_VIEW_TYPE_FOOTER:
return null;
case ITEM_VIEW_TYPE_ACTIVITY:
if (!mShowDefaultActivity && mDataModel.getDefaultActivity() != null) {
position++;
}
return mDataModel.getActivity(position);
default:
throw new IllegalArgumentException();
}
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
final int itemViewType = getItemViewType(position);
switch (itemViewType) {
case ITEM_VIEW_TYPE_FOOTER:
if (convertView == null || convertView.getId() != ITEM_VIEW_TYPE_FOOTER) {
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.abs__activity_chooser_view_list_item, parent, false);
convertView.setId(ITEM_VIEW_TYPE_FOOTER);
TextView titleView = (TextView) convertView.findViewById(R.id.abs__title);
titleView.setText(mContext.getString(
R.string.abs__activity_chooser_view_see_all));
}
return convertView;
case ITEM_VIEW_TYPE_ACTIVITY:
if (convertView == null || convertView.getId() != R.id.abs__list_item) {
convertView = LayoutInflater.from(getContext()).inflate(
R.layout.abs__activity_chooser_view_list_item, parent, false);
}
PackageManager packageManager = mContext.getPackageManager();
// Set the icon
ImageView iconView = (ImageView) convertView.findViewById(R.id.abs__icon);
ResolveInfo activity = (ResolveInfo) getItem(position);
iconView.setImageDrawable(activity.loadIcon(packageManager));
// Set the title.
TextView titleView = (TextView) convertView.findViewById(R.id.abs__title);
titleView.setText(activity.loadLabel(packageManager));
if (IS_HONEYCOMB) {
// Highlight the default.
if (mShowDefaultActivity && position == 0 && mHighlightDefaultActivity) {
SetActivated.invoke(convertView, true);
} else {
SetActivated.invoke(convertView, false);
}
}
return convertView;
default:
throw new IllegalArgumentException();
}
}
public int measureContentWidth() {
// The user may have specified some of the target not to be shown but we
// want to measure all of them since after expansion they should fit.
final int oldMaxActivityCount = mMaxActivityCount;
mMaxActivityCount = MAX_ACTIVITY_COUNT_UNLIMITED;
int contentWidth = 0;
View itemView = null;
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int count = getCount();
for (int i = 0; i < count; i++) {
itemView = getView(i, itemView, null);
itemView.measure(widthMeasureSpec, heightMeasureSpec);
contentWidth = Math.max(contentWidth, itemView.getMeasuredWidth());
}
mMaxActivityCount = oldMaxActivityCount;
return contentWidth;
}
public void setMaxActivityCount(int maxActivityCount) {
if (mMaxActivityCount != maxActivityCount) {
mMaxActivityCount = maxActivityCount;
notifyDataSetChanged();
}
}
public ResolveInfo getDefaultActivity() {
return mDataModel.getDefaultActivity();
}
public void setShowFooterView(boolean showFooterView) {
if (mShowFooterView != showFooterView) {
mShowFooterView = showFooterView;
notifyDataSetChanged();
}
}
public int getActivityCount() {
return mDataModel.getActivityCount();
}
public int getHistorySize() {
return mDataModel.getHistorySize();
}
public int getMaxActivityCount() {
return mMaxActivityCount;
}
public ActivityChooserModel getDataModel() {
return mDataModel;
}
public void setShowDefaultActivity(boolean showDefaultActivity,
boolean highlightDefaultActivity) {
if (mShowDefaultActivity != showDefaultActivity
|| mHighlightDefaultActivity != highlightDefaultActivity) {
mShowDefaultActivity = showDefaultActivity;
mHighlightDefaultActivity = highlightDefaultActivity;
notifyDataSetChanged();
}
}
public boolean getShowDefaultActivity() {
return mShowDefaultActivity;
}
}
}

View File

@ -0,0 +1,316 @@
/*
* 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.actionbarsherlock.widget;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;
import com.actionbarsherlock.R;
import com.actionbarsherlock.view.ActionProvider;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.MenuItem.OnMenuItemClickListener;
import com.actionbarsherlock.view.SubMenu;
import com.actionbarsherlock.widget.ActivityChooserModel.OnChooseActivityListener;
/**
* This is a provider for a share action. It is responsible for creating views
* that enable data sharing and also to show a sub menu with sharing activities
* if the hosting item is placed on the overflow menu.
* <p>
* Here is how to use the action provider with custom backing file in a {@link MenuItem}:
* </p>
* <p>
* <pre>
* <code>
* // In Activity#onCreateOptionsMenu
* public boolean onCreateOptionsMenu(Menu menu) {
* // Get the menu item.
* MenuItem menuItem = menu.findItem(R.id.my_menu_item);
* // Get the provider and hold onto it to set/change the share intent.
* mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider();
* // Set history different from the default before getting the action
* // view since a call to {@link MenuItem#getActionView() MenuItem.getActionView()} calls
* // {@link ActionProvider#onCreateActionView()} which uses the backing file name. Omit this
* // line if using the default share history file is desired.
* mShareActionProvider.setShareHistoryFileName("custom_share_history.xml");
* . . .
* }
*
* // Somewhere in the application.
* public void doShare(Intent shareIntent) {
* // When you want to share set the share intent.
* mShareActionProvider.setShareIntent(shareIntent);
* }
* </pre>
* </code>
* </p>
* <p>
* <strong>Note:</strong> While the sample snippet demonstrates how to use this provider
* in the context of a menu item, the use of the provider is not limited to menu items.
* </p>
*
* @see ActionProvider
*/
public class ShareActionProvider extends ActionProvider {
/**
* Listener for the event of selecting a share target.
*/
public interface OnShareTargetSelectedListener {
/**
* Called when a share target has been selected. The client can
* decide whether to handle the intent or rely on the default
* behavior which is launching it.
* <p>
* <strong>Note:</strong> Modifying the intent is not permitted and
* any changes to the latter will be ignored.
* </p>
*
* @param source The source of the notification.
* @param intent The intent for launching the chosen share target.
* @return Whether the client has handled the intent.
*/
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent);
}
/**
* The default for the maximal number of activities shown in the sub-menu.
*/
private static final int DEFAULT_INITIAL_ACTIVITY_COUNT = 4;
/**
* The the maximum number activities shown in the sub-menu.
*/
private int mMaxShownActivityCount = DEFAULT_INITIAL_ACTIVITY_COUNT;
/**
* Listener for handling menu item clicks.
*/
private final ShareMenuItemOnMenuItemClickListener mOnMenuItemClickListener =
new ShareMenuItemOnMenuItemClickListener();
/**
* The default name for storing share history.
*/
public static final String DEFAULT_SHARE_HISTORY_FILE_NAME = "share_history.xml";
/**
* Context for accessing resources.
*/
private final Context mContext;
/**
* The name of the file with share history data.
*/
private String mShareHistoryFileName = DEFAULT_SHARE_HISTORY_FILE_NAME;
private OnShareTargetSelectedListener mOnShareTargetSelectedListener;
private OnChooseActivityListener mOnChooseActivityListener;
/**
* Creates a new instance.
*
* @param context Context for accessing resources.
*/
public ShareActionProvider(Context context) {
super(context);
mContext = context;
}
/**
* Sets a listener to be notified when a share target has been selected.
* The listener can optionally decide to handle the selection and
* not rely on the default behavior which is to launch the activity.
* <p>
* <strong>Note:</strong> If you choose the backing share history file
* you will still be notified in this callback.
* </p>
* @param listener The listener.
*/
public void setOnShareTargetSelectedListener(OnShareTargetSelectedListener listener) {
mOnShareTargetSelectedListener = listener;
setActivityChooserPolicyIfNeeded();
}
/**
* {@inheritDoc}
*/
@Override
public View onCreateActionView() {
// Create the view and set its data model.
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
activityChooserView.setActivityChooserModel(dataModel);
// Lookup and set the expand action icon.
TypedValue outTypedValue = new TypedValue();
mContext.getTheme().resolveAttribute(R.attr.actionModeShareDrawable, outTypedValue, true);
Drawable drawable = mContext.getResources().getDrawable(outTypedValue.resourceId);
activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
activityChooserView.setProvider(this);
// Set content description.
activityChooserView.setDefaultActionButtonContentDescription(
R.string.abs__shareactionprovider_share_with_application);
activityChooserView.setExpandActivityOverflowButtonContentDescription(
R.string.abs__shareactionprovider_share_with);
return activityChooserView;
}
/**
* {@inheritDoc}
*/
@Override
public boolean hasSubMenu() {
return true;
}
/**
* {@inheritDoc}
*/
@Override
public void onPrepareSubMenu(SubMenu subMenu) {
// Clear since the order of items may change.
subMenu.clear();
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
PackageManager packageManager = mContext.getPackageManager();
final int expandedActivityCount = dataModel.getActivityCount();
final int collapsedActivityCount = Math.min(expandedActivityCount, mMaxShownActivityCount);
// Populate the sub-menu with a sub set of the activities.
for (int i = 0; i < collapsedActivityCount; i++) {
ResolveInfo activity = dataModel.getActivity(i);
subMenu.add(0, i, i, activity.loadLabel(packageManager))
.setIcon(activity.loadIcon(packageManager))
.setOnMenuItemClickListener(mOnMenuItemClickListener);
}
if (collapsedActivityCount < expandedActivityCount) {
// Add a sub-menu for showing all activities as a list item.
SubMenu expandedSubMenu = subMenu.addSubMenu(Menu.NONE, collapsedActivityCount,
collapsedActivityCount,
mContext.getString(R.string.abs__activity_chooser_view_see_all));
for (int i = 0; i < expandedActivityCount; i++) {
ResolveInfo activity = dataModel.getActivity(i);
expandedSubMenu.add(0, i, i, activity.loadLabel(packageManager))
.setIcon(activity.loadIcon(packageManager))
.setOnMenuItemClickListener(mOnMenuItemClickListener);
}
}
}
/**
* Sets the file name of a file for persisting the share history which
* history will be used for ordering share targets. This file will be used
* for all view created by {@link #onCreateActionView()}. Defaults to
* {@link #DEFAULT_SHARE_HISTORY_FILE_NAME}. Set to <code>null</code>
* if share history should not be persisted between sessions.
* <p>
* <strong>Note:</strong> The history file name can be set any time, however
* only the action views created by {@link #onCreateActionView()} after setting
* the file name will be backed by the provided file.
* <p>
*
* @param shareHistoryFile The share history file name.
*/
public void setShareHistoryFileName(String shareHistoryFile) {
mShareHistoryFileName = shareHistoryFile;
setActivityChooserPolicyIfNeeded();
}
/**
* Sets an intent with information about the share action. Here is a
* sample for constructing a share intent:
* <p>
* <pre>
* <code>
* Intent shareIntent = new Intent(Intent.ACTION_SEND);
* shareIntent.setType("image/*");
* Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
* shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());
* </pre>
* </code>
* </p>
*
* @param shareIntent The share intent.
*
* @see Intent#ACTION_SEND
* @see Intent#ACTION_SEND_MULTIPLE
*/
public void setShareIntent(Intent shareIntent) {
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
mShareHistoryFileName);
dataModel.setIntent(shareIntent);
}
/**
* Reusable listener for handling share item clicks.
*/
private class ShareMenuItemOnMenuItemClickListener implements OnMenuItemClickListener {
@Override
public boolean onMenuItemClick(MenuItem item) {
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext,
mShareHistoryFileName);
final int itemId = item.getItemId();
Intent launchIntent = dataModel.chooseActivity(itemId);
if (launchIntent != null) {
mContext.startActivity(launchIntent);
}
return true;
}
}
/**
* Set the activity chooser policy of the model backed by the current
* share history file if needed which is if there is a registered callback.
*/
private void setActivityChooserPolicyIfNeeded() {
if (mOnShareTargetSelectedListener == null) {
return;
}
if (mOnChooseActivityListener == null) {
mOnChooseActivityListener = new ShareAcitivityChooserModelPolicy();
}
ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
dataModel.setOnChooseActivityListener(mOnChooseActivityListener);
}
/**
* Policy that delegates to the {@link OnShareTargetSelectedListener}, if such.
*/
private class ShareAcitivityChooserModelPolicy implements OnChooseActivityListener {
@Override
public boolean onChooseActivity(ActivityChooserModel host, Intent intent) {
if (mOnShareTargetSelectedListener != null) {
return mOnShareTargetSelectedListener.onShareTargetSelected(
ShareActionProvider.this, intent);
}
return false;
}
}
}