mirror of
https://github.com/sismics/docs.git
synced 2024-11-22 14:07:55 +01:00
Android: Searching
This commit is contained in:
parent
c610364ef7
commit
1773998ca0
@ -102,6 +102,7 @@
|
||||
<orderEntry type="library" exported="" name="support-annotations-21.0.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" />
|
||||
<orderEntry type="library" exported="" name="support-v4-21.0.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="eventbus-2.4.0" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-query.0.26.8" level="project" />
|
||||
<orderEntry type="library" exported="" name="appcompat-v7-21.0.2" level="project" />
|
||||
<orderEntry type="library" exported="" name="android-async-http-1.4.6" level="project" />
|
||||
|
@ -35,4 +35,5 @@ dependencies {
|
||||
compile 'com.android.support:recyclerview-v7:21.0.0'
|
||||
compile 'com.loopj.android:android-async-http:1.4.6'
|
||||
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
|
||||
compile 'de.greenrobot:eventbus:2.4.0'
|
||||
}
|
||||
|
@ -27,12 +27,19 @@
|
||||
android:label="@string/app_name"
|
||||
android:logo="@drawable/ic_launcher"
|
||||
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.DocumentActivity"
|
||||
android:label=""
|
||||
android:logo="@drawable/ic_launcher">
|
||||
</activity>
|
||||
<provider android:name=".provider.RecentSuggestionsProvider"
|
||||
android:exported="false"
|
||||
android:authorities="com.sismics.docs.provider.RecentSuggestionsProvider" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
@ -23,7 +23,6 @@ public class MainApplication extends Application {
|
||||
// TODO Fullscreen preview
|
||||
// TODO Sharing
|
||||
// TODO Error feedback
|
||||
// TODO Searching
|
||||
// TODO Printing
|
||||
|
||||
super.onCreate();
|
||||
|
@ -1,18 +1,28 @@
|
||||
package com.sismics.docs.activity;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.provider.SearchRecentSuggestions;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
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.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.event.SearchEvent;
|
||||
import com.sismics.docs.model.application.ApplicationContext;
|
||||
import com.sismics.docs.provider.RecentSuggestionsProvider;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
* Main activity.
|
||||
@ -21,8 +31,8 @@ import com.sismics.docs.model.application.ApplicationContext;
|
||||
*/
|
||||
public class MainActivity extends ActionBarActivity {
|
||||
|
||||
private ListView drawerList;
|
||||
private ActionBarDrawerToggle drawerToggle;
|
||||
private MenuItem searchItem;
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle args) {
|
||||
@ -38,30 +48,27 @@ public class MainActivity extends ActionBarActivity {
|
||||
// Setup the activity
|
||||
setContentView(R.layout.main_activity);
|
||||
|
||||
// Cache view references
|
||||
// Enable ActionBar app icon to behave as action to toggle nav drawer
|
||||
DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
drawerList = (ListView) findViewById(R.id.drawer_list);
|
||||
|
||||
// Drawer item click listener
|
||||
drawerList.setOnItemClickListener(new ListView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
}
|
||||
});
|
||||
|
||||
if (drawerLayout != null) {
|
||||
// Enable ActionBar app icon to behave as action to toggle nav drawer
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
}
|
||||
|
||||
// ActionBarDrawerToggle ties together the the proper interactions
|
||||
// between the sliding drawer and the action bar app icon
|
||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
|
||||
R.string.drawer_open, R.string.drawer_close);
|
||||
drawerLayout.setDrawerListener(drawerToggle);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
}
|
||||
|
||||
// ActionBarDrawerToggle ties together the the proper interactions
|
||||
// between the sliding drawer and the action bar app icon
|
||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
|
||||
R.string.drawer_open, R.string.drawer_close);
|
||||
drawerLayout.setDrawerListener(drawerToggle);
|
||||
|
||||
// Fill the drawer user info
|
||||
JSONObject userInfo = ApplicationContext.getInstance().getUserInfo();
|
||||
TextView usernameTextView = (TextView) findViewById(R.id.usernameTextView);
|
||||
usernameTextView.setText(userInfo.optString("username"));
|
||||
TextView emailTextView = (TextView) findViewById(R.id.emailTextView);
|
||||
emailTextView.setText(userInfo.optString("email"));
|
||||
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,7 +77,7 @@ public class MainActivity extends ActionBarActivity {
|
||||
case android.R.id.home:
|
||||
// The action bar home/up action should open or close the drawer.
|
||||
// ActionBarDrawerToggle will take care of this.
|
||||
if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
|
||||
if (drawerToggle.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
@ -83,24 +90,69 @@ public class MainActivity extends ActionBarActivity {
|
||||
@Override
|
||||
protected void onPostCreate(Bundle savedInstanceState) {
|
||||
super.onPostCreate(savedInstanceState);
|
||||
if (drawerToggle != null) {
|
||||
// Sync the toggle state after onRestoreInstanceState has occurred.
|
||||
drawerToggle.syncState();
|
||||
}
|
||||
// Sync the toggle state after onRestoreInstanceState has occurred.
|
||||
drawerToggle.syncState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
if (drawerToggle != null) {
|
||||
// Pass any configuration change to the drawer toggle
|
||||
drawerToggle.onConfigurationChanged(newConfig);
|
||||
}
|
||||
// Pass any configuration change to the drawer toggle
|
||||
drawerToggle.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt("drawerItemSelected", drawerList.getCheckedItemPosition());
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.main_activity, menu);
|
||||
|
||||
// Get the SearchView and set the searchable configuration
|
||||
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
|
||||
searchItem = menu.findItem(R.id.action_search);
|
||||
SearchView searchView = (SearchView) searchItem.getActionView();
|
||||
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
|
||||
|
||||
searchView.setOnCloseListener(new SearchView.OnCloseListener() {
|
||||
@Override
|
||||
public boolean onClose() {
|
||||
EventBus.getDefault().post(new SearchEvent(null));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
setIntent(intent);
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the incoming intent.
|
||||
*
|
||||
* @param intent Intent
|
||||
*/
|
||||
private void handleIntent(Intent intent) {
|
||||
// Intent is consumed
|
||||
setIntent(null);
|
||||
|
||||
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
|
||||
// Perform a search query
|
||||
String query = intent.getStringExtra(SearchManager.QUERY);
|
||||
|
||||
// Collapse the SearchView
|
||||
if (searchItem != null) {
|
||||
searchItem.collapseActionView();
|
||||
}
|
||||
|
||||
// Save the query
|
||||
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(this, RecentSuggestionsProvider.AUTHORITY, RecentSuggestionsProvider.MODE);
|
||||
suggestions.saveRecentQuery(query, null);
|
||||
|
||||
EventBus.getDefault().post(new SearchEvent(query));
|
||||
}
|
||||
}
|
||||
}
|
@ -88,14 +88,21 @@ public class DocListAdapter extends RecyclerView.Adapter<DocListAdapter.ViewHold
|
||||
return documents.optJSONObject(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the documents.
|
||||
*/
|
||||
public void clearDocuments() {
|
||||
documents = new JSONArray();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add documents to display.
|
||||
*
|
||||
* @param documents Documents
|
||||
* @param reset Reset the list
|
||||
*/
|
||||
public void addDocuments(JSONArray documents, boolean reset) {
|
||||
if (this.documents == null || reset) {
|
||||
public void addDocuments(JSONArray documents) {
|
||||
if (this.documents == null) {
|
||||
this.documents = new JSONArray();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
package com.sismics.docs.event;
|
||||
|
||||
/**
|
||||
* Search event.
|
||||
*
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class SearchEvent {
|
||||
/**
|
||||
* Search query.
|
||||
*/
|
||||
private String query;
|
||||
|
||||
/**
|
||||
* Create a search event.
|
||||
*
|
||||
* @param query Query
|
||||
*/
|
||||
public SearchEvent(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of query.
|
||||
*
|
||||
* @return query
|
||||
*/
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
}
|
@ -14,12 +14,15 @@ import com.sismics.docs.DividerItemDecoration;
|
||||
import com.sismics.docs.R;
|
||||
import com.sismics.docs.activity.DocumentActivity;
|
||||
import com.sismics.docs.adapter.DocListAdapter;
|
||||
import com.sismics.docs.event.SearchEvent;
|
||||
import com.sismics.docs.listener.RecyclerItemClickListener;
|
||||
import com.sismics.docs.resource.DocumentResource;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
* @author bgamard.
|
||||
*/
|
||||
@ -27,12 +30,16 @@ public class DocListFragment extends Fragment {
|
||||
/**
|
||||
* Documents adapter.
|
||||
*/
|
||||
DocListAdapter adapter;
|
||||
private DocListAdapter adapter;
|
||||
|
||||
/**
|
||||
* Search query.
|
||||
*/
|
||||
private String query;
|
||||
|
||||
// Infinite scrolling things
|
||||
private boolean loading = true;
|
||||
private int previousTotal = 0;
|
||||
int firstVisibleItem, visibleItemCount, totalItemCount;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@ -69,9 +76,9 @@ public class DocListFragment extends Fragment {
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
|
||||
visibleItemCount = recyclerView.getChildCount();
|
||||
totalItemCount = layoutManager.getItemCount();
|
||||
firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
|
||||
int visibleItemCount = recyclerView.getChildCount();
|
||||
int totalItemCount = layoutManager.getItemCount();
|
||||
int firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
|
||||
|
||||
if (loading) {
|
||||
if (totalItemCount > previousTotal) {
|
||||
@ -80,26 +87,54 @@ public class DocListFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
if (!loading && totalItemCount - visibleItemCount <= firstVisibleItem + 3) {
|
||||
loadDocuments();
|
||||
loadDocuments(false);
|
||||
loading = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Grab the documents
|
||||
loadDocuments();
|
||||
loadDocuments(true);
|
||||
|
||||
EventBus.getDefault().register(this);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
EventBus.getDefault().unregister(this);
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/**
|
||||
* A search event has been fired.
|
||||
*
|
||||
* @param event Search event
|
||||
*/
|
||||
public void onEvent(SearchEvent event) {
|
||||
query = event.getQuery();
|
||||
loadDocuments(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the document list.
|
||||
*
|
||||
* @param reset If true, reload the documents
|
||||
*/
|
||||
private void loadDocuments() {
|
||||
DocumentResource.list(getActivity(), adapter.getItemCount(), new JsonHttpResponseHandler() {
|
||||
private void loadDocuments(final boolean reset) {
|
||||
if (reset) {
|
||||
loading = true;
|
||||
previousTotal = 0;
|
||||
adapter.clearDocuments();
|
||||
if (getView() != null) {
|
||||
getView().findViewById(R.id.progressBar).setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
DocumentResource.list(getActivity(), reset ? 0 : adapter.getItemCount(), query, new JsonHttpResponseHandler() {
|
||||
@Override
|
||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
||||
adapter.addDocuments(response.optJSONArray("documents"), false);
|
||||
adapter.addDocuments(response.optJSONArray("documents"));
|
||||
if (getView() != null) {
|
||||
getView().findViewById(R.id.progressBar).setVisibility(View.GONE);
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
package com.sismics.docs.provider;
|
||||
|
||||
import android.content.SearchRecentSuggestionsProvider;
|
||||
|
||||
/**
|
||||
* Search recent suggestions provider.
|
||||
*
|
||||
* @author bgamard.
|
||||
*/
|
||||
public class RecentSuggestionsProvider extends SearchRecentSuggestionsProvider {
|
||||
public final static String AUTHORITY = "com.sismics.docs.provider.RecentSuggestionsProvider";
|
||||
public final static int MODE = DATABASE_MODE_QUERIES;
|
||||
|
||||
public RecentSuggestionsProvider() {
|
||||
setupSuggestions(AUTHORITY, MODE);
|
||||
}
|
||||
}
|
@ -15,9 +15,11 @@ public class DocumentResource extends BaseResource {
|
||||
* GET /document/list.
|
||||
*
|
||||
* @param context Context
|
||||
* @param offset Offset
|
||||
* @param query Search query
|
||||
* @param responseHandler Callback
|
||||
*/
|
||||
public static void list(Context context, int offset, JsonHttpResponseHandler responseHandler) {
|
||||
public static void list(Context context, int offset, String query, JsonHttpResponseHandler responseHandler) {
|
||||
init(context);
|
||||
|
||||
RequestParams params = new RequestParams();
|
||||
@ -25,6 +27,7 @@ public class DocumentResource extends BaseResource {
|
||||
params.put("offset", offset);
|
||||
params.put("sort_column", 3);
|
||||
params.put("asc", false);
|
||||
params.put("search", query);
|
||||
client.get(getApiUrl(context) + "/document/list", params, responseHandler);
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 2.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 3.6 KiB |
@ -18,12 +18,40 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
android:background="#fff"
|
||||
android:elevation="5dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#aaa"
|
||||
android:padding="12dp"
|
||||
android:orientation="vertical"
|
||||
android:elevation="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/usernameTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#fff"
|
||||
android:fontFamily="sans-serif"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/emailTextView"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#fff"
|
||||
android:fontFamily="sans-serif-light"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ListView
|
||||
android:id="@+id/drawer_list"
|
||||
android:layout_weight="1"
|
||||
android:id="@+id/tagListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:choiceMode="singleChoice"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="0dp" />
|
||||
|
8
docs-android/app/src/main/res/menu/main_activity.xml
Normal file
8
docs-android/app/src/main/res/menu/main_activity.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item android:id="@+id/action_search"
|
||||
android:title="@string/action_search"
|
||||
app:showAsAction="ifRoom"
|
||||
app:actionViewClass="android.support.v7.widget.SearchView" />
|
||||
</menu>
|
@ -30,5 +30,6 @@
|
||||
<string name="downloading_file">Downloading file number %1s</string>
|
||||
<string name="download_document">Download all files</string>
|
||||
<string name="downloading_document">Downloading document</string>
|
||||
<string name="action_search">Search documents</string>
|
||||
|
||||
</resources>
|
||||
|
7
docs-android/app/src/main/res/xml/searchable.xml
Normal file
7
docs-android/app/src/main/res/xml/searchable.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:label="@string/app_name"
|
||||
android:hint="@string/action_search"
|
||||
android:searchSuggestAuthority="com.sismics.docs.provider.RecentSuggestionsProvider"
|
||||
android:searchSuggestSelection=" ?">
|
||||
</searchable>
|
Loading…
Reference in New Issue
Block a user