Added action bar, updated look and feel

This commit is contained in:
dkeen@dkeen-laptop 2012-07-15 10:00:39 -07:00
parent f2ec482603
commit e79dc2ba46
43 changed files with 1651 additions and 151 deletions

View File

@ -5,7 +5,6 @@
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="libs/commons-io-2.0.1.jar"/>
<classpathentry kind="lib" path="libs/commons-lang3-3.1.jar"/>
<classpathentry kind="lib" path="libs/android-support-v4.jar"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

View File

@ -25,9 +25,15 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>net.rim.ajde.internal.verifier</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>net.rim.ajde.BlackBerryAndroidNature</nature>
</natures>
</projectDescription>

View File

@ -7,21 +7,24 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-sdk android:minSdkVersion="7" />
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="14" />
<application
android:debuggable="true"
android:icon="@drawable/icon"
android:label="@string/app_name" >
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:label="@string/app_name"
android:name="RoutesListActivity" >
<intent-filter >
android:name="RoutesListActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.EDIT" />
<action android:name="android.intent.action.PICK" />
@ -30,7 +33,7 @@
<data android:mimeType="vnd.android.cursor.dir/com.dougkeen.bart.favorite" />
</intent-filter>
<intent-filter >
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT" />
<category android:name="android.intent.category.DEFAULT" />
@ -39,9 +42,10 @@
</intent-filter>
</activity>
<activity
android:label="@string/app_name"
android:name="AddRouteActivity" >
<intent-filter >
android:name="AddRouteActivity"
android:label="@string/add_route"
android:theme="@android:style/Theme.Dialog" >
<intent-filter>
<action android:name="android.intent.action.INSERT" />
<category android:name="android.intent.category.DEFAULT" />
@ -50,9 +54,9 @@
</intent-filter>
</activity>
<activity
android:label="@string/app_name"
android:name="ViewDeparturesActivity" >
<intent-filter >
android:name="ViewDeparturesActivity"
android:label="@string/departures" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@ -61,14 +65,14 @@
</intent-filter>
</activity>
<activity
android:label="@string/app_name"
android:name="ViewMapActivity" >
android:name="ViewMapActivity"
android:label="@string/system_map" >
</activity>
<provider
android:name=".data.BartContentProvider"
android:authorities="com.dougkeen.bart.dataprovider"
android:label="Don\&apos;t Miss The Bart data provider"
android:name=".data.BartContentProvider" />
android:label="BartRunner data provider" />
</application>
</manifest>

Binary file not shown.

3
lint.xml Normal file
View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<lint>
</lint>

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,23 @@
<!--
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.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/actionbar_compat_item_pressed"
android:state_pressed="true" />
<item android:drawable="@drawable/actionbar_compat_item_focused"
android:state_focused="true" />
<item android:drawable="@android:color/transparent" />
</selector>

View File

@ -0,0 +1,19 @@
<!--
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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ef7000" />
</shape>

View File

@ -0,0 +1,19 @@
<!--
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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#eda700" />
</shape>

View File

@ -0,0 +1,27 @@
<!--
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.
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<ProgressBar android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_gravity="center"
style="?android:attr/indeterminateProgressStyle" />
</FrameLayout>

View File

@ -0,0 +1,21 @@
<!--
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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@id/actionbar_compat"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" />

View File

@ -2,10 +2,6 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:paddingLeft="5dp" android:paddingRight="5dp">
<TextView android:id="@+id/form_header" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:textSize="24dp"
android:textStyle="bold" android:layout_alignParentTop="true"
android:text="@string/add_route" android:paddingBottom="10dp" />
<TextView android:id="@+id/origin_label" android:text="@string/origin"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:textSize="15dp" android:layout_below="@+id/form_header"

36
res/layout/departures.xml Normal file
View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/listTitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:textSize="24dp" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="@android:id/empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="@+id/missingDepartureText"
style="@style/MissingDepartureText"
android:autoLink="email"
android:singleLine="false"
android:text="@string/missing_departure"
android:visibility="gone" />
</LinearLayout>

View File

@ -4,16 +4,6 @@
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/listTitle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:textSize="24dp"
android:textStyle="bold" />
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
@ -25,13 +15,4 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:id="@+id/missingDepartureText"
style="@style/MissingDepartureText"
android:autoLink="email"
android:singleLine="false"
android:text="@string/missing_departure"
android:visibility="gone" />
</LinearLayout>

View File

@ -1,7 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/view_on_bart_site" android:icon="@android:drawable/ic_menu_view"
android:id="@+id/view_on_bart_site_button"></item>
<item android:title="@string/view_system_map" android:icon="@android:drawable/ic_menu_mapmode"
android:id="@+id/view_system_map_button"></item>
</menu>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/view_on_bart_site_button"
android:icon="@drawable/web_icon"
android:showAsAction="ifRoom|withText"
android:title="@string/view_on_bart_site">
</item>
<item
android:id="@+id/view_system_map_button"
android:icon="@drawable/map_icon"
android:showAsAction="ifRoom|withText"
android:title="@string/view_system_map">
</item>
</menu>

View File

@ -1,7 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="@string/add_route" android:icon="@android:drawable/ic_menu_add"
android:id="@+id/add_favorite_menu_button"></item>
<item android:title="@string/view_system_map" android:icon="@android:drawable/ic_menu_mapmode"
android:id="@+id/view_system_map_button"></item>
</menu>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/add_favorite_menu_button"
android:icon="@drawable/new_icon"
android:showAsAction="ifRoom|withText"
android:title="@string/add_route">
</item>
<item
android:id="@+id/view_system_map_button"
android:icon="@drawable/map_icon"
android:showAsAction="ifRoom|withText"
android:title="@string/view_system_map">
</item>
</menu>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
</menu>

