Updated our RecyclerView to handle onClick and empty view.
This commit is contained in:
@@ -17,15 +17,18 @@ package com.example.android.sunshine.app;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.os.Build;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Checkable;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.example.android.sunshine.app.data.WeatherContract;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ForecastAdapter} exposes a list of weather forecasts
|
* {@link ForecastAdapter} exposes a list of weather forecasts
|
||||||
@@ -41,11 +44,13 @@ public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.Foreca
|
|||||||
|
|
||||||
private Cursor mCursor;
|
private Cursor mCursor;
|
||||||
final private Context mContext;
|
final private Context mContext;
|
||||||
|
final private ForecastAdapterOnClickHandler mClickHandler;
|
||||||
|
final private View mEmptyView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache of the children views for a forecast list item.
|
* Cache of the children views for a forecast list item.
|
||||||
*/
|
*/
|
||||||
public class ForecastAdapterViewHolder extends RecyclerView.ViewHolder {
|
public class ForecastAdapterViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
|
||||||
public final ImageView mIconView;
|
public final ImageView mIconView;
|
||||||
public final TextView mDateView;
|
public final TextView mDateView;
|
||||||
public final TextView mDescriptionView;
|
public final TextView mDescriptionView;
|
||||||
@@ -59,11 +64,26 @@ public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.Foreca
|
|||||||
mDescriptionView = (TextView) view.findViewById(R.id.list_item_forecast_textview);
|
mDescriptionView = (TextView) view.findViewById(R.id.list_item_forecast_textview);
|
||||||
mHighTempView = (TextView) view.findViewById(R.id.list_item_high_textview);
|
mHighTempView = (TextView) view.findViewById(R.id.list_item_high_textview);
|
||||||
mLowTempView = (TextView) view.findViewById(R.id.list_item_low_textview);
|
mLowTempView = (TextView) view.findViewById(R.id.list_item_low_textview);
|
||||||
|
view.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int adapterPosition = getAdapterPosition();
|
||||||
|
mCursor.moveToPosition(adapterPosition);
|
||||||
|
int dateColumnIndex = mCursor.getColumnIndex(WeatherContract.WeatherEntry.COLUMN_DATE);
|
||||||
|
mClickHandler.onClick(mCursor.getLong(dateColumnIndex), this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ForecastAdapter(Context context) {
|
public static interface ForecastAdapterOnClickHandler {
|
||||||
|
void onClick(Long date, ForecastAdapterViewHolder vh);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForecastAdapter(Context context, ForecastAdapterOnClickHandler dh, View emptyView) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
mClickHandler = dh;
|
||||||
|
mEmptyView = emptyView;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -92,7 +112,7 @@ public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.Foreca
|
|||||||
view.setFocusable(true);
|
view.setFocusable(true);
|
||||||
return new ForecastAdapterViewHolder(view);
|
return new ForecastAdapterViewHolder(view);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Not bound to RecyclerViewSelection");
|
throw new RuntimeException("Not bound to RecyclerView");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +190,7 @@ public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.Foreca
|
|||||||
public void swapCursor(Cursor newCursor) {
|
public void swapCursor(Cursor newCursor) {
|
||||||
mCursor = newCursor;
|
mCursor = newCursor;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
|
mEmptyView.setVisibility(getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Cursor getCursor() {
|
public Cursor getCursor() {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import com.example.android.sunshine.app.data.WeatherContract;
|
|||||||
import com.example.android.sunshine.app.sync.SunshineSyncAdapter;
|
import com.example.android.sunshine.app.sync.SunshineSyncAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates fetching the forecast and displaying it as a {@link RecyclerView} layout.
|
* Encapsulates fetching the forecast and displaying it as a {@link android.support.v7.widget.RecyclerView} layout.
|
||||||
*/
|
*/
|
||||||
public class ForecastFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, SharedPreferences.OnSharedPreferenceChangeListener {
|
public class ForecastFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
public static final String LOG_TAG = ForecastFragment.class.getSimpleName();
|
public static final String LOG_TAG = ForecastFragment.class.getSimpleName();
|
||||||
@@ -148,9 +148,6 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
// The ForecastAdapter will take data from a source and
|
|
||||||
// use it to populate the RecyclerView it's attached to.
|
|
||||||
mForecastAdapter = new ForecastAdapter(getActivity());
|
|
||||||
|
|
||||||
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
|
||||||
|
|
||||||
@@ -159,26 +156,28 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
|
|
||||||
// Set the layout manager
|
// Set the layout manager
|
||||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||||
// View emptyView = rootView.findViewById(R.id.recyclerview_forecast_empty);
|
View emptyView = rootView.findViewById(R.id.recyclerview_forecast_empty);
|
||||||
|
|
||||||
|
// use this setting to improve performance if you know that changes
|
||||||
|
// in content do not change the layout size of the RecyclerView
|
||||||
|
mRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
|
// The ForecastAdapter will take data from a source and
|
||||||
|
// use it to populate the RecyclerView it's attached to.
|
||||||
|
mForecastAdapter = new ForecastAdapter(getActivity(), new ForecastAdapter.ForecastAdapterOnClickHandler() {
|
||||||
|
@Override
|
||||||
|
public void onClick(Long date, ForecastAdapter.ForecastAdapterViewHolder vh) {
|
||||||
|
String locationSetting = Utility.getPreferredLocation(getActivity());
|
||||||
|
((Callback) getActivity())
|
||||||
|
.onItemSelected(WeatherContract.WeatherEntry.buildWeatherLocationWithDate(
|
||||||
|
locationSetting, date)
|
||||||
|
);
|
||||||
|
mPosition = vh.getAdapterPosition();
|
||||||
|
}
|
||||||
|
}, emptyView);
|
||||||
|
|
||||||
|
// specify an adapter (see also next example)
|
||||||
mRecyclerView.setAdapter(mForecastAdapter);
|
mRecyclerView.setAdapter(mForecastAdapter);
|
||||||
// We'll call our MainActivity
|
|
||||||
// mRecyclerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
|
|
||||||
// // CursorAdapter returns a cursor at the correct position for getItem(), or null
|
|
||||||
// // if it cannot seek to that position.
|
|
||||||
// Cursor cursor = (Cursor) adapterView.getItemAtPosition(position);
|
|
||||||
// if (cursor != null) {
|
|
||||||
// String locationSetting = Utility.getPreferredLocation(getActivity());
|
|
||||||
// ((Callback) getActivity())
|
|
||||||
// .onItemSelected(WeatherContract.WeatherEntry.buildWeatherLocationWithDate(
|
|
||||||
// locationSetting, cursor.getLong(COL_WEATHER_DATE)
|
|
||||||
// ));
|
|
||||||
// }
|
|
||||||
// mPosition = position;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
// If there's instance state, mine it for useful information.
|
// If there's instance state, mine it for useful information.
|
||||||
// The end-goal here is that the user never knows that turning their device sideways
|
// The end-goal here is that the user never knows that turning their device sideways
|
||||||
@@ -186,7 +185,7 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
// or magically appeared to take advantage of room, but data or place in the app was never
|
// or magically appeared to take advantage of room, but data or place in the app was never
|
||||||
// actually *lost*.
|
// actually *lost*.
|
||||||
if (savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY)) {
|
if (savedInstanceState != null && savedInstanceState.containsKey(SELECTED_KEY)) {
|
||||||
// The RecyclerView probably hasn't even been populated yet. Actually perform the
|
// The Recycler View probably hasn't even been populated yet. Actually perform the
|
||||||
// swapout in onLoadFinished.
|
// swapout in onLoadFinished.
|
||||||
mPosition = savedInstanceState.getInt(SELECTED_KEY);
|
mPosition = savedInstanceState.getInt(SELECTED_KEY);
|
||||||
}
|
}
|
||||||
@@ -203,7 +202,7 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// since we read the location when we create the loader, all we need to do is restart things
|
// since we read the location when we create the loader, all we need to do is restart things
|
||||||
void onLocationChanged( ) {
|
void onLocationChanged() {
|
||||||
getLoaderManager().restartLoader(FORECAST_LOADER, null, this);
|
getLoaderManager().restartLoader(FORECAST_LOADER, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,9 +210,9 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
// Using the URI scheme for showing a location found on a map. This super-handy
|
// Using the URI scheme for showing a location found on a map. This super-handy
|
||||||
// intent can is detailed in the "Common Intents" page of Android's developer site:
|
// intent can is detailed in the "Common Intents" page of Android's developer site:
|
||||||
// http://developer.android.com/guide/components/intents-common.html#Maps
|
// http://developer.android.com/guide/components/intents-common.html#Maps
|
||||||
if ( null != mForecastAdapter ) {
|
if (null != mForecastAdapter) {
|
||||||
Cursor c = mForecastAdapter.getCursor();
|
Cursor c = mForecastAdapter.getCursor();
|
||||||
if ( null != c ) {
|
if (null != c) {
|
||||||
c.moveToPosition(0);
|
c.moveToPosition(0);
|
||||||
String posLat = c.getString(COL_COORD_LAT);
|
String posLat = c.getString(COL_COORD_LAT);
|
||||||
String posLong = c.getString(COL_COORD_LONG);
|
String posLong = c.getString(COL_COORD_LONG);
|
||||||
@@ -235,7 +234,7 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
// When tablets rotate, the currently selected list item needs to be saved.
|
// When tablets rotate, the currently selected list item needs to be saved.
|
||||||
// When no item is selected, mPosition will be set to RecyclerView.INVALID_POSITION,
|
// When no item is selected, mPosition will be set to RecyclerView.NO_POSITION,
|
||||||
// so check for that before storing.
|
// so check for that before storing.
|
||||||
if (mPosition != RecyclerView.NO_POSITION) {
|
if (mPosition != RecyclerView.NO_POSITION) {
|
||||||
outState.putInt(SELECTED_KEY, mPosition);
|
outState.putInt(SELECTED_KEY, mPosition);
|
||||||
@@ -311,7 +310,7 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
message = R.string.empty_forecast_list_invalid_location;
|
message = R.string.empty_forecast_list_invalid_location;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (!Utility.isNetworkAvailable(getActivity()) ) {
|
if (!Utility.isNetworkAvailable(getActivity())) {
|
||||||
message = R.string.empty_forecast_list_no_network;
|
message = R.string.empty_forecast_list_no_network;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,9 +321,8 @@ public class ForecastFragment extends Fragment implements LoaderManager.LoaderCa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
if ( key.equals(getString(R.string.pref_location_status_key)) ) {
|
if (key.equals(getString(R.string.pref_location_status_key))) {
|
||||||
updateEmptyView();
|
updateEmptyView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -23,8 +23,7 @@
|
|||||||
style="@style/ForecastListStyle"
|
style="@style/ForecastListStyle"
|
||||||
android:id="@+id/recyclerview_forecast"
|
android:id="@+id/recyclerview_forecast"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"/>
|
||||||
android:divider="@null" />
|
|
||||||
<!-- empty list -->
|
<!-- empty list -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/recyclerview_forecast_empty"
|
android:id="@+id/recyclerview_forecast_empty"
|
||||||
|
|||||||
Reference in New Issue
Block a user