diff options
-rw-r--r-- | AndroidManifest.xml | 26 | ||||
-rw-r--r-- | res/layout/searchlist_item.xml | 28 | ||||
-rw-r--r-- | res/menu/main.xml | 7 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/activity/MainActivity.java | 33 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/activity/SearchActivity.java | 8 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/adapter/SearchlistAdapter.java | 38 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/asynctask/DownloadObserver.java | 6 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/ItemlistFragment.java | 71 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java | 59 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/QueueFragment.java | 54 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/SearchFragment.java | 242 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java | 36 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java | 31 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java | 35 | ||||
-rw-r--r-- | src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java | 20 |
15 files changed, 562 insertions, 132 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 193d07963..8526dd4d2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -41,13 +41,6 @@ android:name=".activity.MainActivity" android:configChanges="keyboardHidden|orientation" android:label="@string/app_name"> - <meta-data - android:name="android.app.default_searchable" - android:value="de.danoeh.antennapod.activity.SearchActivity"/> - <meta-data - android:name="android.app.searchable" - android:resource="@xml/searchable"/> - <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> @@ -118,12 +111,6 @@ <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="de.danoeh.antennapod.activity.MainActivity"/> - <meta-data - android:name="android.app.default_searchable" - android:value="de.danoeh.antennapod.activity.SearchActivity"/> - <meta-data - android:name="android.app.searchable" - android:resource="@xml/searchable"/> </activity> <activity android:name="de.danoeh.antennapod.activity.ItemviewActivity" @@ -293,19 +280,6 @@ android:label="@string/opml_import_label"> </activity> <activity - android:name=".activity.SearchActivity" - android:configChanges="keyboardHidden|orientation" - android:label="@string/search_results_label" - android:launchMode="singleTop"> - <intent-filter> - <action android:name="android.intent.action.SEARCH"/> - </intent-filter> - - <meta-data - android:name="android.app.searchable" - android:resource="@xml/searchable"/> - </activity> - <activity android:name=".activity.MiroGuideMainActivity" android:label="@string/miro_guide_label"> <meta-data diff --git a/res/layout/searchlist_item.xml b/res/layout/searchlist_item.xml index 889f40eef..c83f34482 100644 --- a/res/layout/searchlist_item.xml +++ b/res/layout/searchlist_item.xml @@ -1,19 +1,16 @@ <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:padding="8dp" > + android:layout_width="match_parent" + android:layout_height="match_parent"> <ImageView android:id="@+id/imgvFeedimage" android:contentDescription="@string/cover_label" - android:layout_width="55dip" - android:layout_height="55dip" + android:layout_width="@dimen/thumbnail_length_itemlist" + android:layout_height="@dimen/thumbnail_length_itemlist" android:layout_alignParentLeft="true" android:layout_centerVertical="true" - android:layout_marginLeft="1dip" - android:layout_marginRight="4dip" - android:cropToPadding="true" /> + android:scaleType="centerCrop"/> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" @@ -21,20 +18,27 @@ android:layout_height="match_parent" android:layout_centerVertical="true" android:layout_toRightOf="@id/imgvFeedimage" - android:orientation="vertical" > + android:orientation="vertical"> <TextView android:id="@+id/txtvTitle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:maxLines="2" - android:textStyle="bold" /> + android:layout_margin="4dp" + android:lines="2" + android:ellipsize="end" + android:textColor="?android:attr/textColorPrimary" + android:textSize="@dimen/text_size_small"/> <TextView android:id="@+id/txtvSubtitle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:textColor="?android:attr/textColorSecondary" /> + android:layout_margin="4dp" + android:lines="1" + android:ellipsize="end" + android:textColor="?android:attr/textColorTertiary" + android:textSize="@dimen/text_size_small"/> </LinearLayout> </RelativeLayout>
\ No newline at end of file diff --git a/res/menu/main.xml b/res/menu/main.xml index bbb4312b4..9e75898d3 100644 --- a/res/menu/main.xml +++ b/res/menu/main.xml @@ -1,12 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto"> - <item - android:id="@id/search_item" - android:icon="?attr/action_search" - android:title="@string/search_label" - custom:showAsAction="ifRoom|collapseActionView" - android:actionViewClass="android.support.v7.widget.SearchView"/> + <item android:id="@+id/show_preferences" android:title="@string/settings_label" diff --git a/src/de/danoeh/antennapod/activity/MainActivity.java b/src/de/danoeh/antennapod/activity/MainActivity.java index 36f6089de..6c39f256c 100644 --- a/src/de/danoeh/antennapod/activity/MainActivity.java +++ b/src/de/danoeh/antennapod/activity/MainActivity.java @@ -75,6 +75,7 @@ public class MainActivity extends ActionBarActivity { @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); + currentTitle = getSupportActionBar().getTitle(); getSupportActionBar().setTitle(drawerTitle); supportInvalidateOptionsMenu(); } @@ -152,7 +153,7 @@ public class MainActivity extends ActionBarActivity { } else if (viewType == NavListAdapter.VIEW_TYPE_SUBSCRIPTION) { Feed feed = itemAccess.getItem(relPos); - currentTitle = feed.getTitle(); + currentTitle = ""; fragment = ItemlistFragment.newInstance(feed.getId()); } @@ -165,6 +166,17 @@ public class MainActivity extends ActionBarActivity { fT.commit(); } + public void loadFeedFragment(long feedID) { + if (feeds != null) { + for (int i = 0; i < feeds.size(); i++) { + if (feeds.get(i).getId() == feedID) { + loadFragment(NavListAdapter.VIEW_TYPE_SUBSCRIPTION, i, null); + break; + } + } + } + } + public void loadChildFragment(Fragment fragment) { if (fragment == null) throw new IllegalArgumentException("fragment = null"); FragmentManager fm = getSupportFragmentManager(); @@ -210,7 +222,7 @@ public class MainActivity extends ActionBarActivity { @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - outState.putString("title", currentTitle.toString()); + outState.putString("title", getSupportActionBar().getTitle().toString()); outState.putInt("selectedNavIndex", selectedNavListIndex); } @@ -263,8 +275,6 @@ public class MainActivity extends ActionBarActivity { @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - boolean drawerOpen = drawerLayout.isDrawerOpen(navList); - menu.findItem(R.id.search_item).setVisible(!drawerOpen); return true; } @@ -274,21 +284,6 @@ public class MainActivity extends ActionBarActivity { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.main, menu); - - SearchManager searchManager = - (SearchManager) getSystemService(Context.SEARCH_SERVICE); - MenuItem searchItem = menu.findItem(R.id.search_item); - SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem); - if (searchView == null) { - MenuItemCompat.setActionView(searchItem, new SearchView(this)); - searchView = (SearchView) MenuItemCompat.getActionView(searchItem); - } - searchView.setIconifiedByDefault(true); - - SearchableInfo info = searchManager.getSearchableInfo(getComponentName()); - searchView.setSearchableInfo( - searchManager.getSearchableInfo(getComponentName())); - return true; } diff --git a/src/de/danoeh/antennapod/activity/SearchActivity.java b/src/de/danoeh/antennapod/activity/SearchActivity.java index f330aeb7d..02c0838b3 100644 --- a/src/de/danoeh/antennapod/activity/SearchActivity.java +++ b/src/de/danoeh/antennapod/activity/SearchActivity.java @@ -58,7 +58,7 @@ public class SearchActivity extends ActionBarActivity implements AdapterView.OnI txtvStatus = (TextView) findViewById(android.R.id.empty); listView.setOnItemClickListener(this); - searchAdapter = new SearchlistAdapter(this, 0, new ArrayList<SearchResult>()); + //searchAdapter = new SearchlistAdapter(this, 0, new ArrayList<SearchResult>()); listView.setAdapter(searchAdapter); listView.setEmptyView(txtvStatus); } @@ -131,7 +131,7 @@ public class SearchActivity extends ActionBarActivity implements AdapterView.OnI @SuppressLint({"NewApi", "NewApi"}) private void handleSearchRequest(final String query) { if (searchAdapter != null) { - searchAdapter.clear(); + // searchAdapter.clear(); searchAdapter.notifyDataSetChanged(); } txtvStatus.setText(R.string.search_status_searching); @@ -154,9 +154,9 @@ public class SearchActivity extends ActionBarActivity implements AdapterView.OnI Log.d(TAG, "Found " + result.size() + " results"); - searchAdapter.clear(); + // searchAdapter.clear(); for (SearchResult s : result) { - searchAdapter.add(s); + // searchAdapter.add(s); } searchAdapter.notifyDataSetChanged(); txtvStatus diff --git a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java index 926a5a5ad..5c6af3943 100644 --- a/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java +++ b/src/de/danoeh/antennapod/adapter/SearchlistAdapter.java @@ -5,6 +5,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; +import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import de.danoeh.antennapod.R; @@ -17,14 +18,32 @@ import de.danoeh.antennapod.feed.SearchResult; import java.util.List; /** List adapter for search activity. */ -public class SearchlistAdapter extends ArrayAdapter<SearchResult> { +public class SearchlistAdapter extends BaseAdapter { - public SearchlistAdapter(Context context, int textViewResourceId, - List<SearchResult> objects) { - super(context, textViewResourceId, objects); - } + private final Context context; + private final ItemAccess itemAccess; + + public SearchlistAdapter(Context context, ItemAccess itemAccess) { + this.context = context; + this.itemAccess = itemAccess; + } + + @Override + public int getCount() { + return itemAccess.getCount(); + } - @Override + @Override + public SearchResult getItem(int position) { + return itemAccess.getItem(position); + } + + @Override + public long getItemId(int position) { + return 0; + } + + @Override public View getView(int position, View convertView, ViewGroup parent) { final Holder holder; SearchResult result = getItem(position); @@ -33,7 +52,7 @@ public class SearchlistAdapter extends ArrayAdapter<SearchResult> { // Inflate Layout if (convertView == null) { holder = new Holder(); - LayoutInflater inflater = (LayoutInflater) getContext() + LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.searchlist_item, null); @@ -78,4 +97,9 @@ public class SearchlistAdapter extends ArrayAdapter<SearchResult> { TextView subtitle; } + public static interface ItemAccess { + int getCount(); + SearchResult getItem(int position); + } + } diff --git a/src/de/danoeh/antennapod/asynctask/DownloadObserver.java b/src/de/danoeh/antennapod/asynctask/DownloadObserver.java index 1e4234aaa..1c5003ab3 100644 --- a/src/de/danoeh/antennapod/asynctask/DownloadObserver.java +++ b/src/de/danoeh/antennapod/asynctask/DownloadObserver.java @@ -67,7 +67,11 @@ public class DownloadObserver { } catch (IllegalArgumentException e) { e.printStackTrace(); } - activity.unbindService(mConnection); + try { + activity.unbindService(mConnection); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } stopRefresher(); } diff --git a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java index de3d48d55..021aa974b 100644 --- a/src/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/src/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -9,9 +9,12 @@ import android.os.Bundle; import android.os.Handler; import android.support.v4.app.ListFragment; import android.support.v7.app.ActionBarActivity; +import android.support.v7.widget.SearchView; import android.text.util.Linkify; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; import android.view.View; import android.widget.ImageView; import android.widget.ListView; @@ -19,6 +22,7 @@ import android.widget.TextView; import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.ItemviewActivity; +import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.DefaultActionButtonCallback; import de.danoeh.antennapod.adapter.InternalFeedItemlistAdapter; import de.danoeh.antennapod.asynctask.DownloadObserver; @@ -33,6 +37,7 @@ import de.danoeh.antennapod.service.download.Downloader; import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.storage.DownloadRequester; import de.danoeh.antennapod.util.QueueAccess; +import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -61,8 +66,6 @@ public class ItemlistFragment extends ListFragment { private boolean itemsLoaded = false; private boolean viewsCreated = false; - private AtomicReference<Activity> activity = new AtomicReference<Activity>(); - private DownloadObserver downloadObserver; private List<Downloader> downloaderList; @@ -88,6 +91,7 @@ public class ItemlistFragment extends ListFragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); + setHasOptionsMenu(true); Bundle args = getArguments(); if (args == null) throw new IllegalArgumentException("args invalid"); @@ -100,6 +104,13 @@ public class ItemlistFragment extends ListFragment { public void onStart() { super.onStart(); EventDistributor.getInstance().register(contentUpdate); + if (downloadObserver != null) { + downloadObserver.setActivity(getActivity()); + downloadObserver.onResume(); + } + if (viewsCreated && itemsLoaded) { + onFragmentLoaded(); + } } @Override @@ -107,6 +118,7 @@ public class ItemlistFragment extends ListFragment { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); stopItemLoader(); + resetViewState(); } @Override @@ -119,9 +131,12 @@ public class ItemlistFragment extends ListFragment { public void onDetach() { super.onDetach(); stopItemLoader(); + resetViewState(); + } + + private void resetViewState() { adapter = null; viewsCreated = false; - activity.set(null); if (downloadObserver != null) { downloadObserver.onPause(); } @@ -129,21 +144,33 @@ public class ItemlistFragment extends ListFragment { } @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - this.activity.set(activity); - if (downloadObserver != null) { - downloadObserver.setActivity(activity); - downloadObserver.onResume(); - } - if (viewsCreated && itemsLoaded) { - onFragmentLoaded(); - } + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + final SearchView sv = new SearchView(getActivity()); + MenuItemUtils.addSearchItem(menu, sv); + sv.setQueryHint(getString(R.string.search_hint)); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + if (itemsLoaded) { + ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s, feed.getId())); + } + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + ((ActionBarActivity)getActivity()).getSupportActionBar().setTitle(""); + viewsCreated = true; if (itemsLoaded) { onFragmentLoaded(); @@ -153,15 +180,7 @@ public class ItemlistFragment extends ListFragment { @Override public void onListItemClick(ListView l, View v, int position, long id) { FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount()); - /* - Intent showItem = new Intent(getActivity(), ItemviewActivity.class); - showItem.putExtra(FeedlistFragment.EXTRA_SELECTED_FEED, selection - .getFeed().getId()); - showItem.putExtra(EXTRA_SELECTED_FEEDITEM, selection.getId()); - - startActivity(showItem); - */ - feedItemDialog = new FeedItemDialog(activity.get(), selection, queue); + feedItemDialog = new FeedItemDialog(getActivity(), selection, queue); feedItemDialog.show(); } @@ -200,9 +219,9 @@ public class ItemlistFragment extends ListFragment { if (adapter == null) { getListView().setAdapter(null); setupHeaderView(); - adapter = new InternalFeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(activity.get()), false); + adapter = new InternalFeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false); setListAdapter(adapter); - downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback); + downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback); downloadObserver.onResume(); } setListShown(true); @@ -243,7 +262,7 @@ public class ItemlistFragment extends ListFragment { return; } LayoutInflater inflater = (LayoutInflater) - activity.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE); + getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); View header = inflater.inflate(R.layout.feeditemlist_header, null); getListView().addHeaderView(header); @@ -311,7 +330,7 @@ public class ItemlistFragment extends ListFragment { @Override protected Object[] doInBackground(Long... params) { long feedID = params[0]; - Context context = activity.get(); + Context context = getActivity(); if (context != null) { return new Object[]{DBReader.getFeed(context, feedID), QueueAccess.IDListAccess(DBReader.getQueueIDList(context))}; diff --git a/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java index c2dccd820..95b50f62b 100644 --- a/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java +++ b/src/de/danoeh/antennapod/fragment/NewEpisodesFragment.java @@ -6,9 +6,8 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.support.v7.widget.SearchView; +import android.view.*; import android.widget.AdapterView; import android.widget.ProgressBar; import android.widget.TextView; @@ -25,6 +24,7 @@ import de.danoeh.antennapod.feed.FeedMedia; import de.danoeh.antennapod.service.download.Downloader; import de.danoeh.antennapod.storage.DBReader; import de.danoeh.antennapod.util.QueueAccess; +import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -64,14 +64,28 @@ public class NewEpisodesFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); + setHasOptionsMenu(true); startItemLoader(); } @Override + public void onResume() { + super.onResume(); + } + + @Override public void onStart() { super.onStart(); EventDistributor.getInstance().register(contentUpdate); + this.activity.set((MainActivity) getActivity()); + if (downloadObserver != null) { + downloadObserver.setActivity(getActivity()); + downloadObserver.onResume(); + } + if (viewsCreated && itemsLoaded) { + onFragmentLoaded(); + } } @Override @@ -79,26 +93,22 @@ public class NewEpisodesFragment extends Fragment { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); stopItemLoader(); + resetViewState(); } @Override public void onAttach(Activity activity) { super.onAttach(activity); - this.activity.set((MainActivity) activity); - if (downloadObserver != null) { - downloadObserver.setActivity(activity); - downloadObserver.onResume(); - } - if (viewsCreated && itemsLoaded) { - onFragmentLoaded(); - } - - + this.activity.set((MainActivity) getActivity()); } @Override public void onDetach() { super.onDetach(); + resetViewState(); + } + + private void resetViewState() { listAdapter = null; activity.set(null); viewsCreated = false; @@ -109,8 +119,31 @@ public class NewEpisodesFragment extends Fragment { } @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + final SearchView sv = new SearchView(getActivity()); + MenuItemUtils.addSearchItem(menu, sv); + sv.setQueryHint(getString(R.string.search_hint)); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s)); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + } + + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); + ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.new_episodes_label); + View root = inflater.inflate(R.layout.new_episodes_fragment, container, false); listView = (DragSortListView) root.findViewById(android.R.id.list); txtvEmpty = (TextView) root.findViewById(android.R.id.empty); diff --git a/src/de/danoeh/antennapod/fragment/QueueFragment.java b/src/de/danoeh/antennapod/fragment/QueueFragment.java index f9b00a616..838da7e6a 100644 --- a/src/de/danoeh/antennapod/fragment/QueueFragment.java +++ b/src/de/danoeh/antennapod/fragment/QueueFragment.java @@ -7,10 +7,10 @@ import android.os.Bundle; import android.os.Handler; import android.os.Parcelable; import android.support.v4.app.Fragment; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.view.*; import android.widget.AdapterView; import android.widget.ProgressBar; import android.widget.TextView; @@ -30,6 +30,7 @@ import de.danoeh.antennapod.storage.DBWriter; import de.danoeh.antennapod.util.QueueAccess; import de.danoeh.antennapod.util.UndoBarController; import de.danoeh.antennapod.util.gui.FeedItemUndoToken; +import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -71,6 +72,8 @@ public class QueueFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); + setHasOptionsMenu(true); + startItemLoader(); } @@ -78,6 +81,14 @@ public class QueueFragment extends Fragment { public void onStart() { super.onStart(); EventDistributor.getInstance().register(contentUpdate); + this.activity.set((MainActivity) getActivity()); + if (downloadObserver != null) { + downloadObserver.setActivity(getActivity()); + downloadObserver.onResume(); + } + if (viewsCreated && itemsLoaded) { + onFragmentLoaded(); + } } @Override @@ -85,26 +96,22 @@ public class QueueFragment extends Fragment { super.onStop(); EventDistributor.getInstance().unregister(contentUpdate); stopItemLoader(); + resetViewState(); } @Override public void onAttach(Activity activity) { super.onAttach(activity); this.activity.set((MainActivity) activity); - if (downloadObserver != null) { - downloadObserver.setActivity(activity); - downloadObserver.onResume(); - } - if (viewsCreated && itemsLoaded) { - onFragmentLoaded(); - } - - } @Override public void onDetach() { super.onDetach(); + resetViewState(); + } + + private void resetViewState() { listAdapter = null; undoBarController = null; activity.set(null); @@ -117,8 +124,31 @@ public class QueueFragment extends Fragment { } @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + final SearchView sv = new SearchView(getActivity()); + MenuItemUtils.addSearchItem(menu, sv); + sv.setQueryHint(getString(R.string.search_hint)); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s)); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + } + + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); + ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.queue_label); + View root = inflater.inflate(R.layout.queue_fragment, container, false); listView = (DragSortListView) root.findViewById(android.R.id.list); txtvEmpty = (TextView) root.findViewById(android.R.id.empty); diff --git a/src/de/danoeh/antennapod/fragment/SearchFragment.java b/src/de/danoeh/antennapod/fragment/SearchFragment.java new file mode 100644 index 000000000..268e36c37 --- /dev/null +++ b/src/de/danoeh/antennapod/fragment/SearchFragment.java @@ -0,0 +1,242 @@ +package de.danoeh.antennapod.fragment; + +import android.content.Context; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.v4.app.ListFragment; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.app.ActionBarActivity; +import android.support.v7.widget.SearchView; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.ListView; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.adapter.SearchlistAdapter; +import de.danoeh.antennapod.dialog.FeedItemDialog; +import de.danoeh.antennapod.feed.*; +import de.danoeh.antennapod.storage.DBReader; +import de.danoeh.antennapod.storage.FeedSearcher; +import de.danoeh.antennapod.util.QueueAccess; + +import java.util.List; + +/** + * Performs a search operation on all feeds or one specific feed and displays the search result. + */ +public class SearchFragment extends ListFragment { + private static final String TAG = "SearchFragment"; + + private static final String ARG_QUERY = "query"; + private static final String ARG_FEED = "feed"; + + private SearchlistAdapter searchAdapter; + private List<SearchResult> searchResults; + + private boolean viewCreated = false; + private boolean itemsLoaded = false; + + private QueueAccess queue; + + private FeedItemDialog feedItemDialog; + + /** + * Create a new SearchFragment that searches all feeds. + */ + public static SearchFragment newInstance(String query) { + if (query == null) query = ""; + SearchFragment fragment = new SearchFragment(); + Bundle args = new Bundle(); + args.putString(ARG_QUERY, query); + args.putLong(ARG_FEED, 0); + fragment.setArguments(args); + return fragment; + } + + /** + * Create a new SearchFragment that searches one specific feed. + */ + public static SearchFragment newInstance(String query, long feed) { + SearchFragment fragment = newInstance(query); + fragment.getArguments().putLong(ARG_FEED, feed); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setRetainInstance(true); + setHasOptionsMenu(true); + startSearchTask(); + } + + @Override + public void onStart() { + super.onStart(); + EventDistributor.getInstance().register(contentUpdate); + } + + @Override + public void onStop() { + super.onStop(); + stopSearchTask(); + EventDistributor.getInstance().unregister(contentUpdate); + } + + @Override + public void onDetach() { + super.onDetach(); + stopSearchTask(); + searchAdapter = null; + viewCreated = false; + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(R.string.search_label); + viewCreated = true; + if (itemsLoaded) { + onFragmentLoaded(); + } + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + super.onListItemClick(l, v, position, id); + SearchResult result = (SearchResult) l.getAdapter().getItem(position); + FeedComponent comp = result.getComponent(); + if (comp.getClass() == Feed.class) { + ((MainActivity)getActivity()).loadFeedFragment(comp.getId()); + } else { + if (comp.getClass() == FeedItem.class) { + feedItemDialog = new FeedItemDialog(getActivity(), (FeedItem) comp, queue); + feedItemDialog.show(); + } + } + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label); + MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); + final SearchView sv = new SearchView(getActivity()); + sv.setQueryHint(getString(R.string.search_hint)); + sv.setQuery(getArguments().getString(ARG_QUERY), false); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + getArguments().putString(ARG_QUERY, s); + itemsLoaded = false; + startSearchTask(); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + MenuItemCompat.setActionView(item, sv); + } + + private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { + @Override + public void update(EventDistributor eventDistributor, Integer arg) { + if ((arg & (EventDistributor.DOWNLOAD_QUEUED)) != 0) { + feedItemDialog.updateMenuAppearance(); + } + if ((arg & (EventDistributor.UNREAD_ITEMS_UPDATE + | EventDistributor.DOWNLOAD_HANDLED + | EventDistributor.QUEUE_UPDATE)) != 0) { + startSearchTask(); + } + } + }; + + private void onFragmentLoaded() { + if (searchAdapter == null) { + searchAdapter = new SearchlistAdapter(getActivity(), itemAccess); + setListAdapter(searchAdapter); + } + searchAdapter.notifyDataSetChanged(); + setListShown(true); + if (feedItemDialog != null && feedItemDialog.isShowing()) { + feedItemDialog.setQueue(queue); + for (SearchResult result : searchResults) { + FeedComponent comp = result.getComponent(); + if (comp.getClass() == FeedItem.class && ((FeedItem) comp).getId() == feedItemDialog.getItem().getId()) { + feedItemDialog.setItem((FeedItem) comp); + } + } + feedItemDialog.updateMenuAppearance(); + } + } + + private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() { + @Override + public int getCount() { + return (searchResults != null) ? searchResults.size() : 0; + } + + @Override + public SearchResult getItem(int position) { + return (searchResults != null) ? searchResults.get(position) : null; + } + }; + + private SearchTask searchTask; + + private void startSearchTask() { + if (searchTask != null) { + searchTask.cancel(true); + } + searchTask = new SearchTask(); + searchTask.execute(getArguments()); + } + + private void stopSearchTask() { + if (searchTask != null) { + searchTask.cancel(true); + } + } + + private class SearchTask extends AsyncTask<Bundle, Void, Object[]> { + @Override + protected Object[] doInBackground(Bundle... params) { + String query = params[0].getString(ARG_QUERY); + long feed = params[0].getLong(ARG_FEED); + Context context = getActivity(); + if (context != null) { + return new Object[]{FeedSearcher.performSearch(context, query, feed), + QueueAccess.IDListAccess(DBReader.getQueueIDList(context))}; + } else { + return null; + } + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + if (viewCreated && !itemsLoaded) { + setListShown(false); + } + } + + @Override + protected void onPostExecute(Object[] results) { + super.onPostExecute(results); + if (results != null) { + itemsLoaded = true; + searchResults = (List<SearchResult>) results[0]; + queue = (QueueAccess) results[1]; + if (viewCreated) { + onFragmentLoaded(); + } + } + } + } +} diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index acfc57fd8..837df0594 100644 --- a/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/src/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -5,19 +5,22 @@ import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v7.widget.*; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; +import android.view.*; import android.widget.*; +import android.widget.SearchView; import de.danoeh.antennapod.BuildConfig; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity; +import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.adapter.gpodnet.PodcastListAdapter; +import de.danoeh.antennapod.fragment.SearchFragment; import de.danoeh.antennapod.gpoddernet.GpodnetService; import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.List; @@ -33,6 +36,33 @@ public abstract class PodcastListFragment extends Fragment { private Button butRetry; @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + final android.support.v7.widget.SearchView sv = new android.support.v7.widget.SearchView(getActivity()); + MenuItemUtils.addSearchItem(menu, sv); + sv.setQueryHint(getString(R.string.gpodnet_search_hint)); + sv.setOnQueryTextListener(new android.support.v7.widget.SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + ((MainActivity) getActivity()).loadChildFragment(SearchListFragment.newInstance(s)); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + } + + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.gpodnet_podcast_list, container, false); diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java index 322d13097..79d0c5d6f 100644 --- a/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java +++ b/src/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java @@ -1,14 +1,21 @@ package de.danoeh.antennapod.fragment.gpodnet; import android.os.Bundle; +import android.support.v7.widget.SearchView; +import android.view.Menu; +import android.view.MenuInflater; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.fragment.SearchFragment; import de.danoeh.antennapod.gpoddernet.GpodnetService; import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; import de.danoeh.antennapod.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.List; /** - * Created by daniel on 23.08.13. + * Performs a search on the gpodder.net directory and displays the results. */ public class SearchListFragment extends PodcastListFragment { private static final String ARG_QUERY = "query"; @@ -26,6 +33,7 @@ public class SearchListFragment extends PodcastListFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if (getArguments() != null && getArguments().containsKey(ARG_QUERY)) { this.query = getArguments().getString(ARG_QUERY); } else { @@ -34,6 +42,27 @@ public class SearchListFragment extends PodcastListFragment { } @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + final SearchView sv = new SearchView(getActivity()); + MenuItemUtils.addSearchItem(menu, sv); + sv.setQueryHint(getString(R.string.gpodnet_search_hint)); + sv.setQuery(query, false); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + changeQuery(s); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + } + + @Override protected List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException { return service.searchPodcasts(query, 0); } diff --git a/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java index 7ff1bf596..80e896c0f 100644 --- a/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java +++ b/src/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java @@ -1,19 +1,23 @@ package de.danoeh.antennapod.fragment.gpodnet; import android.content.Context; -import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.ListFragment; +import android.support.v7.widget.SearchView; +import android.view.Menu; +import android.view.MenuInflater; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.TextView; +import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; -import de.danoeh.antennapod.activity.gpoddernet.GpodnetTagActivity; +import de.danoeh.antennapod.fragment.SearchFragment; import de.danoeh.antennapod.gpoddernet.GpodnetService; import de.danoeh.antennapod.gpoddernet.GpodnetServiceException; import de.danoeh.antennapod.gpoddernet.model.GpodnetTag; +import de.danoeh.antennapod.util.menuhandler.MenuItemUtils; import java.util.ArrayList; import java.util.List; @@ -23,6 +27,33 @@ public class TagListFragment extends ListFragment { private static final int COUNT = 50; @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + final SearchView sv = new SearchView(getActivity()); + MenuItemUtils.addSearchItem(menu, sv); + sv.setQueryHint(getString(R.string.search_hint)); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + ((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance(s)); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + } + + @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); diff --git a/src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java b/src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java new file mode 100644 index 000000000..e75fa394a --- /dev/null +++ b/src/de/danoeh/antennapod/util/menuhandler/MenuItemUtils.java @@ -0,0 +1,20 @@ +package de.danoeh.antennapod.util.menuhandler; + +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; +import android.view.Menu; +import android.view.MenuItem; +import de.danoeh.antennapod.R; + +/** + * Utilities for menu items + */ +public class MenuItemUtils { + + public static MenuItem addSearchItem(Menu menu, SearchView searchView) { + MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label); + MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_IF_ROOM); + MenuItemCompat.setActionView(item, searchView); + return item; + } +} |