34
res/values-v11/styles.xml Normal file
View File

@ -0,0 +1,34 @@
<!--
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.
-->
<resources>
<style name="AppTheme" parent="android:style/Theme.Holo">
<item name="android:actionBarStyle">@style/ActionBar</item>
<item name="android:windowContentOverlay">@drawable/actionbar_shadow</item>
</style>
<style name="ActionBar" parent="android:style/Widget.Holo.ActionBar">
<item name="android:background">#222</item>
<item name="android:titleTextStyle">@style/ActionBarTitle</item>
<item name="android:icon">@drawable/icon</item>
</style>
<style name="ActionBarTitle">
<item name="android:textColor">@color/actionbar_title_color</item>
</style>
</resources>

23
res/values-v13/styles.xml Normal file
View File

@ -0,0 +1,23 @@
<!--
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.
-->
<resources>
<style name="ActionBarTitle" parent="android:style/TextAppearance.Holo.Widget.ActionBar.Title">
<item name="android:textColor">@color/actionbar_title_color</item>
</style>
</resources>

31
res/values/attrs.xml Normal file
View File

@ -0,0 +1,31 @@
<!--
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.
-->
<resources>
<declare-styleable name="AppTheme">
<attr name="actionbarCompatTitleStyle" format="reference" />
<attr name="actionbarCompatItemStyle" format="reference" />
<attr name="actionbarCompatItemHomeStyle" format="reference" />
<attr name="actionbarCompatProgressIndicatorStyle" format="reference" />
</declare-styleable>
<declare-styleable name="BezelImageView">
<attr name="maskDrawable" format="reference" />
<attr name="borderDrawable" format="reference" />
</declare-styleable>
</resources>

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
</resources>
<color name="actionbar_title_color">#EEEEEE</color>
</resources>

21
res/values/dimens.xml Normal file
View File

@ -0,0 +1,21 @@
<!--
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.
-->
<resources>
<dimen name="actionbar_compat_height">48dp</dimen>
<dimen name="actionbar_compat_button_width">48dp</dimen>
<dimen name="actionbar_compat_button_home_width">56dp</dimen>
</resources>

23
res/values/ids.xml Normal file
View File

@ -0,0 +1,23 @@
<!--
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.
-->
<resources>
<item type="id" name="actionbar_compat" />
<item type="id" name="actionbar_compat_title" />
<item type="id" name="actionbar_compat_item_refresh_progress" />
<item type="id" name="actionbar_compat_item_refresh" />
<item type="id" name="menu_refresh" />
</resources>

View File

@ -2,8 +2,7 @@
<resources>
<string name="app_name">BART Runner</string>
<string name="favorite_routes">Favorite Routes</string>
<string name="empty_favorites_list_message">Press the menu button and select \"Add route\" to
add a route</string>
<string name="empty_favorites_list_message">No favorite routes have been added yet</string>
<string name="add_route">Add a route</string>
<string name="origin">Origin</string>
<string name="destination">Destination</string>
@ -29,4 +28,6 @@
again later.</string>
<string name="also_add_return_route">Also add return route</string>
<string name="view_system_map">View system map</string>
<string name="system_map">System map</string>
<string name="departures">Departures</string>
</resources>

View File

