diff --git a/res/layout/fragment_list_view.xml b/res/layout/fragment_arrivals.xml similarity index 89% copy from res/layout/fragment_list_view.xml copy to res/layout/fragment_arrivals.xml index b65cf85..190516a 100644 --- a/res/layout/fragment_list_view.xml +++ b/res/layout/fragment_arrivals.xml @@ -1,48 +1,49 @@ \ No newline at end of file diff --git a/res/layout/fragment_list_view.xml b/res/layout/fragment_list_view.xml index b65cf85..e4d9361 100644 --- a/res/layout/fragment_list_view.xml +++ b/res/layout/fragment_list_view.xml @@ -1,48 +1,43 @@ - + + android:minHeight="48dp" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_toStartOf="@+id/addToFavorites" + android:foreground="?attr/selectableItemBackground" /> + android:visibility="visible" > + + + \ No newline at end of file diff --git a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java index eca8f1a..2a6142e 100644 --- a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java +++ b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java @@ -1,215 +1,285 @@ /* BusTO - Fragments components Copyright (C) 2018 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.fragments; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; import android.widget.ImageButton; +import android.widget.ListAdapter; +import android.widget.ListView; import android.widget.TextView; +import android.widget.Toast; import it.reyboz.bustorino.R; +import it.reyboz.bustorino.adapters.PalinaAdapter; import it.reyboz.bustorino.backend.DBStatusManager; +import it.reyboz.bustorino.backend.FiveTNormalizer; +import it.reyboz.bustorino.backend.Palina; +import it.reyboz.bustorino.backend.Route; +import it.reyboz.bustorino.backend.Stop; import it.reyboz.bustorino.middleware.AppDataProvider; import it.reyboz.bustorino.middleware.NextGenDB; import it.reyboz.bustorino.middleware.UserDB; public class ArrivalsFragment extends ResultListFragment implements LoaderManager.LoaderCallbacks { private final static String KEY_STOP_ID = "stopid"; private final static String KEY_STOP_NAME = "stopname"; private final static String DEBUG_TAG = "BUSTOArrivalsFragment"; private final static int loaderFavId = 2; private final static int loaderStopId = 1; + static final String STOP_TITLE = "messageExtra"; + private @Nullable String stopID,stopName; - private TextView messageTextView; private DBStatusManager prefs; private DBStatusManager.OnDBUpdateStatusChangeListener listener; private boolean justCreated = false; - private ImageButton addToFavorites; + private Palina lastUpdatedPalina = null; + + //Views + protected ImageButton addToFavorites; public static ArrivalsFragment newInstance(String stopID){ Bundle args = new Bundle(); args.putString(KEY_STOP_ID,stopID); ArrivalsFragment fragment = new ArrivalsFragment(); //parameter for ResultListFragment args.putSerializable(LIST_TYPE,FragmentKind.ARRIVALS); fragment.setArguments(args); return fragment; } public static ArrivalsFragment newInstance(String stopID,String stopName){ ArrivalsFragment fragment = newInstance(stopID); Bundle args = fragment.getArguments(); args.putString(KEY_STOP_NAME,stopName); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); stopID = getArguments().getString(KEY_STOP_ID); //this might really be null stopName = getArguments().getString(KEY_STOP_NAME); - final ArrivalsFragment f = this; + final ArrivalsFragment arrivalsFragment = this; listener = new DBStatusManager.OnDBUpdateStatusChangeListener() { @Override public void onDBStatusChanged(boolean updating) { if(!updating){ - getLoaderManager().restartLoader(loaderFavId,getArguments(),f); + getLoaderManager().restartLoader(loaderFavId,getArguments(),arrivalsFragment); } else { final LoaderManager lm = getLoaderManager(); lm.destroyLoader(loaderFavId); lm.destroyLoader(loaderStopId); } } @Override public boolean defaultStatusValue() { return true; } }; prefs = new DBStatusManager(getContext().getApplicationContext(),listener); justCreated = true; } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View root = inflater.inflate(R.layout.fragment_arrivals, container, false); + messageTextView = (TextView) root.findViewById(R.id.messageTextView); + addToFavorites = (ImageButton) root.findViewById(R.id.addToFavorites); + resultsListView = (ListView) root.findViewById(R.id.resultsListView); + //Button + addToFavorites.setClickable(true); + addToFavorites.setOnClickListener(v -> { + // add/remove the stop in the favorites + mListener.toggleLastStopToFavorites(); + }); + + resultsListView.setOnItemClickListener((parent, view, position, id) -> { + String routeName; + + Route r = (Route) parent.getItemAtPosition(position); + routeName = FiveTNormalizer.routeInternalToDisplay(r.getNameForDisplay()); + if (routeName == null) { + routeName = r.getNameForDisplay(); + } + if (r.destinazione == null || r.destinazione.length() == 0) { + Toast.makeText(getContext(), + getString(R.string.route_towards_unknown, routeName), Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(getContext(), + getString(R.string.route_towards_destination, routeName, r.destinazione), Toast.LENGTH_SHORT).show(); + } + }); + String displayName = getArguments().getString(STOP_TITLE); + setTextViewMessage(String.format( + getString(R.string.passages), displayName)); + + + String probablemessage = getArguments().getString(MESSAGE_TEXT_VIEW); + if (probablemessage != null) { + //Log.d("BusTO fragment " + this.getTag(), "We have a possible message here in the savedInstaceState: " + probablemessage); + messageTextView.setText(probablemessage); + messageTextView.setVisibility(View.VISIBLE); + } + return root; + } @Override public void onResume() { super.onResume(); LoaderManager loaderManager = getLoaderManager(); if(stopID!=null){ //refresh the arrivals if(!justCreated) mListener.createFragmentForStop(stopID); else justCreated = false; //start the loader if(prefs.isDBUpdating(true)){ prefs.registerListener(); } else { loaderManager.restartLoader(loaderFavId, getArguments(), this); } updateMessage(); } } @Nullable public String getStopID() { return stopID; } + + public void updateFragmentData(Palina p, PalinaAdapter adapter){ + + super.resetListAdapter(adapter); + } + + @Override + public void setNewListAdapter(ListAdapter adapter) { + throw new UnsupportedOperationException(); + } + /** * Update the message in the fragment * * It may eventually change the "Add to Favorite" icon */ private void updateMessage(){ String message = null; if (stopName != null && stopID != null && stopName.length() > 0) { message = (stopID.concat(" - ").concat(stopName)); } else if(stopID!=null) { message = stopID; } else { Log.e("ArrivalsFragm"+getTag(),"NO ID FOR THIS FRAGMENT - something went horribly wrong"); } if(message!=null) { setTextViewMessage(getString(R.string.passages,message)); } // whatever is the case, update the star icon mListener.updateStarIconFromLastBusStop(); } @Override public Loader onCreateLoader(int id, Bundle args) { if(args.getString(KEY_STOP_ID)==null) return null; final String stopID = args.getString(KEY_STOP_ID); final Uri.Builder builder = AppDataProvider.getUriBuilderToComplete(); CursorLoader cl; switch (id){ case loaderFavId: builder.appendPath("favorites").appendPath(stopID); cl = new CursorLoader(getContext(),builder.build(),UserDB.getFavoritesColumnNamesAsArray,null,null,null); break; case loaderStopId: builder.appendPath("stop").appendPath(stopID); cl = new CursorLoader(getContext(),builder.build(),new String[]{NextGenDB.Contract.StopsTable.COL_NAME}, null,null,null); break; default: return null; } cl.setUpdateThrottle(500); return cl; } @Override public void onLoadFinished(Loader loader, Cursor data) { switch (loader.getId()){ case loaderFavId: final int colUserName = data.getColumnIndex(UserDB.getFavoritesColumnNamesAsArray[1]); if(data.getCount()>0){ data.moveToFirst(); final String probableName = data.getString(colUserName); if(probableName!=null && !probableName.isEmpty()){ stopName = probableName; updateMessage(); } } if(stopName == null){ //stop is not inside the favorites and wasn't provided Log.d("ArrivalsFragment"+getTag(),"Stop wasn't in the favorites and has no name, looking in the DB"); getLoaderManager().restartLoader(loaderStopId,getArguments(),this); } break; case loaderStopId: if(data.getCount()>0){ data.moveToFirst(); stopName = data.getString(data.getColumnIndex( NextGenDB.Contract.StopsTable.COL_NAME )); updateMessage(); } else { Log.w("ArrivalsFragment"+getTag(),"Stop is not inside the database... CLOISTER BELL"); } } } @Override public void onPause() { if(listener!=null) prefs.unregisterListener(); super.onPause(); } @Override public void onLoaderReset(Loader loader) { //NOTHING TO DO } } diff --git a/src/it/reyboz/bustorino/fragments/FragmentHelper.java b/src/it/reyboz/bustorino/fragments/FragmentHelper.java index 70cc018..105fe04 100644 --- a/src/it/reyboz/bustorino/fragments/FragmentHelper.java +++ b/src/it/reyboz/bustorino/fragments/FragmentHelper.java @@ -1,230 +1,232 @@ /* BusTO (fragments) Copyright (C) 2018 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.fragments; import android.content.ContentResolver; import android.content.ContentValues; import android.database.sqlite.SQLiteException; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import it.reyboz.bustorino.R; import it.reyboz.bustorino.adapters.PalinaAdapter; import it.reyboz.bustorino.backend.Fetcher; import it.reyboz.bustorino.backend.Palina; import it.reyboz.bustorino.backend.Stop; import it.reyboz.bustorino.middleware.*; import java.lang.ref.WeakReference; import java.util.List; /** * Helper class to manage the fragments and their needs */ public class FragmentHelper { GeneralActivity act; private Stop lastSuccessfullySearchedBusStop; //support for multiple frames private int primaryFrameLayout,secondaryFrameLayout, swipeRefID; public static final int NO_FRAME = -3; private WeakReference lastTaskRef; private NextGenDB newDBHelper; private boolean shouldHaltAllActivities=false; public FragmentHelper(GeneralActivity act, int swipeRefID, int mainFrame) { this(act,swipeRefID,mainFrame,NO_FRAME); } public FragmentHelper(GeneralActivity act, int swipeRefID, int primaryFrameLayout, int secondaryFrameLayout) { this.act = act; this.swipeRefID = swipeRefID; this.primaryFrameLayout = primaryFrameLayout; this.secondaryFrameLayout = secondaryFrameLayout; newDBHelper = new NextGenDB(act.getApplicationContext()); } /** * Get the last successfully searched bus stop or NULL * - * @return + * @return the stop */ public Stop getLastSuccessfullySearchedBusStop() { return lastSuccessfullySearchedBusStop; } public void setLastSuccessfullySearchedBusStop(Stop stop) { this.lastSuccessfullySearchedBusStop = stop; } public void setLastTaskRef(WeakReference lastTaskRef) { this.lastTaskRef = lastTaskRef; } /** * Called when you need to create a fragment for a specified Palina * @param p the Stop that needs to be displayed */ public void createOrUpdateStopFragment(Palina p){ boolean sameFragment; ArrivalsFragment arrivalsFragment; if(act==null || shouldHaltAllActivities) { //SOMETHING WENT VERY WRONG return; } - SwipeRefreshLayout srl = (SwipeRefreshLayout) act.findViewById(swipeRefID); FragmentManager fm = act.getSupportFragmentManager(); if(fm.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { arrivalsFragment = (ArrivalsFragment) fm.findFragmentById(R.id.resultFrame); sameFragment = arrivalsFragment.isFragmentForTheSameStop(p); } else sameFragment = false; setLastSuccessfullySearchedBusStop(p); if(!sameFragment) { //set the String to be displayed on the fragment String displayName = p.getStopDisplayName(); String displayStuff; if (displayName != null && displayName.length() > 0) { arrivalsFragment = ArrivalsFragment.newInstance(p.ID,displayName); } else { arrivalsFragment = ArrivalsFragment.newInstance(p.ID); } attachFragmentToContainer(fm,arrivalsFragment,true,ResultListFragment.getFragmentTag(p)); } else { Log.d("BusTO", "Same bus stop, accessing existing fragment"); arrivalsFragment = (ArrivalsFragment) fm.findFragmentById(R.id.resultFrame); } - arrivalsFragment.setListAdapter(new PalinaAdapter(act.getApplicationContext(),p)); + final PalinaAdapter adapter = new PalinaAdapter(act.getApplicationContext(), p); + // DO NOT CALL `setListAdapter` ever on arrivals fragment + arrivalsFragment.updateFragmentData(p, adapter); + act.hideKeyboard(); toggleSpinner(false); } /** * Called when you need to display the results of a search of stops * @param resultList the List of stops found * @param query String queried */ public void createFragmentFor(List resultList,String query){ act.hideKeyboard(); StopListFragment listfragment = StopListFragment.newInstance(query); attachFragmentToContainer(act.getSupportFragmentManager(),listfragment,false,"search_"+query); listfragment.setStopList(resultList); toggleSpinner(false); } /** * Wrapper for toggleSpinner in Activity * @param on new status of spinner system */ public void toggleSpinner(boolean on){ if (act instanceof FragmentListener) ((FragmentListener) act).toggleSpinner(on); else { SwipeRefreshLayout srl = (SwipeRefreshLayout) act.findViewById(swipeRefID); srl.setRefreshing(false); } } /** * Attach a new fragment to a cointainer * @param fm the FragmentManager * @param fragment the Fragment * @param sendToSecondaryFrame needs to be displayed in secondary frame or not * @param tag tag for the fragment */ public void attachFragmentToContainer(FragmentManager fm,Fragment fragment, boolean sendToSecondaryFrame, String tag){ FragmentTransaction ft = fm.beginTransaction(); if(sendToSecondaryFrame && secondaryFrameLayout!=NO_FRAME) ft.replace(secondaryFrameLayout,fragment,tag); else ft.replace(primaryFrameLayout,fragment,tag); ft.addToBackStack("state_"+tag); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); ft.commit(); //fm.executePendingTransactions(); } synchronized public int insertBatchDataInNextGenDB(ContentValues[] valuesArr,String tableName){ if(newDBHelper !=null) try { return newDBHelper.insertBatchContent(valuesArr, tableName); } catch (SQLiteException exc){ Log.w("DB Batch inserting: ","ERROR Inserting the data batch: ",exc.fillInStackTrace()); return -2; } else return -1; } synchronized public ContentResolver getContentResolver(){ return act.getContentResolver(); } public void setBlockAllActivities(boolean shouldI) { this.shouldHaltAllActivities = shouldI; } public void stopLastRequestIfNeeded(){ if(lastTaskRef == null) return; AsyncDataDownload task = lastTaskRef.get(); if(task!=null){ task.cancel(true); } } /** * Wrapper to show the errors/status that happened * @param res result from Fetcher */ public void showErrorMessage(Fetcher.result res){ //TODO: implement a common set of errors for all fragments switch (res){ case OK: break; case CLIENT_OFFLINE: act.showMessage(R.string.network_error); break; case SERVER_ERROR: if (act.isConnected()) { act.showMessage(R.string.parsing_error); } else { act.showMessage(R.string.network_error); } case PARSER_ERROR: default: act.showMessage(R.string.internal_error); break; case QUERY_TOO_SHORT: act.showMessage(R.string.query_too_short); break; case EMPTY_RESULT_SET: act.showMessage(R.string.no_bus_stop_have_this_name); break; } } } diff --git a/src/it/reyboz/bustorino/fragments/ResultListFragment.java b/src/it/reyboz/bustorino/fragments/ResultListFragment.java index fb17b48..d796b29 100644 --- a/src/it/reyboz/bustorino/fragments/ResultListFragment.java +++ b/src/it/reyboz/bustorino/fragments/ResultListFragment.java @@ -1,314 +1,298 @@ /* BusTO - Fragments components Copyright (C) 2016 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.fragments; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.*; import android.support.design.widget.FloatingActionButton; import it.reyboz.bustorino.R; import it.reyboz.bustorino.backend.FiveTNormalizer; import it.reyboz.bustorino.backend.Palina; import it.reyboz.bustorino.backend.Route; import it.reyboz.bustorino.backend.Stop; import it.reyboz.bustorino.middleware.UserDB; /** * This is a generalized fragment that can be used both for * * */ public class ResultListFragment extends Fragment{ // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER static final String LIST_TYPE = "list-type"; - private static final String STOP_TITLE = "messageExtra"; protected static final String LIST_STATE = "list_state"; - private static final String MESSAGE_TEXT_VIEW = "message_text_view"; + protected static final String MESSAGE_TEXT_VIEW = "message_text_view"; private FragmentKind adapterKind; private boolean adapterSet = false; protected FragmentListener mListener; - private TextView messageTextView; - private ImageButton addToFavorites; + protected TextView messageTextView; + protected ListView resultsListView; + private FloatingActionButton fabutton; - private ListView resultsListView; private ListAdapter mListAdapter = null; boolean listShown; private Parcelable mListInstanceState = null; public ResultListFragment() { // Required empty public constructor } public ListView getResultsListView() { return resultsListView; } /** * Use this factory method to create a new instance of * this fragment using the provided parameters. * * @param listType whether the list is used for STOPS or LINES (Orari) * @return A new instance of fragment ResultListFragment. */ public static ResultListFragment newInstance(FragmentKind listType, String eventualStopTitle) { ResultListFragment fragment = new ResultListFragment(); Bundle args = new Bundle(); args.putSerializable(LIST_TYPE, listType); if (eventualStopTitle != null) { - args.putString(STOP_TITLE, eventualStopTitle); + args.putString(ArrivalsFragment.STOP_TITLE, eventualStopTitle); } fragment.setArguments(args); return fragment; } public static ResultListFragment newInstance(FragmentKind listType) { return newInstance(listType, null); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { adapterKind = (FragmentKind) getArguments().getSerializable(LIST_TYPE); } } /** * Check if the last Bus Stop is in the favorites - * @return + * @return true if it iss */ public boolean isStopInFavorites(String busStopId) { boolean found = false; // no stop no party if(busStopId != null) { SQLiteDatabase userDB = new UserDB(getContext()).getReadableDatabase(); found = UserDB.isStopInFavorites(userDB, busStopId); } return found; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_list_view, container, false); messageTextView = (TextView) root.findViewById(R.id.messageTextView); - addToFavorites = (ImageButton) root.findViewById(R.id.addToFavorites); if (adapterKind != null) { resultsListView = (ListView) root.findViewById(R.id.resultsListView); switch (adapterKind) { case STOPS: resultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { /* * Casting because of Javamerda * @url http://stackoverflow.com/questions/30549485/androids-list-view-parameterized-type-in-adapterview-onitemclicklistener */ Stop busStop = (Stop) parent.getItemAtPosition(position); mListener.createFragmentForStop(busStop.ID); } }); // set the textviewMessage setTextViewMessage(getString(R.string.results)); break; case ARRIVALS: resultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { String routeName; Route r = (Route) parent.getItemAtPosition(position); routeName = FiveTNormalizer.routeInternalToDisplay(r.getNameForDisplay()); if (routeName == null) { routeName = r.getNameForDisplay(); } if (r.destinazione == null || r.destinazione.length() == 0) { Toast.makeText(getContext(), getString(R.string.route_towards_unknown, routeName), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getContext(), getString(R.string.route_towards_destination, routeName, r.destinazione), Toast.LENGTH_SHORT).show(); } } }); - String displayName = getArguments().getString(STOP_TITLE); + String displayName = getArguments().getString(ArrivalsFragment.STOP_TITLE); setTextViewMessage(String.format( getString(R.string.passages), displayName)); break; default: throw new IllegalStateException("Argument passed was not of a supported type"); } String probablemessage = getArguments().getString(MESSAGE_TEXT_VIEW); if (probablemessage != null) { //Log.d("BusTO fragment " + this.getTag(), "We have a possible message here in the savedInstaceState: " + probablemessage); messageTextView.setText(probablemessage); messageTextView.setVisibility(View.VISIBLE); } } else Log.d(getString(R.string.list_fragment_debug), "No content root for fragment"); return root; } public boolean isFragmentForTheSameStop(Palina p) { return adapterKind.equals(FragmentKind.ARRIVALS) && getTag().equals(getFragmentTag(p)); } public static String getFragmentTag(Palina p) { return p.ID; } @Override public void onResume() { super.onResume(); //Log.d(getString(R.string.list_fragment_debug),"Fragment restored, saved listAdapter is "+(mListAdapter)); if (mListAdapter != null) { ListAdapter adapter = mListAdapter; mListAdapter = null; - setListAdapter(adapter); + resetListAdapter(adapter); } if (mListInstanceState != null) { Log.d("resultsListView", "trying to restore instance state"); resultsListView.onRestoreInstanceState(mListInstanceState); } switch (adapterKind) { case ARRIVALS: resultsListView.setOnScrollListener(new CommonScrollListener(mListener, true)); fabutton.show(); break; case STOPS: resultsListView.setOnScrollListener(new CommonScrollListener(mListener, false)); break; default: //NONE } mListener.readyGUIfor(adapterKind); } @Override public void onPause() { if (adapterKind.equals(FragmentKind.ARRIVALS)) { SwipeRefreshLayout reflay = (SwipeRefreshLayout) getActivity().findViewById(R.id.listRefreshLayout); reflay.setEnabled(false); Log.d("BusTO Fragment " + this.getTag(), "RefreshLayout disabled"); } super.onPause(); } @Override public void onAttach(Context context) { super.onAttach(context); if (context instanceof FragmentListener) { mListener = (FragmentListener) context; fabutton = (FloatingActionButton) getActivity().findViewById(R.id.floatingActionButton); } else { throw new RuntimeException(context.toString() + " must implement ResultFragmentListener"); } } @Override public void onDetach() { mListener = null; if (fabutton != null) fabutton.show(); super.onDetach(); } @Override public void onDestroyView() { resultsListView = null; //Log.d(getString(R.string.list_fragment_debug), "called onDestroyView"); getArguments().putString(MESSAGE_TEXT_VIEW, messageTextView.getText().toString()); super.onDestroyView(); } @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); Log.d("ResultListFragment", "onViewStateRestored"); if (savedInstanceState != null) { mListInstanceState = savedInstanceState.getParcelable(LIST_STATE); Log.d("ResultListFragment", "listInstanceStatePresent :" + mListInstanceState); } } - public void setListAdapter(ListAdapter adapter) { + protected void resetListAdapter(ListAdapter adapter) { boolean hadAdapter = mListAdapter != null; mListAdapter = adapter; if (resultsListView != null) { resultsListView.setAdapter(adapter); resultsListView.setVisibility(View.VISIBLE); } } + public void setNewListAdapter(ListAdapter adapter){ + resetListAdapter(adapter); + } /** * Set the message textView * @param message the whole message to write in the textView */ public void setTextViewMessage(String message) { messageTextView.setText(message); - switch (adapterKind) { - case ARRIVALS: - addToFavorites.setClickable(true); - addToFavorites.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - // add/remove the stop in the favorites - mListener.toggleLastStopToFavorites(); - } - }); - break; - case STOPS: - addToFavorites.setClickable(false); - addToFavorites.setVisibility(View.INVISIBLE); - break; - } - messageTextView.setVisibility(View.VISIBLE); } } \ No newline at end of file diff --git a/src/it/reyboz/bustorino/fragments/StopListFragment.java b/src/it/reyboz/bustorino/fragments/StopListFragment.java index e27f3de..7f6daa2 100644 --- a/src/it/reyboz/bustorino/fragments/StopListFragment.java +++ b/src/it/reyboz/bustorino/fragments/StopListFragment.java @@ -1,145 +1,145 @@ /* BusTO - Fragments components Copyright (C) 2018 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.fragments; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.util.Log; import it.reyboz.bustorino.backend.Route; import it.reyboz.bustorino.backend.Stop; import it.reyboz.bustorino.middleware.AppDataProvider; import it.reyboz.bustorino.middleware.NextGenDB.Contract.StopsTable; import it.reyboz.bustorino.adapters.StopAdapter; import java.util.Arrays; import java.util.List; public class StopListFragment extends ResultListFragment implements LoaderManager.LoaderCallbacks { private List stopList; private StopAdapter mListAdapter; private static final String[] dataProjection={StopsTable.COL_LINES_STOPPING,StopsTable.COL_PLACE,StopsTable.COL_TYPE,StopsTable.COL_LOCATION}; private static final String KEY_STOP_ID = "stopID"; private static final String WORDS_SEARCHED= "query"; private static final int EXTRA_ID=160; private String searchedWords; public StopListFragment(){ //required empty constructor } public static StopListFragment newInstance(String searchQuery) { Bundle args = new Bundle(); //TODO: search stops inside the DB args.putString(WORDS_SEARCHED,searchQuery); StopListFragment fragment = new StopListFragment(); args.putSerializable(LIST_TYPE,FragmentKind.STOPS); fragment.setArguments(args); return fragment; } public void setStopList(List stopList){ this.stopList = stopList; } @Override public void onResume() { super.onResume(); LoaderManager loaderManager = getLoaderManager(); if(stopList!=null) { mListAdapter = new StopAdapter(getContext(),stopList); - setListAdapter(mListAdapter); + resetListAdapter(mListAdapter); for (int i = 0; i < stopList.size(); i++) { final Bundle b = new Bundle(); b.putString(KEY_STOP_ID, stopList.get(i).ID); loaderManager.restartLoader(i, b, this); } } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); searchedWords = getArguments().getString(WORDS_SEARCHED); } @Override public Loader onCreateLoader(int id, Bundle args) { //The id will be the position of the element in the list Uri.Builder builder = new Uri.Builder(); String stopID = args.getString(KEY_STOP_ID); //Log.d("StopListLoader","Creating loader for stop "+stopID+" in position: "+id); if(stopID!=null) { builder.scheme("content").authority(AppDataProvider.AUTHORITY) .appendPath("stop").appendPath(stopID); CursorLoader cursorLoader = new CursorLoader(getContext(),builder.build(),dataProjection,null,null,null); return cursorLoader; } else return null; } @Override public void onLoadFinished(Loader loader, Cursor data) { //check that we have valid data if(data==null) return; final int numRows = data.getCount(); final int elementIdx = loader.getId(); if (numRows==0) { Log.w(this.getClass().getName(),"No info for stop in position "+elementIdx); return; } else if(numRows>1){ Log.d("StopLoading","we have "+numRows+" rows, should only have 1. Taking the first..."); } final int linesIndex = data.getColumnIndex(StopsTable.COL_LINES_STOPPING); data.moveToFirst(); Stop stopToModify = stopList.get(elementIdx); final String linesStopping = data.getString(linesIndex); stopToModify.setRoutesThatStopHere(Arrays.asList(linesStopping.split(","))); try { final String possibleLocation = data.getString(data.getColumnIndexOrThrow(StopsTable.COL_LOCATION)); if (stopToModify.location == null && possibleLocation != null && !possibleLocation.isEmpty() && !possibleLocation.equals("_")) { stopToModify.location = possibleLocation; } if (stopToModify.type == null) { stopToModify.type = Route.Type.fromCode(data.getInt(data.getColumnIndex(StopsTable.COL_TYPE))); } }catch (IllegalArgumentException arg){ if(arg.getMessage().contains("'location' does not exist")) Log.w("StopLoading","stop with no location found"); } //Log.d("StopListFragmentLoader","Finished parsing data for stop in position "+elementIdx); mListAdapter.notifyDataSetChanged(); } @Override public void onLoaderReset(Loader loader) { loader.abandon(); } }