diff --git a/README.md b/README.md
index af53014..dd1731f 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ Android SDK 21 or Higher
Build Tools version 21.1.2
Android Support AppCompat 22.2.0
Android Support Annotations 22.2.0
+Android Support GridLayout 22.2.0
Google Play Services GCM 7.0.0
BumpTech Glide 3.5.2
diff --git a/app/build.gradle b/app/build.gradle
index 2068d3d..b8b3914 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -24,5 +24,6 @@ dependencies {
compile 'com.github.bumptech.glide:glide:3.5.2'
compile 'com.android.support:appcompat-v7:22.1.0'
compile 'com.android.support:support-annotations:22.1.0'
+ compile 'com.android.support:gridlayout-v7:22.1.0'
compile 'com.google.android.gms:play-services-gcm:7.0.0'
}
diff --git a/app/src/main/java/com/example/android/sunshine/app/DetailActivity.java b/app/src/main/java/com/example/android/sunshine/app/DetailActivity.java
index 80185b3..a23c185 100644
--- a/app/src/main/java/com/example/android/sunshine/app/DetailActivity.java
+++ b/app/src/main/java/com/example/android/sunshine/app/DetailActivity.java
@@ -31,10 +31,6 @@ public class DetailActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
- Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
-
if (savedInstanceState == null) {
// Create the detail fragment and add it to the activity
// using a fragment transaction.
@@ -50,24 +46,4 @@ public class DetailActivity extends AppCompatActivity {
.commit();
}
}
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.detail, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- if (id == R.id.action_settings) {
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/android/sunshine/app/DetailFragment.java b/app/src/main/java/com/example/android/sunshine/app/DetailFragment.java
index 0c88c6f..6a83b4b 100644
--- a/app/src/main/java/com/example/android/sunshine/app/DetailFragment.java
+++ b/app/src/main/java/com/example/android/sunshine/app/DetailFragment.java
@@ -24,7 +24,9 @@ import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
+import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.ShareActionProvider;
+import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -84,14 +86,16 @@ public class DetailFragment extends Fragment implements LoaderManager.LoaderCall
public static final int COL_WEATHER_CONDITION_ID = 9;
private ImageView mIconView;
- private TextView mFriendlyDateView;
private TextView mDateView;
private TextView mDescriptionView;
private TextView mHighTempView;
private TextView mLowTempView;
private TextView mHumidityView;
+ private TextView mHumidityLabelView;
private TextView mWindView;
+ private TextView mWindLabelView;
private TextView mPressureView;
+ private TextView mPressureLabelView;
public DetailFragment() {
setHasOptionsMenu(true);
@@ -109,30 +113,30 @@ public class DetailFragment extends Fragment implements LoaderManager.LoaderCall
View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
mIconView = (ImageView) rootView.findViewById(R.id.detail_icon);
mDateView = (TextView) rootView.findViewById(R.id.detail_date_textview);
- mFriendlyDateView = (TextView) rootView.findViewById(R.id.detail_day_textview);
mDescriptionView = (TextView) rootView.findViewById(R.id.detail_forecast_textview);
mHighTempView = (TextView) rootView.findViewById(R.id.detail_high_textview);
mLowTempView = (TextView) rootView.findViewById(R.id.detail_low_textview);
mHumidityView = (TextView) rootView.findViewById(R.id.detail_humidity_textview);
+ mHumidityLabelView = (TextView) rootView.findViewById(R.id.detail_humidity_label_textview);
mWindView = (TextView) rootView.findViewById(R.id.detail_wind_textview);
+ mWindLabelView = (TextView) rootView.findViewById(R.id.detail_wind_label_textview);
mPressureView = (TextView) rootView.findViewById(R.id.detail_pressure_textview);
+ mPressureLabelView = (TextView) rootView.findViewById(R.id.detail_pressure_label_textview);
return rootView;
}
+ private void finishCreatingMenu(Menu menu) {
+ // Retrieve the share menu item
+ MenuItem menuItem = menu.findItem(R.id.action_share);
+ menuItem.setIntent(createShareForecastIntent());
+ }
+
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- // Inflate the menu; this adds items to the action bar if it is present.
- inflater.inflate(R.menu.detailfragment, menu);
-
- // Retrieve the share menu item
- MenuItem menuItem = menu.findItem(R.id.action_share);
-
- // Get the provider and hold onto it to set/change the share intent.
- mShareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
-
- // If onLoadFinished happens before this, we can go ahead and set the share intent now.
- if (mForecast != null) {
- mShareActionProvider.setShareIntent(createShareForecastIntent());
+ if ( getActivity() instanceof DetailActivity ){
+ // Inflate the menu; this adds items to the action bar if it is present.
+ inflater.inflate(R.menu.detailfragment, menu);
+ finishCreatingMenu(menu);
}
}
@@ -184,18 +188,20 @@ public class DetailFragment extends Fragment implements LoaderManager.LoaderCall
// Read weather condition ID from cursor
int weatherId = data.getInt(COL_WEATHER_CONDITION_ID);
- // Use weather art image
- Glide.with(this)
- .load(Utility.getArtUrlForWeatherCondition(getActivity(), weatherId))
- .error(Utility.getArtResourceForWeatherCondition(weatherId))
- .crossFade()
- .into(mIconView);
+ if ( Utility.usingLocalGraphics(getActivity()) ) {
+ mIconView.setImageResource(Utility.getArtResourceForWeatherCondition(weatherId));
+ } else {
+ // Use weather art image
+ Glide.with(this)
+ .load(Utility.getArtUrlForWeatherCondition(getActivity(), weatherId))
+ .error(Utility.getArtResourceForWeatherCondition(weatherId))
+ .crossFade()
+ .into(mIconView);
+ }
// Read date from cursor and update views for day of week and date
long date = data.getLong(COL_WEATHER_DATE);
- String friendlyDateText = Utility.getDayName(getActivity(), date);
- String dateText = Utility.getFormattedMonthDay(getActivity(), date);
- mFriendlyDateView.setText(friendlyDateText);
+ String dateText = Utility.getFullFriendlyDayString(getActivity(),date);
mDateView.setText(dateText);
// Get description from weather condition ID
@@ -226,18 +232,21 @@ public class DetailFragment extends Fragment implements LoaderManager.LoaderCall
// Read humidity from cursor and update view
float humidity = data.getFloat(COL_WEATHER_HUMIDITY);
mHumidityView.setText(getActivity().getString(R.string.format_humidity, humidity));
- mHumidityView.setContentDescription(mHumidityView.getText());
+ mHumidityView.setContentDescription(getString(R.string.a11y_humidity, mHumidityView.getText()));
+ mHumidityLabelView.setContentDescription(mHumidityView.getContentDescription());
// Read wind speed and direction from cursor and update view
float windSpeedStr = data.getFloat(COL_WEATHER_WIND_SPEED);
float windDirStr = data.getFloat(COL_WEATHER_DEGREES);
mWindView.setText(Utility.getFormattedWind(getActivity(), windSpeedStr, windDirStr));
- mWindView.setContentDescription(mWindView.getText());
+ mWindView.setContentDescription(getString(R.string.a11y_wind, mWindView.getText()));
+ mWindLabelView.setContentDescription(mWindView.getContentDescription());
// Read pressure from cursor and update view
float pressure = data.getFloat(COL_WEATHER_PRESSURE);
- mPressureView.setText(getActivity().getString(R.string.format_pressure, pressure));
- mPressureView.setContentDescription(mPressureView.getText());
+ mPressureView.setText(getString(R.string.format_pressure, pressure));
+ mPressureView.setContentDescription(getString(R.string.a11y_pressure, mPressureView.getText()));
+ mPressureLabelView.setContentDescription(mPressureView.getContentDescription());
// We still need this for the share intent
mForecast = String.format("%s - %s - %s/%s", dateText, description, high, low);
@@ -247,6 +256,27 @@ public class DetailFragment extends Fragment implements LoaderManager.LoaderCall
mShareActionProvider.setShareIntent(createShareForecastIntent());
}
}
+ AppCompatActivity activity = (AppCompatActivity)getActivity();
+ Toolbar toolbarView = (Toolbar) getView().findViewById(R.id.toolbar);
+
+ // We need to start the enter transition after the data has loaded
+ if (activity instanceof DetailActivity) {
+ activity.supportStartPostponedEnterTransition();
+
+ if ( null != toolbarView ) {
+ activity.setSupportActionBar(toolbarView);
+
+ activity.getSupportActionBar().setDisplayShowTitleEnabled(false);
+ activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ }
+ } else {
+ if ( null != toolbarView ) {
+ Menu menu = toolbarView.getMenu();
+ if ( null != menu ) menu.clear();
+ toolbarView.inflateMenu(R.menu.detailfragment);
+ finishCreatingMenu(toolbarView.getMenu());
+ }
+ }
}
@Override
diff --git a/app/src/main/java/com/example/android/sunshine/app/Utility.java b/app/src/main/java/com/example/android/sunshine/app/Utility.java
index bad6d0c..7e1dacb 100644
--- a/app/src/main/java/com/example/android/sunshine/app/Utility.java
+++ b/app/src/main/java/com/example/android/sunshine/app/Utility.java
@@ -104,6 +104,24 @@ public class Utility {
}
}
+ /**
+ * Helper method to convert the database representation of the date into something to display
+ * to users. As classy and polished a user experience as "20140102" is, we can do better.
+ *
+ * @param context Context to use for resource localization
+ * @param dateInMillis The date in milliseconds
+ * @return a user-friendly representation of the date.
+ */
+ public static String getFullFriendlyDayString(Context context, long dateInMillis) {
+
+ String day = getDayName(context, dateInMillis);
+ int formatId = R.string.format_full_friendly_date;
+ return String.format(context.getString(
+ formatId,
+ day,
+ getFormattedMonthDay(context, dateInMillis)));
+ }
+
/**
* Given a day, returns just the name to use for that day.
* E.g "today", "tomorrow", "wednesday".
@@ -217,6 +235,19 @@ public class Utility {
return -1;
}
+ /**
+ * Helper method to return whether or not Sunshine is using local graphics.
+ *
+ * @param context Context to use for retrieving the preference
+ * @return true if Sunshine is using local graphics, false otherwise.
+ */
+ public static boolean usingLocalGraphics(Context context) {
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ String sunshineArtPack = context.getString(R.string.pref_art_pack_sunshine);
+ return prefs.getString(context.getString(R.string.pref_art_pack_key),
+ sunshineArtPack).equals(sunshineArtPack);
+ }
+
/**
* Helper method to provide the art urls according to the weather condition id returned
* by the OpenWeatherMap call.
diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml
index fd45611..280300c 100644
--- a/app/src/main/res/layout/activity_detail.xml
+++ b/app/src/main/res/layout/activity_detail.xml
@@ -13,23 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
-
-
-
\ No newline at end of file
+ android:layout_height="match_parent"
+ tools:context="com.example.android.sunshine.app.DetailActivity"
+ tools:ignore="MergeRootFrame" />
diff --git a/app/src/main/res/layout/detail_today_grid.xml b/app/src/main/res/layout/detail_today_grid.xml
new file mode 100644
index 0000000..de8f317
--- /dev/null
+++ b/app/src/main/res/layout/detail_today_grid.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml
index be69a26..f4108dd 100644
--- a/app/src/main/res/layout/fragment_detail.xml
+++ b/app/src/main/res/layout/fragment_detail.xml
@@ -14,115 +14,127 @@
limitations under the License.
-->
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
+
+
+ android:paddingBottom="@dimen/abc_list_item_padding_horizontal_material"
+ android:paddingEnd="@dimen/forecast_detail_horizontal_padding"
+ android:paddingLeft="@dimen/forecast_detail_horizontal_padding"
+ android:paddingRight="@dimen/forecast_detail_horizontal_padding"
+ android:paddingStart="@dimen/forecast_detail_horizontal_padding"
+ android:paddingTop="@dimen/abc_list_item_padding_horizontal_material">
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+ android:paddingEnd="@dimen/forecast_detail_horizontal_padding"
+ android:paddingRight="@dimen/forecast_detail_horizontal_padding"
+ android:id="@+id/detail_humidity_textview"
+ android:gravity="center_vertical"
+ android:textAppearance="@style/TextAppearance.AppCompat.Headline"
+ android:textColor="@android:color/white"
+ tools:text="38%" />
-
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ android:paddingEnd="@dimen/forecast_detail_horizontal_padding"
+ android:paddingRight="@dimen/forecast_detail_horizontal_padding"
+ android:id="@+id/detail_pressure_label_textview"
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ android:text="@string/pressure"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ android:textColor="@color/detail_accent_label" />
+
+ android:gravity="center_vertical"
+ android:textAppearance="@style/TextAppearance.AppCompat.Headline"
+ android:textColor="@android:color/white"
+ tools:text="995 hPa" />
+
+
+
+
+ android:paddingEnd="@dimen/forecast_detail_horizontal_padding"
+ android:paddingRight="@dimen/forecast_detail_horizontal_padding"
+ android:id="@+id/detail_wind_label_textview"
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ android:text="@string/wind"
+ android:textColor="@color/detail_accent_label"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title" />
+
+
+
-
+
+
+
diff --git a/app/src/main/res/layout/fragment_detail_wide.xml b/app/src/main/res/layout/fragment_detail_wide.xml
index 4724e23..b92648a 100644
--- a/app/src/main/res/layout/fragment_detail_wide.xml
+++ b/app/src/main/res/layout/fragment_detail_wide.xml
@@ -14,113 +14,119 @@
limitations under the License.
-->
-
+ android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
-
+
+
+
+
+
+
+
+
+ android:layout_height="match_parent"
+ app:columnCount="2"
+ android:background="@color/detail_accent_pane_background"
+ android:paddingEnd="@dimen/abc_list_item_padding_horizontal_material"
+ android:paddingRight="@dimen/abc_list_item_padding_horizontal_material"
+ >
-
-
+
-
-
-
-
-
+ android:id="@+id/detail_humidity_label_textview"
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ android:text="@string/humidity"
+ android:textColor="@color/detail_accent_label"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ android:paddingLeft="@dimen/abc_list_item_padding_horizontal_material"
+ android:paddingRight="@dimen/abc_list_item_padding_horizontal_material"
+ android:paddingBottom="@dimen/abc_list_item_padding_horizontal_material"
+ />
-
-
-
-
-
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ tools:text="38%"
+ android:textColor="@android:color/white"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ />
+
+
+
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ tools:text="995 hPa"
+ android:textColor="@android:color/white"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ />
+
+
-
+ android:fontFamily="sans-serif"
+ android:gravity="center_vertical"
+ tools:text="4km/h NW"
+ android:textColor="@android:color/white"
+ android:textAppearance="@style/TextAppearance.AppCompat.Title"
+ />
-
+
-
-
-
-
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/detailfragment.xml b/app/src/main/res/menu/detailfragment.xml
index b929cc8..c92c7c6 100644
--- a/app/src/main/res/menu/detailfragment.xml
+++ b/app/src/main/res/menu/detailfragment.xml
@@ -18,6 +18,6 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
+ android:icon="@drawable/abc_ic_menu_share_mtrl_alpha"
+ app:showAsAction="always"/>
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index ab9ea4d..d36c35c 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -26,5 +26,11 @@
#0288D1
#B3E5FC
#FFD740
+ #212121
+ #727272
+
+
+ #455A64
+ #90A4AE
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index b12ae05..5d125fb 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -19,4 +19,11 @@
16dp
48dp
+ 32dp
+
+
+ 96dp
+
+
+ @dimen/abc_list_item_padding_horizontal_material
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f330d64..1263e48 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -111,17 +111,20 @@
%1.0f\u00B0
+ Wind
- Wind: %1$1.0f mph %2$s
+ %1$1.0f mph %2$s
- Wind: %1$1.0f km/h %2$s
+ %1$1.0f km/h %2$s
+ Pressure
- Pressure: %1.0f hPa
+ %1.0f hPa
+ Humidity
- Humidity: %1.0f %%
+ %1.0f %%
sunshine.example.com
@@ -145,6 +148,9 @@
Forecast icon: %1$s
High: %1$s
Low: %1$s
+ Humidity: %1$s
+ Barometric Pressure: %1$s
+ Wind speed and direction: %1$s
Storm