@ -1,78 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme is the default theme. -->
<style name="Theme" parent="android:Theme"></style>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="ButtonBar">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingTop">10dp</item>
<item name="android:paddingBottom">10dp</item>
</style>
<!-- Base application theme is the default theme. -->
<style name="AppTheme" parent="@android:Theme">
<item name="android:windowTitleSize">@dimen/actionbar_compat_height</item>
<item name="android:windowTitleBackgroundStyle">@style/ActionBarCompat</item>
<item name="android:windowContentOverlay">@drawable/actionbar_shadow</item>
<style name="FavoriteListingTextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">20dp</item>
<item name="android:ellipsize">end</item>
<item name="android:singleLine">true</item>
</style>
<!-- for programmatic instantiation -->
<item name="actionbarCompatTitleStyle">@style/ActionBarCompatTitle</item>
<item name="actionbarCompatItemStyle">@style/ActionBarCompatItem</item>
<item name="actionbarCompatItemHomeStyle">@style/ActionBarCompatHomeItem</item>
<item name="actionbarCompatProgressIndicatorStyle">@style/ActionBarCompatProgressIndicator</item>
</style>
<style name="FareTextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16dp</item>
<item name="android:ellipsize">end</item>
<item name="android:singleLine">true</item>
</style>
<style name="ActionBarCompat">
<item name="android:background">#222</item>
</style>
<style name="DepartureDestinationText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">22dp</item>
<item name="android:textStyle">bold</item>
<item name="android:singleLine">true</item>
<item name="android:layout_marginLeft">3dp</item>
</style>
<style name="ActionBarCompatItemBase">
<style name="DepartureTrainLengthText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">18dp</item>
<item name="android:singleLine">true</item>
<item name="android:layout_marginLeft">3dp</item>
</style>
<!-- layout_width/height must be set in code -->
<item name="android:scaleType">center</item>
<item name="android:background">@drawable/actionbar_compat_item</item>
</style>
<style name="DepartureCountdownText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">20dp</item>
<item name="android:singleLine">true</item>
<item name="android:width">90dp</item>
</style>
<style name="DepartureUncertaintyText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16dp</item>
<item name="android:singleLine">true</item>
</style>
<style name="MissingDepartureText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">12dp</item>
<item name="android:singleLine">true</item>
<item name="android:gravity">center</item>
</style>
<style name="BikeIcon">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">5dp</item>
<item name="android:layout_marginLeft">5dp</item>
</style>
<style name="XferIcon">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginRight">87dp</item>
<item name="android:layout_marginBottom">5dp</item>
</style>
</resources>
<style name="ActionBarCompatProgressIndicator" parent="android:style/Widget.ProgressBar.Large">
<item name="android:indeterminate">true</item>
</style>
<style name="ActionBarCompatTitleBase">
<item name="android:id">@id/actionbar_compat_title</item>
<!-- layout_width/height/weight must be set in code -->
<item name="android:gravity">center_vertical</item>
<item name="android:textSize">18sp</item>
<item name="android:paddingLeft">6dp</item>
<item name="android:paddingRight">6dp</item>
<item name="android:singleLine">false</item>
<item name="android:maxLines">2</item>
<item name="android:ellipsize">marquee</item>
</style>
<style name="ActionBarCompatTitle" parent="style/ActionBarCompatTitleBase">
<item name="android:textColor">@color/actionbar_title_color</item>
</style>
<style name="ActionBarCompatItem" parent="style/ActionBarCompatItemBase"></style>
<style name="ActionBarCompatHomeItem" parent="style/ActionBarCompatItemBase"></style>
<style name="ButtonBar">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingTop">10dp</item>
<item name="android:paddingBottom">10dp</item>
</style>
<style name="FavoriteListingTextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">20dp</item>
<item name="android:ellipsize">end</item>
<item name="android:singleLine">true</item>
</style>
<style name="FareTextView">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16dp</item>
<item name="android:ellipsize">end</item>
<item name="android:singleLine">true</item>
</style>
<style name="DepartureDestinationText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">22dp</item>
<item name="android:textStyle">bold</item>
<item name="android:singleLine">true</item>
<item name="android:layout_marginLeft">3dp</item>
</style>
<style name="DepartureTrainLengthText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">18dp</item>
<item name="android:singleLine">true</item>
<item name="android:layout_marginLeft">3dp</item>
</style>
<style name="DepartureCountdownText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">20dp</item>
<item name="android:singleLine">true</item>
<item name="android:width">90dp</item>
</style>
<style name="DepartureUncertaintyText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">16dp</item>
<item name="android:singleLine">true</item>
</style>
<style name="MissingDepartureText">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">12dp</item>
<item name="android:singleLine">true</item>
<item name="android:gravity">center</item>
</style>
<style name="BikeIcon">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginTop">5dp</item>
<item name="android:layout_marginLeft">5dp</item>
</style>
<style name="XferIcon">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginRight">87dp</item>
<item name="android:layout_marginBottom">5dp</item>
</style>
</resources>

View File

@ -6,7 +6,6 @@ import java.util.TimeZone;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
@ -27,13 +26,14 @@ import android.widget.SimpleCursorAdapter;
import android.widget.SimpleCursorAdapter.ViewBinder;
import android.widget.TextView;
import com.dougkeen.bart.actionbarcompat.ActionBarListActivity;
import com.dougkeen.bart.data.CursorUtils;
import com.dougkeen.bart.data.RoutesColumns;
import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Station;
import com.dougkeen.bart.networktasks.GetRouteFareTask;
public class RoutesListActivity extends ListActivity {
public class RoutesListActivity extends ActionBarListActivity {
private static final TimeZone PACIFIC_TIME = TimeZone
.getTimeZone("America/Los_Angeles");
@ -50,6 +50,7 @@ public class RoutesListActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setTitle(R.string.favorite_routes);
mQuery = managedQuery(Constants.FAVORITE_CONTENT_URI, new String[] {
RoutesColumns._ID.string, RoutesColumns.FROM_STATION.string,
@ -138,8 +139,6 @@ public class RoutesListActivity extends ListActivity {
@Override
protected void onResume() {
super.onResume();
((TextView) findViewById(R.id.listTitle))
.setText(R.string.favorite_routes);
((TextView) findViewById(android.R.id.empty))
.setText(R.string.empty_favorites_list_message);
refreshFares();

View File

@ -4,7 +4,6 @@ import java.util.List;
import org.apache.commons.lang3.math.NumberUtils;
import android.app.ListActivity;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
@ -24,6 +23,7 @@ import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.dougkeen.bart.actionbarcompat.ActionBarListActivity;
import com.dougkeen.bart.data.RoutesColumns;
import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Departure;
@ -35,7 +35,7 @@ import com.dougkeen.bart.model.StationPair;
import com.dougkeen.bart.networktasks.GetRealTimeDeparturesTask;
import com.dougkeen.bart.networktasks.GetScheduleInformationTask;
public class ViewDeparturesActivity extends ListActivity {
public class ViewDeparturesActivity extends ActionBarListActivity {
private static final int UNCERTAINTY_THRESHOLD = 17;
@ -50,7 +50,7 @@ public class ViewDeparturesActivity extends ListActivity {
private ScheduleInformation mLatestScheduleInfo;
private TextView mListTitleView;
private TextView mEmptyView;
private AsyncTask<StationPair, Integer, RealTimeDepartures> mGetDeparturesTask;
private AsyncTask<StationPair, Integer, ScheduleInformation> mGetScheduleInformationTask;
@ -71,7 +71,7 @@ public class ViewDeparturesActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setContentView(R.layout.departures);
final Intent intent = getIntent();
@ -96,13 +96,11 @@ public class ViewDeparturesActivity extends ListActivity {
mAverageTripLength = cursor.getInt(2);
mAverageTripSampleCount = cursor.getInt(3);
String header = "Departures:\n" + mOrigin.name + " to "
+ mDestination.name;
((TextView) findViewById(R.id.listTitle)).setText(mOrigin.name + " to "
+ mDestination.name);
mListTitleView = (TextView) findViewById(R.id.listTitle);
mListTitleView.setText(header);
((TextView) findViewById(android.R.id.empty))
.setText(R.string.departure_wait_message);
mEmptyView = (TextView) findViewById(android.R.id.empty);
mEmptyView.setText(R.string.departure_wait_message);
mDeparturesAdapter = new DepartureArrayAdapter(this,
R.layout.departure_listing);
@ -200,8 +198,7 @@ public class ViewDeparturesActivity extends ListActivity {
Log.w(Constants.TAG, e.getMessage(), e);
Toast.makeText(ViewDeparturesActivity.this,
R.string.could_not_connect, Toast.LENGTH_LONG).show();
((TextView) findViewById(android.R.id.empty))
.setText(R.string.could_not_connect);
mEmptyView.setText(R.string.could_not_connect);
// Try again in 60s
scheduleDepartureFetch(60000);
}
@ -236,8 +233,7 @@ public class ViewDeparturesActivity extends ListActivity {
Log.w(Constants.TAG, e.getMessage(), e);
Toast.makeText(ViewDeparturesActivity.this,
R.string.could_not_connect, Toast.LENGTH_LONG).show();
((TextView) findViewById(android.R.id.empty))
.setText(R.string.could_not_connect);
mEmptyView.setText(R.string.could_not_connect);
// Try again in 60s
scheduleScheduleInfoFetch(60000);
}
@ -262,7 +258,7 @@ public class ViewDeparturesActivity extends ListActivity {
return;
}
if (result.getDepartures().isEmpty()) {
final TextView textView = (TextView) findViewById(android.R.id.empty);
final TextView textView = mEmptyView;
textView.setText(R.string.no_data_message);
Linkify.addLinks(textView, Linkify.WEB_URLS);
return;
@ -486,7 +482,7 @@ public class ViewDeparturesActivity extends ListActivity {
private void scheduleDepartureFetch(int millisUntilExecute) {
if (!mDepartureFetchIsPending) {
mListTitleView.postDelayed(new Runnable() {
postDelayed(new Runnable() {
public void run() {
fetchLatestDepartures();
}
@ -499,7 +495,7 @@ public class ViewDeparturesActivity extends ListActivity {
private void scheduleScheduleInfoFetch(int millisUntilExecute) {
if (!mScheduleFetchIsPending) {
mListTitleView.postDelayed(new Runnable() {
postDelayed(new Runnable() {
public void run() {
fetchLatestSchedule();
}
@ -523,12 +519,16 @@ public class ViewDeparturesActivity extends ListActivity {
}
mLastAutoUpdate = now;
if (hasWindowFocus()) {
mListTitleView.postDelayed(AUTO_UPDATE_RUNNABLE, 1000);
postDelayed(AUTO_UPDATE_RUNNABLE, 1000);
} else {
mIsAutoUpdating = false;
}
}
private boolean postDelayed(Runnable runnable, long delayMillis) {
return mEmptyView.postDelayed(runnable, delayMillis);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();

View File

@ -1,10 +1,13 @@
package com.dougkeen.bart;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.webkit.WebView;
public class ViewMapActivity extends Activity {
import com.dougkeen.bart.actionbarcompat.ActionBarActivity;
public class ViewMapActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -18,4 +21,12 @@ public class ViewMapActivity extends Activity {
webview.loadUrl("file:///android_res/drawable/map.png");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.system_map_menu, menu);
return true;
}
}

View File

@ -0,0 +1,63 @@
package com.dougkeen.bart.actionbarcompat;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
/**
* Damn, I wish Java had mixins
*/
public class ActionBarActivity extends Activity {
final ActionBarHelper mActionBarHelper = ActionBarHelper
.createInstance(this);
/**
* Returns the {@link ActionBarHelper} for this activity.
*/
protected ActionBarHelper getActionBarHelper() {
return mActionBarHelper;
}
/** {@inheritDoc} */
@Override
public MenuInflater getMenuInflater() {
return mActionBarHelper.getMenuInflater(super.getMenuInflater());
}
/** {@inheritDoc} */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActionBarHelper.onCreate(savedInstanceState);
}
/** {@inheritDoc} */
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mActionBarHelper.onPostCreate(savedInstanceState);
}
/**
* Base action bar-aware implementation for
* {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* Note: marking menu items as invisible/visible is not currently supported.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean retValue = false;
retValue |= mActionBarHelper.onCreateOptionsMenu(menu);
retValue |= super.onCreateOptionsMenu(menu);
return retValue;
}
/** {@inheritDoc} */
@Override
protected void onTitleChanged(CharSequence title, int color) {
mActionBarHelper.onTitleChanged(title, color);
super.onTitleChanged(title, color);
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
/**
* An abstract class that handles some common action bar-related functionality in the app. This
* class provides functionality useful for both phones and tablets, and does not require any Android
* 3.0-specific features, although it uses them if available.
*
* Two implementations of this class are {@link ActionBarHelperBase} for a pre-Honeycomb version of
* the action bar, and {@link ActionBarHelperHoneycomb}, which uses the built-in ActionBar features
* in Android 3.0 and later.
*/
public abstract class ActionBarHelper {
protected Activity mActivity;
/**
* Factory method for creating {@link ActionBarHelper} objects for a
* given activity. Depending on which device the app is running, either a basic helper or
* Honeycomb-specific helper will be returned.
*/
public static ActionBarHelper createInstance(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
return new ActionBarHelperICS(activity);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
return new ActionBarHelperHoneycomb(activity);
} else {
return new ActionBarHelperBase(activity);
}
}
protected ActionBarHelper(Activity activity) {
mActivity = activity;
}
/**
* Action bar helper code to be run in {@link Activity#onCreate(android.os.Bundle)}.
*/
public void onCreate(Bundle savedInstanceState) {
}
/**
* Action bar helper code to be run in {@link Activity#onPostCreate(android.os.Bundle)}.
*/
public void onPostCreate(Bundle savedInstanceState) {
}
/**
* Action bar helper code to be run in {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* NOTE: Setting the visibility of menu items in <em>menu</em> is not currently supported.
*/
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
/**
* Action bar helper code to be run in {@link Activity#onTitleChanged(CharSequence, int)}.
*/
protected void onTitleChanged(CharSequence title, int color) {
}
/**
* Sets the indeterminate loading state of the item with ID {@link R.id.menu_refresh}.
* (where the item ID was menu_refresh).
*/
public abstract void setRefreshActionItemState(boolean refreshing);
/**
* Returns a {@link MenuInflater} for use when inflating menus. The implementation of this
* method in {@link ActionBarHelperBase} returns a wrapped menu inflater that can read
* action bar metadata from a menu resource pre-Honeycomb.
*/
public MenuInflater getMenuInflater(MenuInflater superMenuInflater) {
return superMenuInflater;
}
}

View File

@ -0,0 +1,319 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.app.Activity;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.view.InflateException;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.dougkeen.bart.R;
/**
* A class that implements the action bar pattern for pre-Honeycomb devices.
*/
public class ActionBarHelperBase extends ActionBarHelper {
private static final String MENU_RES_NAMESPACE = "http://schemas.android.com/apk/res/android";
private static final String MENU_ATTR_ID = "id";
private static final String MENU_ATTR_SHOW_AS_ACTION = "showAsAction";
protected Set<Integer> mActionItemIds = new HashSet<Integer>();
protected ActionBarHelperBase(Activity activity) {
super(activity);
}
/** {@inheritDoc} */
@Override
public void onCreate(Bundle savedInstanceState) {
mActivity.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
}
/** {@inheritDoc} */
@Override
public void onPostCreate(Bundle savedInstanceState) {
mActivity.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.actionbar_compat);
setupActionBar();
SimpleMenu menu = new SimpleMenu(mActivity);
mActivity.onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu);
mActivity.onPrepareOptionsMenu(menu);
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (mActionItemIds.contains(item.getItemId())) {
addActionItemCompatFromMenuItem(item);
}
}
}
/**
* Sets up the compatibility action bar with the given title.
*/
private void setupActionBar() {
final ViewGroup actionBarCompat = getActionBarCompat();
if (actionBarCompat == null) {
return;
}
LinearLayout.LayoutParams springLayoutParams = new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.FILL_PARENT);
springLayoutParams.weight = 1;
// Add Home button
SimpleMenu tempMenu = new SimpleMenu(mActivity);
SimpleMenuItem homeItem = new SimpleMenuItem(tempMenu,
android.R.id.home, 0, mActivity.getString(R.string.app_name));
homeItem.setIcon(R.drawable.icon);
addActionItemCompatFromMenuItem(homeItem);
// Add title text
TextView titleText = new TextView(mActivity, null,
R.attr.actionbarCompatTitleStyle);
titleText.setLayoutParams(springLayoutParams);
titleText.setText(mActivity.getTitle());
actionBarCompat.addView(titleText);
}
/** {@inheritDoc} */
@Override
public void setRefreshActionItemState(boolean refreshing) {
View refreshButton = mActivity
.findViewById(R.id.actionbar_compat_item_refresh);
View refreshIndicator = mActivity
.findViewById(R.id.actionbar_compat_item_refresh_progress);
if (refreshButton != null) {
refreshButton.setVisibility(refreshing ? View.GONE : View.VISIBLE);
}
if (refreshIndicator != null) {
refreshIndicator.setVisibility(refreshing ? View.VISIBLE
: View.GONE);
}
}
/**
* Action bar helper code to be run in
* {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* NOTE: This code will mark on-screen menu items as invisible.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Hides on-screen action items from the options menu.
for (Integer id : mActionItemIds) {
menu.findItem(id).setVisible(false);
}
return true;
}
/** {@inheritDoc} */
@Override
protected void onTitleChanged(CharSequence title, int color) {
TextView titleView = (TextView) mActivity
.findViewById(R.id.actionbar_compat_title);
if (titleView != null) {
titleView.setText(title);
}
}
/**
* Returns a {@link android.view.MenuInflater} that can read action bar
* metadata on pre-Honeycomb devices.
*/
public MenuInflater getMenuInflater(MenuInflater superMenuInflater) {
return new WrappedMenuInflater(mActivity, superMenuInflater);
}
/**
* Returns the {@link android.view.ViewGroup} for the action bar on phones
* (compatibility action bar). Can return null, and will return null on
* Honeycomb.
*/
private ViewGroup getActionBarCompat() {
return (ViewGroup) mActivity.findViewById(R.id.actionbar_compat);
}
/**
* Adds an action button to the compatibility action bar, using menu
* information from a {@link android.view.MenuItem}. If the menu item ID is
* <code>menu_refresh</code>, the menu item's state can be changed to show a
* loading spinner using
* {@link com.example.android.actionbarcompat.ActionBarHelperBase#setRefreshActionItemState(boolean)}
* .
*/
private View addActionItemCompatFromMenuItem(final MenuItem item) {
final int itemId = item.getItemId();
final ViewGroup actionBar = getActionBarCompat();
if (actionBar == null) {
return null;
}
// Create the button
ImageButton actionButton = new ImageButton(
mActivity,
null,
itemId == android.R.id.home ? R.attr.actionbarCompatItemHomeStyle
: R.attr.actionbarCompatItemStyle);
actionButton
.setLayoutParams(new ViewGroup.LayoutParams(
(int) mActivity
.getResources()
.getDimension(
itemId == android.R.id.home ? R.dimen.actionbar_compat_button_home_width
: R.dimen.actionbar_compat_button_width),
ViewGroup.LayoutParams.FILL_PARENT));
if (itemId == R.id.menu_refresh) {
actionButton.setId(R.id.actionbar_compat_item_refresh);
}
actionButton.setImageDrawable(item.getIcon());
actionButton.setScaleType(ImageView.ScaleType.CENTER);
actionButton.setContentDescription(item.getTitle());
actionButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mActivity
.onMenuItemSelected(Window.FEATURE_OPTIONS_PANEL, item);
}
});
actionBar.addView(actionButton);
if (item.getItemId() == R.id.menu_refresh) {
// Refresh buttons should be stateful, and allow for indeterminate
// progress indicators,
// so add those.
ProgressBar indicator = new ProgressBar(mActivity, null,
R.attr.actionbarCompatProgressIndicatorStyle);
final int buttonWidth = mActivity.getResources()
.getDimensionPixelSize(
R.dimen.actionbar_compat_button_width);
final int buttonHeight = mActivity.getResources()
.getDimensionPixelSize(R.dimen.actionbar_compat_height);
final int progressIndicatorWidth = buttonWidth / 2;
LinearLayout.LayoutParams indicatorLayoutParams = new LinearLayout.LayoutParams(
progressIndicatorWidth, progressIndicatorWidth);
indicatorLayoutParams.setMargins(
(buttonWidth - progressIndicatorWidth) / 2,
(buttonHeight - progressIndicatorWidth) / 2,
(buttonWidth - progressIndicatorWidth) / 2, 0);
indicator.setLayoutParams(indicatorLayoutParams);
indicator.setVisibility(View.GONE);
indicator.setId(R.id.actionbar_compat_item_refresh_progress);
actionBar.addView(indicator);
}
return actionButton;
}
/**
* A {@link android.view.MenuInflater} that reads action bar metadata.
*/
private class WrappedMenuInflater extends MenuInflater {
MenuInflater mInflater;
public WrappedMenuInflater(Context context, MenuInflater inflater) {
super(context);
mInflater = inflater;
}
@Override
public void inflate(int menuRes, Menu menu) {
loadActionBarMetadata(menuRes);
mInflater.inflate(menuRes, menu);
}
/**
* Loads action bar metadata from a menu resource, storing a list of
* menu item IDs that should be shown on-screen (i.e. those with
* showAsAction set to always or ifRoom).
*
* @param menuResId
*/
private void loadActionBarMetadata(int menuResId) {
XmlResourceParser parser = null;
try {
parser = mActivity.getResources().getXml(menuResId);
int eventType = parser.getEventType();
int itemId;
int showAsAction;
boolean eof = false;
while (!eof) {
switch (eventType) {
case XmlPullParser.START_TAG:
if (!parser.getName().equals("item")) {
break;
}
itemId = parser.getAttributeResourceValue(
MENU_RES_NAMESPACE, MENU_ATTR_ID, 0);
if (itemId == 0) {
break;
}
showAsAction = parser.getAttributeIntValue(
MENU_RES_NAMESPACE, MENU_ATTR_SHOW_AS_ACTION,
-1);
if ((showAsAction & MenuItem.SHOW_AS_ACTION_ALWAYS) > 0
|| (showAsAction & MenuItem.SHOW_AS_ACTION_IF_ROOM) > 0) {
mActionItemIds.add(itemId);
}
break;
case XmlPullParser.END_DOCUMENT:
eof = true;
break;
}
eventType = parser.next();
}
} catch (XmlPullParserException e) {
throw new InflateException("Error inflating menu XML", e);
} catch (IOException e) {
throw new InflateException("Error inflating menu XML", e);
} finally {
if (parser != null) {
parser.close();
}
}
}
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.dougkeen.bart.R;
/**
* An extension of {@link ActionBarHelper} that provides Android 3.0-specific functionality for
* Honeycomb tablets. It thus requires API level 11.
*/
public class ActionBarHelperHoneycomb extends ActionBarHelper {
private Menu mOptionsMenu;
private View mRefreshIndeterminateProgressView = null;
protected ActionBarHelperHoneycomb(Activity activity) {
super(activity);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mOptionsMenu = menu;
return super.onCreateOptionsMenu(menu);
}
@Override
public void setRefreshActionItemState(boolean refreshing) {
// On Honeycomb, we can set the state of the refresh button by giving it a custom
// action view.
if (mOptionsMenu == null) {
return;
}
final MenuItem refreshItem = mOptionsMenu.findItem(R.id.menu_refresh);
if (refreshItem != null) {
if (refreshing) {
if (mRefreshIndeterminateProgressView == null) {
LayoutInflater inflater = (LayoutInflater)
getActionBarThemedContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mRefreshIndeterminateProgressView = inflater.inflate(
R.layout.actionbar_indeterminate_progress, null);
}
refreshItem.setActionView(mRefreshIndeterminateProgressView);
} else {
refreshItem.setActionView(null);
}
}
}
/**
* Returns a {@link Context} suitable for inflating layouts for the action bar. The
* implementation for this method in {@link ActionBarHelperICS} asks the action bar for a
* themed context.
*/
protected Context getActionBarThemedContext() {
return mActivity;
}
}

View File

@ -0,0 +1,37 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.MenuItem;
/**
* An extension of {@link com.example.android.actionbarcompat.ActionBarHelper} that provides Android
* 4.0-specific functionality for IceCreamSandwich devices. It thus requires API level 14.
*/
public class ActionBarHelperICS extends ActionBarHelperHoneycomb {
protected ActionBarHelperICS(Activity activity) {
super(activity);
}
@Override
protected Context getActionBarThemedContext() {
return mActivity.getActionBar().getThemedContext();
}
}

View File

@ -0,0 +1,84 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import android.app.Activity;
import android.app.ListActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
/**
* A base activity that defers common functionality across app activities to an {@link
* ActionBarHelper}.
*
* NOTE: dynamically marking menu items as invisible/visible is not currently supported.
*
* NOTE: this may used with the Android Compatibility Package by extending
* android.support.v4.app.FragmentActivity instead of {@link Activity}.
*/
public abstract class ActionBarListActivity extends ListActivity {
final ActionBarHelper mActionBarHelper = ActionBarHelper.createInstance(this);
/**
* Returns the {@link ActionBarHelper} for this activity.
*/
protected ActionBarHelper getActionBarHelper() {
return mActionBarHelper;
}
/**{@inheritDoc}*/
@Override
public MenuInflater getMenuInflater() {
return mActionBarHelper.getMenuInflater(super.getMenuInflater());
}
/**{@inheritDoc}*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActionBarHelper.onCreate(savedInstanceState);
}
/**{@inheritDoc}*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mActionBarHelper.onPostCreate(savedInstanceState);
}
/**
* Base action bar-aware implementation for
* {@link Activity#onCreateOptionsMenu(android.view.Menu)}.
*
* Note: marking menu items as invisible/visible is not currently supported.
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
boolean retValue = false;
retValue |= mActionBarHelper.onCreateOptionsMenu(menu);
retValue |= super.onCreateOptionsMenu(menu);
return retValue;
}
/**{@inheritDoc}*/
@Override
protected void onTitleChanged(CharSequence title, int color) {
mActionBarHelper.onTitleChanged(title, color);
super.onTitleChanged(title, color);
}
}

View File

@ -0,0 +1,203 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import java.util.ArrayList;
/**
* A <em>really</em> dumb implementation of the {@link android.view.Menu} interface, that's only
* useful for our actionbar-compat purposes. See
* <code>com.android.internal.view.menu.MenuBuilder</code> in AOSP for a more complete
* implementation.
*/
public class SimpleMenu implements Menu {
private Context mContext;
private Resources mResources;
private ArrayList<SimpleMenuItem> mItems;
public SimpleMenu(Context context) {
mContext = context;
mResources = context.getResources();
mItems = new ArrayList<SimpleMenuItem>();
}
public Context getContext() {
return mContext;
}
public Resources getResources() {
return mResources;
}
public MenuItem add(CharSequence title) {
return addInternal(0, 0, title);
}
public MenuItem add(int titleRes) {
return addInternal(0, 0, mResources.getString(titleRes));
}
public MenuItem add(int groupId, int itemId, int order, CharSequence title) {
return addInternal(itemId, order, title);
}
public MenuItem add(int groupId, int itemId, int order, int titleRes) {
return addInternal(itemId, order, mResources.getString(titleRes));
}
/**
* Adds an item to the menu. The other add methods funnel to this.
*/
private MenuItem addInternal(int itemId, int order, CharSequence title) {
final SimpleMenuItem item = new SimpleMenuItem(this, itemId, order, title);
mItems.add(findInsertIndex(mItems, order), item);
return item;
}
private static int findInsertIndex(ArrayList<? extends MenuItem> items, int order) {
for (int i = items.size() - 1; i >= 0; i--) {
MenuItem item = items.get(i);
if (item.getOrder() <= order) {
return i + 1;
}
}
return 0;
}
public int findItemIndex(int id) {
final int size = size();
for (int i = 0; i < size; i++) {
SimpleMenuItem item = mItems.get(i);
if (item.getItemId() == id) {
return i;
}
}
return -1;
}
public void removeItem(int itemId) {
removeItemAtInt(findItemIndex(itemId));
}
private void removeItemAtInt(int index) {
if ((index < 0) || (index >= mItems.size())) {
return;
}
mItems.remove(index);
}
public void clear() {
mItems.clear();
}
public MenuItem findItem(int id) {
final int size = size();
for (int i = 0; i < size; i++) {
SimpleMenuItem item = mItems.get(i);
if (item.getItemId() == id) {
return item;
}
}
return null;
}
public int size() {
return mItems.size();
}
public MenuItem getItem(int index) {
return mItems.get(index);
}
// Unsupported operations.
public SubMenu addSubMenu(CharSequence charSequence) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public SubMenu addSubMenu(int titleRes) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public int addIntentOptions(int i, int i1, int i2, ComponentName componentName,
Intent[] intents, Intent intent, int i3, MenuItem[] menuItems) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void removeGroup(int i) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setGroupCheckable(int i, boolean b, boolean b1) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setGroupVisible(int i, boolean b) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setGroupEnabled(int i, boolean b) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean hasVisibleItems() {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void close() {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean performShortcut(int i, KeyEvent keyEvent, int i1) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean isShortcutKey(int i, KeyEvent keyEvent) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public boolean performIdentifierAction(int i, int i1) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
public void setQwertyMode(boolean b) {
throw new UnsupportedOperationException("This operation is not supported for SimpleMenu");
}
}

View File

@ -0,0 +1,263 @@
/*
* 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.
*/
package com.dougkeen.bart.actionbarcompat;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.view.ActionProvider;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
/**
* A <em>really</em> dumb implementation of the {@link android.view.MenuItem}
* interface, that's only useful for our actionbar-compat purposes. See
* <code>com.android.internal.view.menu.MenuItemImpl</code> in AOSP for a more
* complete implementation.
*/
public class SimpleMenuItem implements MenuItem {
private SimpleMenu mMenu;
private final int mId;
private final int mOrder;
private CharSequence mTitle;
private CharSequence mTitleCondensed;
private Drawable mIconDrawable;
private int mIconResId = 0;
private boolean mEnabled = true;
public SimpleMenuItem(SimpleMenu menu, int id, int order, CharSequence title) {
mMenu = menu;
mId = id;
mOrder = order;
mTitle = title;
}
public int getItemId() {
return mId;
}
public int getOrder() {
return mOrder;
}
public MenuItem setTitle(CharSequence title) {
mTitle = title;
return this;
}
public MenuItem setTitle(int titleRes) {
return setTitle(mMenu.getContext().getString(titleRes));
}
public CharSequence getTitle() {
return mTitle;
}
public MenuItem setTitleCondensed(CharSequence title) {
mTitleCondensed = title;
return this;
}
public CharSequence getTitleCondensed() {
return mTitleCondensed != null ? mTitleCondensed : mTitle;
}
public MenuItem setIcon(Drawable icon) {
mIconResId = 0;
mIconDrawable = icon;
return this;
}
public MenuItem setIcon(int iconResId) {
mIconDrawable = null;
mIconResId = iconResId;
return this;
}
public Drawable getIcon() {
if (mIconDrawable != null) {
return mIconDrawable;
}
if (mIconResId != 0) {
return mMenu.getResources().getDrawable(mIconResId);
}
return null;
}
public MenuItem setEnabled(boolean enabled) {
mEnabled = enabled;
return this;
}
public boolean isEnabled() {
return mEnabled;
}
// No-op operations. We use no-ops to allow inflation from menu XML.
public int getGroupId() {
// Noop
return 0;
}
public View getActionView() {
// Noop
return null;
}
public MenuItem setActionProvider(ActionProvider actionProvider) {
// Noop
return this;
}
public ActionProvider getActionProvider() {
// Noop
return null;
}
public boolean expandActionView() {
// Noop
return false;
}
public boolean collapseActionView() {
// Noop
return false;
}
public boolean isActionViewExpanded() {
// Noop
return false;
}
@Override
public MenuItem setOnActionExpandListener(
OnActionExpandListener onActionExpandListener) {
// Noop
return this;
}
public MenuItem setIntent(Intent intent) {
// Noop
return this;
}
public Intent getIntent() {
// Noop
return null;
}
public MenuItem setShortcut(char c, char c1) {
// Noop
return this;
}
public MenuItem setNumericShortcut(char c) {
// Noop
return this;
}
public char getNumericShortcut() {
// Noop
return 0;
}
public MenuItem setAlphabeticShortcut(char c) {
// Noop
return this;
}
public char getAlphabeticShortcut() {
// Noop
return 0;
}
public MenuItem setCheckable(boolean b) {
// Noop
return this;
}
public boolean isCheckable() {
// Noop
return false;
}
public MenuItem setChecked(boolean b) {
// Noop
return this;
}
public boolean isChecked() {
// Noop
return false;
}
public MenuItem setVisible(boolean b) {
// Noop
return this;
}
public boolean isVisible() {
// Noop
return true;
}
public boolean hasSubMenu() {
// Noop
return false;
}
public SubMenu getSubMenu() {
// Noop
return null;
}
public MenuItem setOnMenuItemClickListener(
OnMenuItemClickListener onMenuItemClickListener) {
// Noop
return this;
}
public ContextMenu.ContextMenuInfo getMenuInfo() {
// Noop
return null;
}
public void setShowAsAction(int i) {
// Noop
}
public MenuItem setShowAsActionFlags(int i) {
// Noop
return null;
}
public MenuItem setActionView(View view) {
// Noop
return this;
}
public MenuItem setActionView(int i) {
// Noop
return this;
}
}