├── .gitignore ├── LICENSE.txt ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── 0_height.png ├── 14zhou.gif ├── 150696.gif ├── 1506tq.gif ├── 1508kn.gif ├── 150sde.gif ├── 150sg9.gif ├── 150sox.gif ├── device-2015-12-06-215814.png ├── device-2015-12-08-123103.png ├── full_height.png ├── inaction.gif ├── intermediate.png ├── search_bar.png ├── style_dark.png ├── style_light.png ├── suggestions.png ├── vf2c2.gif ├── vf2ii.gif ├── vf2lz.gif ├── vf2oi.gif ├── vf353.gif ├── vf91i.gif └── vf9cp.gif ├── library-rxbinding-kotlin ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── kotlin │ └── com │ └── arlib │ └── floatingsearchview │ └── rxbinding │ └── RxFloatingSearchView.kt ├── library-rxbinding ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── arlib │ └── floatingsearchbiew │ └── rxbinding │ ├── QueryObservable.java │ └── RxFloatingSearchView.java ├── library ├── .gitignore ├── build.gradle ├── consumer-proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── arlib │ │ └── floatingsearchview │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── arlib │ │ └── floatingsearchview │ │ ├── FloatingSearchView.java │ │ ├── suggestions │ │ ├── SearchSuggestionsAdapter.java │ │ └── model │ │ │ └── SearchSuggestion.java │ │ └── util │ │ ├── MenuPopupHelper.java │ │ ├── Util.java │ │ ├── adapter │ │ ├── GestureDetectorListenerAdapter.java │ │ ├── OnItemTouchListenerAdapter.java │ │ └── TextWatcherAdapter.java │ │ └── view │ │ ├── MenuView.java │ │ └── SearchInputView.java │ └── res │ ├── drawable-hdpi │ ├── ic_arrow_back_black_24dp.png │ ├── ic_clear_black_24dp.png │ ├── ic_history_black_24dp.png │ ├── ic_invert_colors_black_24dp.png │ ├── ic_mic_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ └── ic_search_black_24dp.png │ ├── drawable-mdpi │ ├── ic_arrow_back_black_24dp.png │ ├── ic_clear_black_24dp.png │ ├── ic_history_black_24dp.png │ ├── ic_invert_colors_black_24dp.png │ ├── ic_mic_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ └── ic_search_black_24dp.png │ ├── drawable-v21 │ ├── oval_btn_selector.xml │ ├── rect_btn_selector.xml │ └── suggestion_item_background.xml │ ├── drawable-xhdpi │ ├── ic_arrow_back_black_24dp.png │ ├── ic_clear_black_24dp.png │ ├── ic_history_black_24dp.png │ ├── ic_invert_colors_black_24dp.png │ ├── ic_mic_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ └── ic_search_black_24dp.png │ ├── drawable-xxhdpi │ ├── ic_arrow_back_black_24dp.png │ ├── ic_clear_black_24dp.png │ ├── ic_history_black_24dp.png │ ├── ic_invert_colors_black_24dp.png │ ├── ic_mic_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ └── ic_search_black_24dp.png │ ├── drawable-xxxhdpi │ ├── ic_arrow_back_black_24dp.png │ ├── ic_clear_black_24dp.png │ ├── ic_history_black_24dp.png │ ├── ic_invert_colors_black_24dp.png │ ├── ic_mic_black_24dp.png │ ├── ic_more_vert_black_24dp.png │ └── ic_search_black_24dp.png │ ├── drawable │ ├── divider_background.xml │ ├── oval_btn_selector.xml │ └── suggestion_item_background.xml │ ├── layout │ ├── action_item_layout.xml │ ├── floating_search_layout.xml │ ├── overflow_action_item_layout.xml │ ├── search_query_section.xml │ ├── search_suggestion_item.xml │ └── search_suggestions_section.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ └── dimens.xml ├── sample ├── .gitignore ├── build.gradle ├── libs │ └── gson-2.4.jar ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── arlib │ │ └── floatingsearchviewdemo │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── assets │ └── colors.json │ ├── java │ └── com │ │ └── arlib │ │ └── floatingsearchviewdemo │ │ ├── MainActivity.java │ │ ├── adapter │ │ └── SearchResultsListAdapter.java │ │ ├── data │ │ ├── ColorSuggestion.java │ │ ├── ColorWrapper.java │ │ └── DataHelper.java │ │ └── fragment │ │ ├── BaseExampleFragment.java │ │ ├── ScrollingSearchExampleFragment.java │ │ ├── SlidingSearchResultsExampleFragment.java │ │ └── SlidingSearchViewExampleFragment.java │ └── res │ ├── drawable-hdpi │ ├── ic_invert_colors_black_24dp.png │ ├── ic_keyboard_voice_black_24dp.png │ ├── ic_lightbulb_outline_black_24dp.png │ ├── ic_local_taxi_black_24dp.png │ ├── ic_my_location_black_24dp.png │ └── ic_restaurant_menu_black_24dp.png │ ├── drawable-mdpi │ ├── ic_invert_colors_black_24dp.png │ ├── ic_keyboard_voice_black_24dp.png │ ├── ic_lightbulb_outline_black_24dp.png │ ├── ic_local_taxi_black_24dp.png │ ├── ic_my_location_black_24dp.png │ └── ic_restaurant_menu_black_24dp.png │ ├── drawable-xhdpi │ ├── ic_invert_colors_black_24dp.png │ ├── ic_keyboard_voice_black_24dp.png │ ├── ic_lightbulb_outline_black_24dp.png │ ├── ic_local_taxi_black_24dp.png │ ├── ic_my_location_black_24dp.png │ └── ic_restaurant_menu_black_24dp.png │ ├── drawable-xxhdpi │ ├── ic_invert_colors_black_24dp.png │ ├── ic_keyboard_voice_black_24dp.png │ ├── ic_lightbulb_outline_black_24dp.png │ ├── ic_local_taxi_black_24dp.png │ ├── ic_my_location_black_24dp.png │ └── ic_restaurant_menu_black_24dp.png │ ├── drawable-xxxhdpi │ ├── ic_invert_colors_black_24dp.png │ ├── ic_keyboard_voice_black_24dp.png │ ├── ic_lightbulb_outline_black_24dp.png │ ├── ic_local_taxi_black_24dp.png │ ├── ic_my_location_black_24dp.png │ └── ic_restaurant_menu_black_24dp.png │ ├── drawable │ └── circle_background.xml │ ├── layout │ ├── activity_main.xml │ ├── fragment_scrolling_search_example.xml │ ├── fragment_sliding_search_example.xml │ ├── fragment_sliding_search_results_example_fragment.xml │ └── search_results_list_item.xml │ ├── menu │ ├── menu_app.xml │ └── menu_search_view.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ └── values │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | /notes 11 | *.iml 12 | **/build 13 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Floating Search View [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Floating%20Search%20View-green.svg?style=true)](https://android-arsenal.com/details/1/2842) 2 | ============= 3 | 4 | An implementation of a floating search box with search suggestions, also called persistent search bar. 5 | 6 | ![Alt text](/images/150696.gif) 7 | ![Alt text](/images/1506tq.gif) 8 | ![Alt text](/images/1508kn.gif) 9 | 10 | 11 | Note 12 | ----- 13 | 14 | This project is not being actively maintained. Have a look [here](https://github.com/arimorty/floatingsearchview/wiki) for information 15 | that might help you make changes to your own copy of the code base. 16 | 17 | 18 | ... 19 | 20 | 21 | Usage 22 | ----- 23 | 24 | 1. In your dependencies, add 25 | ``` 26 | compile 'com.github.arimorty:floatingsearchview:2.1.1' 27 | ``` 28 | 2. Add a FloatingSearchView to your view hierarchy, and make sure that it takes 29 | up the full width and height of the screen 30 | 3. Listen to query changes and provide suggestion items that implement SearchSuggestion 31 | 32 | **Example:** 33 | 34 | ```xml 35 | 48 | ``` 49 | 50 | ``` 51 | mSearchView.setOnQueryChangeListener(new FloatingSearchView.OnQueryChangeListener() { 52 | @Override 53 | public void onSearchTextChanged(String oldQuery, final String newQuery) { 54 | 55 | //get suggestions based on newQuery 56 | 57 | //pass them on to the search view 58 | mSearchView.swapSuggestions(newSuggestions); 59 | } 60 | }); 61 | ``` 62 |
63 | 64 | **Left action mode:** 65 | 66 | The left action can be configured as follows: 67 | 68 | Add 69 | ```xml 70 | app:floatingSearch_leftActionMode="[insert one of the options from table below]" 71 | ``` 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 |
showHamburger
showSearch
showHome
noLeftAction
90 | 91 | Listen to *hamburger* button clicks: 92 | ``` 93 | mSearchView.setOnLeftMenuClickListener( 94 | new FloatingSearchView.OnLeftMenuClickListener() { ...} ); 95 | ``` 96 | 97 | To quickly connect your **NavigationDrawer** to the *hamburger* button: 98 | ``` 99 | mSearchView.attachNavigationDrawerToMenuButton(mDrawerLayout); 100 | ``` 101 | 102 | Listen to home (back arrow) button clicks: 103 | ``` 104 | mSearchView.setOnHomeActionClickListener( 105 | new FloatingSearchView.OnHomeActionClickListener() { ... }); 106 | ``` 107 | 108 |
109 | 110 | **Configure menu items:** 111 | 112 | ![Alt text](/images/150sg9.gif) 113 | 114 | Add a menu resource 115 | ```xml 116 | app:floatingSearch_menu="@menu/menu_main" 117 | ``` 118 | 119 | In the menu resource, set items' ```app:showAsAction="[insert one of the options described in the table below]"``` 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 132 | 133 | 134 | 135 | 136 | 137 |
neverPuts the menu item in the overflow options popup
ifRoomShows an action icon for the menu if the following conditions are met: 129 | 1. The search is not focused. 130 | 2. There is enough room for it. 131 |
alwaysShows an action icon for the menu if there is room, regardless of whether the search is focused or not.
138 | 139 | Listen for item selections 140 | ``` 141 | mSearchView.setOnMenuItemClickListener(new FloatingSearchView.OnMenuItemClickListener() { 142 | @Override 143 | public void onMenuItemSelected(MenuItem item) { 144 | 145 | } 146 | }); 147 | ``` 148 | 149 |
150 | 151 | 152 | **Configure suggestion item:** 153 | 154 | First, implement [SearchSuggestion](https://github.com/arimorty/floatingsearchview/blob/master/library/src/main/java/com/arlib/floatingsearchview/suggestions/model/SearchSuggestion.java) 155 | 156 | *Optional*: 157 | 158 | Set a callback for when a given suggestion is bound to the suggestion list. 159 | 160 | For the history icons to show, you would need to implement this. Refer to the sample app for an [example implementation](https://github.com/arimorty/floatingsearchview/blob/master/sample/src/main/java/com/arlib/floatingsearchviewdemo/fragment/ScrollingSearchExampleFragment.java#L222). 161 | ``` 162 | mSearchView.setOnBindSuggestionCallback(new SearchSuggestionsAdapter.OnBindSuggestionCallback() { 163 | @Override 164 | public void onBindSuggestion(View suggestionView, ImageView leftIcon, TextView textView, SearchSuggestion item, int itemPosition) { 165 | 166 | //here you can set some attributes for the suggestion's left icon and text. For example, 167 | //you can choose your favorite image-loading library for setting the left icon's image. 168 | } 169 | 170 | }); 171 | ``` 172 | 173 |
174 | 175 | **Styling:** 176 | 177 | 178 | 179 | 180 | Available styling: 181 | 182 | ```xml 183 | 195 | ``` 196 | ### RxBinding Extension 197 | The RxBinding library allows you to listen for query changes using RxJava Obervables. 198 | 199 | ```java 200 | Observable queryObservable = RxFloatingSearchView.queryChanges(view); 201 | queryObservable.doOnNext { query -> Toast.makeText(this, "Query is %s".format(query), Toast.LENGTH_LONG).show() }.subscribe(); 202 | ``` 203 | 204 | ### The Kotlin Extension 205 | The Kotlin extension adds an extension function to the view for more goodness. 206 | 207 | ```kotlin 208 | view.queryChanges(5).doOnNext { query -> Toast.makeText(this, "Query is %s".format(query), Toast.LENGTH_LONG).show() }.subscribe() 209 | ``` 210 | 211 | 212 | License 213 | ======= 214 | 215 | Copyright (C) 2015 Ari C. 216 | 217 | Licensed under the Apache License, Version 2.0 (the "License"); 218 | you may not use this file except in compliance with the License. 219 | You may obtain a copy of the License at 220 | 221 | http://www.apache.org/licenses/LICENSE-2.0 222 | 223 | Unless required by applicable law or agreed to in writing, software 224 | distributed under the License is distributed on an "AS IS" BASIS, 225 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 226 | See the License for the specific language governing permissions and 227 | limitations under the License. 228 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.3.0' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenCentral() 18 | jcenter() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Apr 16 14:28:23 EDT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /images/0_height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/0_height.png -------------------------------------------------------------------------------- /images/14zhou.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/14zhou.gif -------------------------------------------------------------------------------- /images/150696.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/150696.gif -------------------------------------------------------------------------------- /images/1506tq.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/1506tq.gif -------------------------------------------------------------------------------- /images/1508kn.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/1508kn.gif -------------------------------------------------------------------------------- /images/150sde.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/150sde.gif -------------------------------------------------------------------------------- /images/150sg9.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/150sg9.gif -------------------------------------------------------------------------------- /images/150sox.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/150sox.gif -------------------------------------------------------------------------------- /images/device-2015-12-06-215814.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/device-2015-12-06-215814.png -------------------------------------------------------------------------------- /images/device-2015-12-08-123103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/device-2015-12-08-123103.png -------------------------------------------------------------------------------- /images/full_height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/full_height.png -------------------------------------------------------------------------------- /images/inaction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/inaction.gif -------------------------------------------------------------------------------- /images/intermediate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/intermediate.png -------------------------------------------------------------------------------- /images/search_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/search_bar.png -------------------------------------------------------------------------------- /images/style_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/style_dark.png -------------------------------------------------------------------------------- /images/style_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/style_light.png -------------------------------------------------------------------------------- /images/suggestions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/suggestions.png -------------------------------------------------------------------------------- /images/vf2c2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf2c2.gif -------------------------------------------------------------------------------- /images/vf2ii.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf2ii.gif -------------------------------------------------------------------------------- /images/vf2lz.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf2lz.gif -------------------------------------------------------------------------------- /images/vf2oi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf2oi.gif -------------------------------------------------------------------------------- /images/vf353.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf353.gif -------------------------------------------------------------------------------- /images/vf91i.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf91i.gif -------------------------------------------------------------------------------- /images/vf9cp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/images/vf9cp.gif -------------------------------------------------------------------------------- /library-rxbinding-kotlin/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.1.2-3' 3 | repositories { 4 | mavenCentral() 5 | } 6 | dependencies { 7 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 8 | } 9 | } 10 | 11 | apply plugin: 'com.android.library' 12 | apply plugin: 'kotlin-android' 13 | 14 | android { 15 | compileSdkVersion 25 16 | buildToolsVersion '25.0.3' 17 | 18 | defaultConfig { 19 | minSdkVersion 14 20 | targetSdkVersion 25 21 | versionCode 11 22 | versionName "2.0.4" 23 | } 24 | sourceSets{ 25 | main.java.srcDirs += 'src/main/kotlin' 26 | } 27 | } 28 | 29 | dependencies { 30 | compile project(path: ':library-rxbinding') 31 | compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 32 | } 33 | 34 | sourceCompatibility = "1.7" 35 | targetCompatibility = "1.7" 36 | -------------------------------------------------------------------------------- /library-rxbinding-kotlin/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library-rxbinding-kotlin/src/main/kotlin/com/arlib/floatingsearchview/rxbinding/RxFloatingSearchView.kt: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.rxbinding 2 | 3 | import com.arlib.floatingsearchbiew.rxbinding.RxFloatingSearchView 4 | import com.arlib.floatingsearchview.FloatingSearchView 5 | import com.jakewharton.rxbinding2.InitialValueObservable 6 | 7 | inline fun FloatingSearchView.queryChanges(minQueryLimit: Int = 1): InitialValueObservable = RxFloatingSearchView.queryChanges(this, minQueryLimit) -------------------------------------------------------------------------------- /library-rxbinding/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'maven-publish' 3 | 4 | android { 5 | compileSdkVersion 25 6 | buildToolsVersion '25.0.3' 7 | 8 | defaultConfig { 9 | minSdkVersion 14 10 | targetSdkVersion 25 11 | versionCode 11 12 | versionName "2.0.4" 13 | } 14 | } 15 | 16 | dependencies { 17 | compile 'com.android.support:support-annotations:25.3.1' 18 | compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0' 19 | compile project(path: ':library') 20 | } 21 | 22 | sourceCompatibility = "1.7" 23 | targetCompatibility = "1.7" 24 | -------------------------------------------------------------------------------- /library-rxbinding/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library-rxbinding/src/main/java/com/arlib/floatingsearchbiew/rxbinding/QueryObservable.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchbiew.rxbinding; 2 | 3 | import com.arlib.floatingsearchview.FloatingSearchView; 4 | import com.jakewharton.rxbinding2.InitialValueObservable; 5 | 6 | import io.reactivex.Observer; 7 | import io.reactivex.android.MainThreadDisposable; 8 | 9 | final public class QueryObservable extends InitialValueObservable { 10 | 11 | private final FloatingSearchView view; 12 | 13 | private final int minQueryLength; 14 | 15 | public QueryObservable(FloatingSearchView view) { 16 | this(view, 1); 17 | } 18 | 19 | public QueryObservable(FloatingSearchView view, int minQueryLength) { 20 | this.view = view; 21 | this.minQueryLength = minQueryLength; 22 | } 23 | 24 | @Override 25 | protected void subscribeListener(Observer observer) { 26 | Listener listener = new Listener(view, observer, minQueryLength); 27 | observer.onSubscribe(listener); 28 | view.setOnQueryChangeListener(listener); 29 | } 30 | 31 | @Override 32 | protected CharSequence getInitialValue() { 33 | return view.getQuery(); 34 | } 35 | 36 | final static class Listener extends MainThreadDisposable implements FloatingSearchView.OnQueryChangeListener { 37 | 38 | private final FloatingSearchView view; 39 | private final Observer observer; 40 | private final int minQueryLength; 41 | 42 | public Listener(FloatingSearchView view, Observer observer, int minQueryLength) { 43 | this.view = view; 44 | this.observer = observer; 45 | this.minQueryLength = minQueryLength; 46 | } 47 | 48 | @Override 49 | public void onSearchTextChanged(String oldQuery, String newQuery) { 50 | if(!isDisposed() && newQuery != null && newQuery.length() >= minQueryLength) { 51 | observer.onNext(newQuery); 52 | } 53 | } 54 | 55 | @Override 56 | protected void onDispose() { 57 | view.setOnQueryChangeListener(null); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /library-rxbinding/src/main/java/com/arlib/floatingsearchbiew/rxbinding/RxFloatingSearchView.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchbiew.rxbinding; 2 | 3 | import android.support.annotation.CheckResult; 4 | import android.support.annotation.NonNull; 5 | 6 | import com.arlib.floatingsearchview.FloatingSearchView; 7 | import com.jakewharton.rxbinding2.InitialValueObservable; 8 | 9 | public final class RxFloatingSearchView { 10 | 11 | @CheckResult 12 | @NonNull 13 | public static InitialValueObservable queryChanges( 14 | @NonNull FloatingSearchView view) { 15 | return queryChanges(view, 1); 16 | } 17 | 18 | @CheckResult 19 | @NonNull 20 | public static InitialValueObservable queryChanges( 21 | @NonNull FloatingSearchView view, int characterLimit) { 22 | checkNotNull(view, "view == null"); 23 | return new QueryObservable(view, characterLimit); 24 | } 25 | 26 | public static void checkNotNull(Object value, String message) { 27 | if (value == null) { 28 | throw new NullPointerException(message); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | gradle.properties 3 | maven-push.gradle 4 | .idea 5 | *.iml -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion '25.0.3' 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 25 10 | versionCode 13 11 | versionName "2.1.1" 12 | //consumerProguardFiles 'consumer-proguard-rules.txt' 13 | } 14 | } 15 | 16 | dependencies { 17 | compile fileTree(dir: 'libs', include: ['*.jar']) 18 | compile 'com.android.support:appcompat-v7:25.3.1' 19 | compile 'com.android.support:recyclerview-v7:25.3.1' 20 | compile 'com.android.support:design:25.3.1' 21 | compile 'com.android.support:cardview-v7:25.3.1' 22 | compile 'com.bartoszlipinski:viewpropertyobjectanimator:1.2.0' 23 | } 24 | 25 | //enable when uploading lib// apply from: 'maven-push.gradle' -------------------------------------------------------------------------------- /library/consumer-proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\ari\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Support libs 20 | -dontwarn android.support.v7.** 21 | -keep class android.support.v7.** { *; } 22 | -keep interface android.support.v7.** { *; } 23 | 24 | -keep class com.bartoszlipinski.** { *; } 25 | -keep interface com.bartoszlipinski.** { *; } 26 | 27 | # Keep all floatingsearchview classes 28 | -keep class com.arlib.** { *; } -------------------------------------------------------------------------------- /library/src/androidTest/java/com/arlib/floatingsearchview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/suggestions/SearchSuggestionsAdapter.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.suggestions; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.content.Context; 20 | import android.graphics.drawable.Drawable; 21 | import android.support.v4.graphics.drawable.DrawableCompat; 22 | import android.support.v7.widget.RecyclerView; 23 | import android.util.TypedValue; 24 | import android.view.LayoutInflater; 25 | import android.view.View; 26 | import android.view.ViewGroup; 27 | import android.widget.ImageView; 28 | import android.widget.TextView; 29 | 30 | import com.arlib.floatingsearchview.R; 31 | import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion; 32 | import com.arlib.floatingsearchview.util.Util; 33 | 34 | import java.util.ArrayList; 35 | import java.util.Collections; 36 | import java.util.List; 37 | 38 | public class SearchSuggestionsAdapter extends RecyclerView.Adapter { 39 | 40 | private static final String TAG = "SearchSuggestionsAdapter"; 41 | 42 | private List mSearchSuggestions = new ArrayList<>(); 43 | 44 | private Listener mListener; 45 | 46 | private Context mContext; 47 | 48 | private Drawable mRightIconDrawable; 49 | private boolean mShowRightMoveUpBtn = false; 50 | private int mBodyTextSizePx; 51 | private int mTextColor = -1; 52 | private int mRightIconColor = -1; 53 | 54 | public interface OnBindSuggestionCallback { 55 | 56 | void onBindSuggestion(View suggestionView, ImageView leftIcon, TextView textView, 57 | SearchSuggestion item, int itemPosition); 58 | } 59 | 60 | private OnBindSuggestionCallback mOnBindSuggestionCallback; 61 | 62 | public interface Listener { 63 | 64 | void onItemSelected(SearchSuggestion item); 65 | 66 | void onMoveItemToSearchClicked(SearchSuggestion item); 67 | } 68 | 69 | public static class SearchSuggestionViewHolder extends RecyclerView.ViewHolder { 70 | 71 | public TextView body; 72 | public ImageView leftIcon; 73 | public ImageView rightIcon; 74 | 75 | private Listener mListener; 76 | 77 | public interface Listener { 78 | 79 | void onItemClicked(int adapterPosition); 80 | 81 | void onMoveItemToSearchClicked(int adapterPosition); 82 | } 83 | 84 | public SearchSuggestionViewHolder(View v, Listener listener) { 85 | super(v); 86 | 87 | mListener = listener; 88 | body = (TextView) v.findViewById(R.id.body); 89 | leftIcon = (ImageView) v.findViewById(R.id.left_icon); 90 | rightIcon = (ImageView) v.findViewById(R.id.right_icon); 91 | 92 | rightIcon.setOnClickListener(new View.OnClickListener() { 93 | @Override 94 | public void onClick(View v) { 95 | 96 | int adapterPosition = getAdapterPosition(); 97 | if (mListener != null && adapterPosition != RecyclerView.NO_POSITION) { 98 | mListener.onMoveItemToSearchClicked(getAdapterPosition()); 99 | } 100 | } 101 | }); 102 | 103 | itemView.setOnClickListener(new View.OnClickListener() { 104 | @Override 105 | public void onClick(View v) { 106 | 107 | int adapterPosition = getAdapterPosition(); 108 | if (mListener != null && adapterPosition != RecyclerView.NO_POSITION) { 109 | mListener.onItemClicked(adapterPosition); 110 | } 111 | } 112 | }); 113 | } 114 | } 115 | 116 | public SearchSuggestionsAdapter(Context context, int suggestionTextSize, Listener listener) { 117 | this.mContext = context; 118 | this.mListener = listener; 119 | this.mBodyTextSizePx = suggestionTextSize; 120 | 121 | mRightIconDrawable = Util.getWrappedDrawable(mContext, R.drawable.ic_arrow_back_black_24dp); 122 | DrawableCompat.setTint(mRightIconDrawable, Util.getColor(mContext, R.color.gray_active_icon)); 123 | } 124 | 125 | public void swapData(List searchSuggestions) { 126 | mSearchSuggestions = searchSuggestions; 127 | notifyDataSetChanged(); 128 | } 129 | 130 | public List getDataSet() { 131 | return mSearchSuggestions; 132 | } 133 | 134 | public void setOnBindSuggestionCallback(OnBindSuggestionCallback callback) { 135 | this.mOnBindSuggestionCallback = callback; 136 | } 137 | 138 | @Override 139 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 140 | 141 | View view = LayoutInflater.from(viewGroup.getContext()) 142 | .inflate(R.layout.search_suggestion_item, viewGroup, false); 143 | SearchSuggestionViewHolder viewHolder = new SearchSuggestionViewHolder(view, 144 | new SearchSuggestionViewHolder.Listener() { 145 | 146 | @Override 147 | public void onItemClicked(int adapterPosition) { 148 | 149 | if (mListener != null) { 150 | mListener.onItemSelected(mSearchSuggestions.get(adapterPosition)); 151 | } 152 | } 153 | 154 | @Override 155 | public void onMoveItemToSearchClicked(int adapterPosition) { 156 | 157 | if (mListener != null) { 158 | mListener.onMoveItemToSearchClicked(mSearchSuggestions 159 | .get(adapterPosition)); 160 | } 161 | } 162 | 163 | }); 164 | 165 | viewHolder.rightIcon.setImageDrawable(mRightIconDrawable); 166 | viewHolder.body.setTextSize(TypedValue.COMPLEX_UNIT_PX, mBodyTextSizePx); 167 | 168 | return viewHolder; 169 | } 170 | 171 | @Override 172 | public void onBindViewHolder(RecyclerView.ViewHolder vh, int position) { 173 | 174 | SearchSuggestionViewHolder viewHolder = (SearchSuggestionViewHolder) vh; 175 | 176 | if (!mShowRightMoveUpBtn) { 177 | viewHolder.rightIcon.setEnabled(false); 178 | viewHolder.rightIcon.setVisibility(View.INVISIBLE); 179 | } else { 180 | viewHolder.rightIcon.setEnabled(true); 181 | viewHolder.rightIcon.setVisibility(View.VISIBLE); 182 | } 183 | 184 | SearchSuggestion suggestionItem = mSearchSuggestions.get(position); 185 | viewHolder.body.setText(suggestionItem.getBody()); 186 | 187 | if(mTextColor != -1){ 188 | viewHolder.body.setTextColor(mTextColor); 189 | } 190 | 191 | if(mRightIconColor != -1){ 192 | Util.setIconColor(viewHolder.rightIcon, mRightIconColor); 193 | } 194 | 195 | if (mOnBindSuggestionCallback != null) { 196 | mOnBindSuggestionCallback.onBindSuggestion(viewHolder.itemView, viewHolder.leftIcon, viewHolder.body, 197 | suggestionItem, position); 198 | } 199 | } 200 | 201 | @Override 202 | public int getItemCount() { 203 | return mSearchSuggestions != null ? mSearchSuggestions.size() : 0; 204 | } 205 | 206 | public void setTextColor(int color) { 207 | 208 | boolean notify = false; 209 | if (this.mTextColor != color) { 210 | notify = true; 211 | } 212 | this.mTextColor = color; 213 | if (notify) { 214 | notifyDataSetChanged(); 215 | } 216 | } 217 | 218 | public void setRightIconColor(int color) { 219 | 220 | boolean notify = false; 221 | if (this.mRightIconColor != color) { 222 | notify = true; 223 | } 224 | this.mRightIconColor = color; 225 | if (notify) { 226 | notifyDataSetChanged(); 227 | } 228 | } 229 | 230 | public void setShowMoveUpIcon(boolean show) { 231 | 232 | boolean notify = false; 233 | if (this.mShowRightMoveUpBtn != show) { 234 | notify = true; 235 | } 236 | this.mShowRightMoveUpBtn = show; 237 | if (notify) { 238 | notifyDataSetChanged(); 239 | } 240 | } 241 | 242 | public void reverseList() { 243 | Collections.reverse(mSearchSuggestions); 244 | notifyDataSetChanged(); 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/suggestions/model/SearchSuggestion.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.suggestions.model; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.os.Parcelable; 20 | 21 | /** 22 | * An object that represents a single suggestion item 23 | * in the suggestions drop down generated in response 24 | * to an entered query in the {@link com.arlib.floatingsearchview.FloatingSearchView} 25 | */ 26 | public interface SearchSuggestion extends Parcelable{ 27 | 28 | /** 29 | * Returns the text that should be displayed 30 | * for the suggestion represented by this object. 31 | * 32 | * @return the text for this suggestion 33 | */ 34 | String getBody(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/util/Util.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.util; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import android.content.ContextWrapper; 22 | import android.content.res.Resources; 23 | import android.graphics.drawable.Drawable; 24 | import android.os.Build; 25 | import android.os.Handler; 26 | import android.support.annotation.ColorRes; 27 | import android.support.annotation.DrawableRes; 28 | import android.support.v4.content.ContextCompat; 29 | import android.support.v4.content.res.ResourcesCompat; 30 | import android.support.v4.graphics.drawable.DrawableCompat; 31 | import android.util.DisplayMetrics; 32 | import android.util.TypedValue; 33 | import android.view.Display; 34 | import android.view.View; 35 | import android.view.ViewTreeObserver; 36 | import android.view.inputmethod.InputMethodManager; 37 | import android.widget.EditText; 38 | import android.widget.ImageView; 39 | 40 | public class Util { 41 | 42 | private static final String TAG = "Util"; 43 | 44 | public static void showSoftKeyboard(final Context context, final EditText editText) { 45 | 46 | new Handler().postDelayed(new Runnable() { 47 | @Override 48 | public void run() { 49 | 50 | InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); 51 | inputMethodManager.showSoftInput(editText, InputMethodManager.SHOW_FORCED); 52 | } 53 | }, 100); 54 | } 55 | 56 | public static void closeSoftKeyboard(Activity activity) { 57 | 58 | View currentFocusView = activity.getCurrentFocus(); 59 | if (currentFocusView != null) { 60 | InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); 61 | imm.hideSoftInputFromWindow(currentFocusView.getWindowToken(), 0); 62 | } 63 | } 64 | 65 | public static int dpToPx(int dp) { 66 | DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); 67 | return (int) (dp * metrics.density); 68 | } 69 | 70 | public static int pxToDp(int px) { 71 | DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); 72 | return (int) (px / metrics.density); 73 | } 74 | 75 | public static int spToPx(int sp) { 76 | DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); 77 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, metrics); 78 | } 79 | 80 | public static int pxToSp(int px) { 81 | DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); 82 | return px / (int) metrics.scaledDensity; 83 | } 84 | 85 | public static int getScreenWidth(Activity activity) { 86 | 87 | Display display = activity.getWindowManager().getDefaultDisplay(); 88 | DisplayMetrics outMetrics = new DisplayMetrics(); 89 | display.getMetrics(outMetrics); 90 | 91 | return outMetrics.widthPixels; 92 | } 93 | 94 | public static int getScreenHeight(Activity activity) { 95 | 96 | Display display = activity.getWindowManager().getDefaultDisplay(); 97 | DisplayMetrics outMetrics = new DisplayMetrics(); 98 | display.getMetrics(outMetrics); 99 | 100 | return outMetrics.heightPixels; 101 | } 102 | 103 | public static void setIconColor(ImageView iconHolder, int color) { 104 | Drawable wrappedDrawable = DrawableCompat.wrap(iconHolder.getDrawable()); 105 | DrawableCompat.setTint(wrappedDrawable, color); 106 | iconHolder.setImageDrawable(wrappedDrawable); 107 | iconHolder.invalidate(); 108 | } 109 | 110 | /** 111 | * Gets a reference to a given drawable and prepares it for use with tinting through. 112 | * 113 | * @param resId the resource id for the given drawable 114 | * @return a wrapped drawable ready fo use 115 | * with {@link android.support.v4.graphics.drawable.DrawableCompat}'s tinting methods 116 | * @throws Resources.NotFoundException 117 | */ 118 | public static Drawable getWrappedDrawable(Context context, @DrawableRes int resId) throws Resources.NotFoundException { 119 | return DrawableCompat.wrap(ResourcesCompat.getDrawable(context.getResources(), 120 | resId, null)); 121 | } 122 | 123 | public static int getColor(Context context, @ColorRes int resId) throws Resources.NotFoundException { 124 | return ContextCompat.getColor(context, resId); 125 | } 126 | 127 | public static void removeGlobalLayoutObserver(View view, ViewTreeObserver.OnGlobalLayoutListener layoutListener) { 128 | if (Build.VERSION.SDK_INT < 16) { 129 | view.getViewTreeObserver().removeGlobalOnLayoutListener(layoutListener); 130 | } else { 131 | view.getViewTreeObserver().removeOnGlobalLayoutListener(layoutListener); 132 | } 133 | } 134 | 135 | public static Activity getHostActivity(Context context) { 136 | while (context instanceof ContextWrapper) { 137 | if (context instanceof Activity) { 138 | return (Activity) context; 139 | } 140 | context = ((ContextWrapper) context).getBaseContext(); 141 | } 142 | return null; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/util/adapter/GestureDetectorListenerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.util.adapter; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.view.GestureDetector; 20 | import android.view.MotionEvent; 21 | 22 | public abstract class GestureDetectorListenerAdapter implements 23 | GestureDetector.OnGestureListener{ 24 | 25 | private static final String TAG = "GestureDetectorListenerAdapter"; 26 | 27 | @Override 28 | public boolean onDown(MotionEvent e) { 29 | return false; 30 | } 31 | 32 | @Override 33 | public void onShowPress(MotionEvent e) { 34 | 35 | } 36 | 37 | @Override 38 | public boolean onSingleTapUp(MotionEvent e) { 39 | return false; 40 | } 41 | 42 | @Override 43 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 44 | return false; 45 | } 46 | 47 | @Override 48 | public void onLongPress(MotionEvent e) { 49 | 50 | } 51 | 52 | @Override 53 | public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/util/adapter/OnItemTouchListenerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.util.adapter; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.support.v7.widget.RecyclerView; 20 | import android.view.MotionEvent; 21 | 22 | public abstract class OnItemTouchListenerAdapter implements RecyclerView.OnItemTouchListener { 23 | 24 | private static final String TAG = "OnItemTouchListenerAdapter"; 25 | 26 | @Override 27 | public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) { 28 | return false; 29 | } 30 | 31 | @Override 32 | public void onTouchEvent(RecyclerView rv, MotionEvent e) { 33 | 34 | } 35 | 36 | @Override 37 | public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/util/adapter/TextWatcherAdapter.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.util.adapter; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.text.Editable; 20 | import android.text.TextWatcher; 21 | 22 | public abstract class TextWatcherAdapter implements TextWatcher { 23 | 24 | private static final String TAG = "TextWatcherAdapter"; 25 | 26 | @Override 27 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 28 | 29 | } 30 | 31 | @Override 32 | public void onTextChanged(CharSequence s, int start, int before, int count) { 33 | 34 | } 35 | 36 | @Override 37 | public void afterTextChanged(Editable s) { 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /library/src/main/java/com/arlib/floatingsearchview/util/view/SearchInputView.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchview.util.view; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.KeyEvent; 6 | import android.view.View; 7 | import android.widget.EditText; 8 | 9 | public class SearchInputView extends EditText { 10 | 11 | private OnKeyboardSearchKeyClickListener mSearchKeyListener; 12 | 13 | private OnKeyboardDismissedListener mOnKeyboardDismissedListener; 14 | 15 | private OnKeyListener mOnKeyListener = new OnKeyListener() { 16 | public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { 17 | 18 | if (keyCode == KeyEvent.KEYCODE_ENTER && mSearchKeyListener != null) { 19 | mSearchKeyListener.onSearchKeyClicked(); 20 | return true; 21 | } 22 | return false; 23 | } 24 | }; 25 | 26 | public SearchInputView(Context context) { 27 | super(context); 28 | init(); 29 | } 30 | 31 | public SearchInputView(Context context, AttributeSet attrs) { 32 | super(context, attrs); 33 | init(); 34 | } 35 | 36 | public SearchInputView(Context context, AttributeSet attrs, int defStyle) { 37 | super(context, attrs, defStyle); 38 | init(); 39 | } 40 | 41 | private void init() { 42 | setOnKeyListener(mOnKeyListener); 43 | } 44 | 45 | @Override 46 | public boolean onKeyPreIme(int keyCode, KeyEvent ev) { 47 | if (ev.getKeyCode() == KeyEvent.KEYCODE_BACK && mOnKeyboardDismissedListener != null) { 48 | mOnKeyboardDismissedListener.onKeyboardDismissed(); 49 | } 50 | return super.onKeyPreIme(keyCode, ev); 51 | } 52 | 53 | public void setOnKeyboardDismissedListener(OnKeyboardDismissedListener onKeyboardDismissedListener) { 54 | mOnKeyboardDismissedListener = onKeyboardDismissedListener; 55 | } 56 | 57 | public void setOnSearchKeyListener(OnKeyboardSearchKeyClickListener searchKeyListener) { 58 | mSearchKeyListener = searchKeyListener; 59 | } 60 | 61 | public interface OnKeyboardDismissedListener { 62 | void onKeyboardDismissed(); 63 | } 64 | 65 | public interface OnKeyboardSearchKeyClickListener { 66 | void onSearchKeyClicked(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_clear_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_clear_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_history_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_history_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_mic_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_mic_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-hdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-hdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_clear_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_clear_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_history_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_history_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_mic_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_mic_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-mdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-mdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-v21/oval_btn_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-v21/rect_btn_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-v21/suggestion_item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_clear_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_clear_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_history_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_history_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_mic_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_mic_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xhdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xhdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_clear_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_clear_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_history_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_history_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_mic_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_mic_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxhdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_arrow_back_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_arrow_back_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_clear_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_clear_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_history_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_history_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_mic_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_mic_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_more_vert_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/library/src/main/res/drawable-xxxhdpi/ic_search_black_24dp.png -------------------------------------------------------------------------------- /library/src/main/res/drawable/divider_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/oval_btn_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /library/src/main/res/drawable/suggestion_item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /library/src/main/res/layout/action_item_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /library/src/main/res/layout/floating_search_layout.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /library/src/main/res/layout/overflow_action_item_layout.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /library/src/main/res/layout/search_query_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 17 | 18 | 25 | 26 | 35 | 36 | 43 | 44 | 45 | 54 | 55 | 70 | 71 | 72 | 83 | 84 | 94 | 95 | -------------------------------------------------------------------------------- /library/src/main/res/layout/search_suggestion_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 19 | 20 | 34 | 35 | 48 | 49 | -------------------------------------------------------------------------------- /library/src/main/res/layout/search_suggestions_section.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /library/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #F0F0F0 4 | #000000 5 | #00000000 6 | #33000000 7 | #FAFAFA 8 | #bbbbbb 9 | #FFFFFF 10 | #FFFFFF 11 | #BEBEBE 12 | #787878 13 | #787878 14 | #e9e9e9 15 | #E7E7E7 16 | #FFFFFF 17 | #F0F0F0 18 | #787878 19 | #787878 20 | #787878 21 | #787878 22 | #808080 23 | -------------------------------------------------------------------------------- /library/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 48dp 3 | 4dp 4 | 4dp 5 | 20dp 6 | 68dp 7 | 64dp 8 | 16dp 9 | 3dp 10 | 11 | 12 | 24dp 13 | 48dp 14 | 12dp 15 | 16 | 18sp 17 | 16sp 18 | 19 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion '25.0.3' 6 | 7 | defaultConfig { 8 | applicationId "com.arlib.floatingsearchviewdemo" 9 | minSdkVersion 14 10 | targetSdkVersion 25 11 | versionCode 11 12 | versionName "3.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile project(":library") 25 | compile files('libs/gson-2.4.jar') 26 | compile 'com.android.support:appcompat-v7:25.3.1' 27 | compile 'com.android.support:palette-v7:25.3.1' 28 | compile 'com.android.support:support-v4:25.3.1' 29 | } 30 | -------------------------------------------------------------------------------- /sample/libs/gson-2.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/libs/gson-2.4.jar -------------------------------------------------------------------------------- /sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\ari\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | ##---------------Begin: proguard configuration for Gson ---------- 20 | 21 | #the sample project uses GSON, so if you set minifyEnabled to true, make sure to uncomment the below progaurd rules for GSON 22 | #-keepattributes Signature 23 | #-keepattributes *Annotation* 24 | #-keep class sun.misc.Unsafe { *; } 25 | #-keep class com.google.gson.stream.** { *; } 26 | #-keep class com.google.gson.examples.android.model.** { *; } 27 | 28 | ##---------------End: proguard configuration for Gson ---------- -------------------------------------------------------------------------------- /sample/src/androidTest/java/com/arlib/floatingsearchviewdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /sample/src/main/assets/colors.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "hex": "#EFDECD", 4 | "name": "Almond", 5 | "rgb": "(239, 222, 205)" 6 | }, 7 | { 8 | "hex": "#CD9575", 9 | "name": "Antique Brass", 10 | "rgb": "(205, 149, 117)" 11 | }, 12 | { 13 | "hex": "#FDD9B5", 14 | "name": "Apricot", 15 | "rgb": "(253, 217, 181)" 16 | }, 17 | { 18 | "hex": "#78DBE2", 19 | "name": "Aquamarine", 20 | "rgb": "(120, 219, 226)" 21 | }, 22 | { 23 | "hex": "#87A96B", 24 | "name": "Asparagus", 25 | "rgb": "(135, 169, 107)" 26 | }, 27 | { 28 | "hex": "#FFA474", 29 | "name": "Atomic Tangerine", 30 | "rgb": "(255, 164, 116)" 31 | }, 32 | { 33 | "hex": "#FAE7B5", 34 | "name": "Banana Mania", 35 | "rgb": "(250, 231, 181)" 36 | }, 37 | { 38 | "hex": "#9F8170", 39 | "name": "Beaver", 40 | "rgb": "(159, 129, 112)" 41 | }, 42 | { 43 | "hex": "#FD7C6E", 44 | "name": "Bittersweet", 45 | "rgb": "(253, 124, 110)" 46 | }, 47 | { 48 | "hex": "#000000", 49 | "name": "Black", 50 | "rgb": "(0,0,0)" 51 | }, 52 | { 53 | "hex": "#ACE5EE", 54 | "name": "Blizzard Blue", 55 | "rgb": "(172, 229, 238)" 56 | }, 57 | { 58 | "hex": "#1F75FE", 59 | "name": "Blue", 60 | "rgb": "(31, 117, 254)" 61 | }, 62 | { 63 | "hex": "#A2A2D0", 64 | "name": "Blue Bell", 65 | "rgb": "(162, 162, 208)" 66 | }, 67 | { 68 | "hex": "#6699CC", 69 | "name": "Blue Gray", 70 | "rgb": "(102, 153, 204)" 71 | }, 72 | { 73 | "hex": "#0D98BA", 74 | "name": "Blue Green", 75 | "rgb": "(13, 152, 186)" 76 | }, 77 | { 78 | "hex": "#7366BD", 79 | "name": "Blue Violet", 80 | "rgb": "(115, 102, 189)" 81 | }, 82 | { 83 | "hex": "#DE5D83", 84 | "name": "Blush", 85 | "rgb": "(222, 93, 131)" 86 | }, 87 | { 88 | "hex": "#CB4154", 89 | "name": "Brick Red", 90 | "rgb": "(203, 65, 84)" 91 | }, 92 | { 93 | "hex": "#B4674D", 94 | "name": "Brown", 95 | "rgb": "(180, 103, 77)" 96 | }, 97 | { 98 | "hex": "#FF7F49", 99 | "name": "Burnt Orange", 100 | "rgb": "(255, 127, 73)" 101 | }, 102 | { 103 | "hex": "#EA7E5D", 104 | "name": "Burnt Sienna", 105 | "rgb": "(234, 126, 93)" 106 | }, 107 | { 108 | "hex": "#B0B7C6", 109 | "name": "Cadet Blue", 110 | "rgb": "(176, 183, 198)" 111 | }, 112 | { 113 | "hex": "#FFFF99", 114 | "name": "Canary", 115 | "rgb": "(255, 255, 153)" 116 | }, 117 | { 118 | "hex": "#1CD3A2", 119 | "name": "Caribbean Green", 120 | "rgb": "(28, 211, 162)" 121 | }, 122 | { 123 | "hex": "#FFAACC", 124 | "name": "Carnation Pink", 125 | "rgb": "(255, 170, 204)" 126 | }, 127 | { 128 | "hex": "#DD4492", 129 | "name": "Cerise", 130 | "rgb": "(221, 68, 146)" 131 | }, 132 | { 133 | "hex": "#1DACD6", 134 | "name": "Cerulean", 135 | "rgb": "(29, 172, 214)" 136 | }, 137 | { 138 | "hex": "#BC5D58", 139 | "name": "Chestnut", 140 | "rgb": "(188, 93, 88)" 141 | }, 142 | { 143 | "hex": "#DD9475", 144 | "name": "Copper", 145 | "rgb": "(221, 148, 117)" 146 | }, 147 | { 148 | "hex": "#9ACEEB", 149 | "name": "Cornflower", 150 | "rgb": "(154, 206, 235)" 151 | }, 152 | { 153 | "hex": "#FFBCD9", 154 | "name": "Cotton Candy", 155 | "rgb": "(255, 188, 217)" 156 | }, 157 | { 158 | "hex": "#FDDB6D", 159 | "name": "Dandelion", 160 | "rgb": "(253, 219, 109)" 161 | }, 162 | { 163 | "hex": "#2B6CC4", 164 | "name": "Denim", 165 | "rgb": "(43, 108, 196)" 166 | }, 167 | { 168 | "hex": "#EFCDB8", 169 | "name": "Desert Sand", 170 | "rgb": "(239, 205, 184)" 171 | }, 172 | { 173 | "hex": "#6E5160", 174 | "name": "Eggplant", 175 | "rgb": "(110, 81, 96)" 176 | }, 177 | { 178 | "hex": "#CEFF1D", 179 | "name": "Electric Lime", 180 | "rgb": "(206, 255, 29)" 181 | }, 182 | { 183 | "hex": "#71BC78", 184 | "name": "Fern", 185 | "rgb": "(113, 188, 120)" 186 | }, 187 | { 188 | "hex": "#6DAE81", 189 | "name": "Forest Green", 190 | "rgb": "(109, 174, 129)" 191 | }, 192 | { 193 | "hex": "#C364C5", 194 | "name": "Fuchsia", 195 | "rgb": "(195, 100, 197)" 196 | }, 197 | { 198 | "hex": "#CC6666", 199 | "name": "Fuzzy Wuzzy", 200 | "rgb": "(204, 102, 102)" 201 | }, 202 | { 203 | "hex": "#E7C697", 204 | "name": "Gold", 205 | "rgb": "(231, 198, 151)" 206 | }, 207 | { 208 | "hex": "#FCD975", 209 | "name": "Goldenrod", 210 | "rgb": "(252, 217, 117)" 211 | }, 212 | { 213 | "hex": "#A8E4A0", 214 | "name": "Granny Smith Apple", 215 | "rgb": "(168, 228, 160)" 216 | }, 217 | { 218 | "hex": "#95918C", 219 | "name": "Gray", 220 | "rgb": "(149, 145, 140)" 221 | }, 222 | { 223 | "hex": "#1CAC78", 224 | "name": "Green", 225 | "rgb": "(28, 172, 120)" 226 | }, 227 | { 228 | "hex": "#1164B4", 229 | "name": "Green Blue", 230 | "rgb": "(17, 100, 180)" 231 | }, 232 | { 233 | "hex": "#F0E891", 234 | "name": "Green Yellow", 235 | "rgb": "(240, 232, 145)" 236 | }, 237 | { 238 | "hex": "#FF1DCE", 239 | "name": "Hot Magenta", 240 | "rgb": "(255, 29, 206)" 241 | }, 242 | { 243 | "hex": "#B2EC5D", 244 | "name": "Inchworm", 245 | "rgb": "(178, 236, 93)" 246 | }, 247 | { 248 | "hex": "#5D76CB", 249 | "name": "Indigo", 250 | "rgb": "(93, 118, 203)" 251 | }, 252 | { 253 | "hex": "#CA3767", 254 | "name": "Jazzberry Jam", 255 | "rgb": "(202, 55, 103)" 256 | }, 257 | { 258 | "hex": "#3BB08F", 259 | "name": "Jungle Green", 260 | "rgb": "(59, 176, 143)" 261 | }, 262 | { 263 | "hex": "#FEFE22", 264 | "name": "Laser Lemon", 265 | "rgb": "(254, 254, 34)" 266 | }, 267 | { 268 | "hex": "#FCB4D5", 269 | "name": "Lavender", 270 | "rgb": "(252, 180, 213)" 271 | }, 272 | { 273 | "hex": "#FFF44F", 274 | "name": "Lemon Yellow", 275 | "rgb": "(255, 244, 79)" 276 | }, 277 | { 278 | "hex": "#FFBD88", 279 | "name": "Macaroni and Cheese", 280 | "rgb": "(255, 189, 136)" 281 | }, 282 | { 283 | "hex": "#F664AF", 284 | "name": "Magenta", 285 | "rgb": "(246, 100, 175)" 286 | }, 287 | { 288 | "hex": "#AAF0D1", 289 | "name": "Magic Mint", 290 | "rgb": "(170, 240, 209)" 291 | }, 292 | { 293 | "hex": "#CD4A4C", 294 | "name": "Mahogany", 295 | "rgb": "(205, 74, 76)" 296 | }, 297 | { 298 | "hex": "#EDD19C", 299 | "name": "Maize", 300 | "rgb": "(237, 209, 156)" 301 | }, 302 | { 303 | "hex": "#979AAA", 304 | "name": "Manatee", 305 | "rgb": "(151, 154, 170)" 306 | }, 307 | { 308 | "hex": "#FF8243", 309 | "name": "Mango Tango", 310 | "rgb": "(255, 130, 67)" 311 | }, 312 | { 313 | "hex": "#C8385A", 314 | "name": "Maroon", 315 | "rgb": "(200, 56, 90)" 316 | }, 317 | { 318 | "hex": "#EF98AA", 319 | "name": "Mauvelous", 320 | "rgb": "(239, 152, 170)" 321 | }, 322 | { 323 | "hex": "#FDBCB4", 324 | "name": "Melon", 325 | "rgb": "(253, 188, 180)" 326 | }, 327 | { 328 | "hex": "#1A4876", 329 | "name": "Midnight Blue", 330 | "rgb": "(26, 72, 118)" 331 | }, 332 | { 333 | "hex": "#30BA8F", 334 | "name": "Mountain Meadow", 335 | "rgb": "(48, 186, 143)" 336 | }, 337 | { 338 | "hex": "#C54B8C", 339 | "name": "Mulberry", 340 | "rgb": "(197, 75, 140)" 341 | }, 342 | { 343 | "hex": "#1974D2", 344 | "name": "Navy Blue", 345 | "rgb": "(25, 116, 210)" 346 | }, 347 | { 348 | "hex": "#FFA343", 349 | "name": "Neon Carrot", 350 | "rgb": "(255, 163, 67)" 351 | }, 352 | { 353 | "hex": "#BAB86C", 354 | "name": "Olive Green", 355 | "rgb": "(186, 184, 108)" 356 | }, 357 | { 358 | "hex": "#FF7538", 359 | "name": "Orange", 360 | "rgb": "(255, 117, 56)" 361 | }, 362 | { 363 | "hex": "#FF2B2B", 364 | "name": "Orange Red", 365 | "rgb": "(255, 43, 43)" 366 | }, 367 | { 368 | "hex": "#F8D568", 369 | "name": "Orange Yellow", 370 | "rgb": "(248, 213, 104)" 371 | }, 372 | { 373 | "hex": "#E6A8D7", 374 | "name": "Orchid", 375 | "rgb": "(230, 168, 215)" 376 | }, 377 | { 378 | "hex": "#414A4C", 379 | "name": "Outer Space", 380 | "rgb": "(65, 74, 76)" 381 | }, 382 | { 383 | "hex": "#FF6E4A", 384 | "name": "Outrageous Orange", 385 | "rgb": "(255, 110, 74)" 386 | }, 387 | { 388 | "hex": "#1CA9C9", 389 | "name": "Pacific Blue", 390 | "rgb": "(28, 169, 201)" 391 | }, 392 | { 393 | "hex": "#FFCFAB", 394 | "name": "Peach", 395 | "rgb": "(255, 207, 171)" 396 | }, 397 | { 398 | "hex": "#C5D0E6", 399 | "name": "Periwinkle", 400 | "rgb": "(197, 208, 230)" 401 | }, 402 | { 403 | "hex": "#FDDDE6", 404 | "name": "Piggy Pink", 405 | "rgb": "(253, 221, 230)" 406 | }, 407 | { 408 | "hex": "#158078", 409 | "name": "Pine Green", 410 | "rgb": "(21, 128, 120)" 411 | }, 412 | { 413 | "hex": "#FC74FD", 414 | "name": "Pink Flamingo", 415 | "rgb": "(252, 116, 253)" 416 | }, 417 | { 418 | "hex": "#F78FA7", 419 | "name": "Pink Sherbet", 420 | "rgb": "(247, 143, 167)" 421 | }, 422 | { 423 | "hex": "#8E4585", 424 | "name": "Plum", 425 | "rgb": "(142, 69, 133)" 426 | }, 427 | { 428 | "hex": "#7442C8", 429 | "name": "Purple Heart", 430 | "rgb": "(116, 66, 200)" 431 | }, 432 | { 433 | "hex": "#9D81BA", 434 | "name": "Purple Mountain's Majesty", 435 | "rgb": "(157, 129, 186)" 436 | }, 437 | { 438 | "hex": "#FE4EDA", 439 | "name": "Purple Pizzazz", 440 | "rgb": "(254, 78, 218)" 441 | }, 442 | { 443 | "hex": "#FF496C", 444 | "name": "Radical Red", 445 | "rgb": "(255, 73, 108)" 446 | }, 447 | { 448 | "hex": "#D68A59", 449 | "name": "Raw Sienna", 450 | "rgb": "(214, 138, 89)" 451 | }, 452 | { 453 | "hex": "#714B23", 454 | "name": "Raw Umber", 455 | "rgb": "(113, 75, 35)" 456 | }, 457 | { 458 | "hex": "#FF48D0", 459 | "name": "Razzle Dazzle Rose", 460 | "rgb": "(255, 72, 208)" 461 | }, 462 | { 463 | "hex": "#E3256B", 464 | "name": "Razzmatazz", 465 | "rgb": "(227, 37, 107)" 466 | }, 467 | { 468 | "hex": "#EE204D", 469 | "name": "Red", 470 | "rgb": "(238,32 ,77 )" 471 | }, 472 | { 473 | "hex": "#FF5349", 474 | "name": "Red Orange", 475 | "rgb": "(255, 83, 73)" 476 | }, 477 | { 478 | "hex": "#C0448F", 479 | "name": "Red Violet", 480 | "rgb": "(192, 68, 143)" 481 | }, 482 | { 483 | "hex": "#1FCECB", 484 | "name": "Robin's Egg Blue", 485 | "rgb": "(31, 206, 203)" 486 | }, 487 | { 488 | "hex": "#7851A9", 489 | "name": "Royal Purple", 490 | "rgb": "(120, 81, 169)" 491 | }, 492 | { 493 | "hex": "#FF9BAA", 494 | "name": "Salmon", 495 | "rgb": "(255, 155, 170)" 496 | }, 497 | { 498 | "hex": "#FC2847", 499 | "name": "Scarlet", 500 | "rgb": "(252, 40, 71)" 501 | }, 502 | { 503 | "hex": "#76FF7A", 504 | "name": "Screamin' Green", 505 | "rgb": "(118, 255, 122)" 506 | }, 507 | { 508 | "hex": "#9FE2BF", 509 | "name": "Sea Green", 510 | "rgb": "(159, 226, 191)" 511 | }, 512 | { 513 | "hex": "#A5694F", 514 | "name": "Sepia", 515 | "rgb": "(165, 105, 79)" 516 | }, 517 | { 518 | "hex": "#8A795D", 519 | "name": "Shadow", 520 | "rgb": "(138, 121, 93)" 521 | }, 522 | { 523 | "hex": "#45CEA2", 524 | "name": "Shamrock", 525 | "rgb": "(69, 206, 162)" 526 | }, 527 | { 528 | "hex": "#FB7EFD", 529 | "name": "Shocking Pink", 530 | "rgb": "(251, 126, 253)" 531 | }, 532 | { 533 | "hex": "#CDC5C2", 534 | "name": "Silver", 535 | "rgb": "(205, 197, 194)" 536 | }, 537 | { 538 | "hex": "#80DAEB", 539 | "name": "Sky Blue", 540 | "rgb": "(128, 218, 235)" 541 | }, 542 | { 543 | "hex": "#ECEABE", 544 | "name": "Spring Green", 545 | "rgb": "(236, 234, 190)" 546 | }, 547 | { 548 | "hex": "#FFCF48", 549 | "name": "Sunglow", 550 | "rgb": "(255, 207, 72)" 551 | }, 552 | { 553 | "hex": "#FD5E53", 554 | "name": "Sunset Orange", 555 | "rgb": "(253, 94, 83)" 556 | }, 557 | { 558 | "hex": "#FAA76C", 559 | "name": "Tan", 560 | "rgb": "(250, 167, 108)" 561 | }, 562 | { 563 | "hex": "#18A7B5", 564 | "name": "Teal Blue", 565 | "rgb": "(24, 167, 181)" 566 | }, 567 | { 568 | "hex": "#EBC7DF", 569 | "name": "Thistle", 570 | "rgb": "(235, 199, 223)" 571 | }, 572 | { 573 | "hex": "#FC89AC", 574 | "name": "Tickle Me Pink", 575 | "rgb": "(252, 137, 172)" 576 | }, 577 | { 578 | "hex": "#DBD7D2", 579 | "name": "Timberwolf", 580 | "rgb": "(219, 215, 210)" 581 | }, 582 | { 583 | "hex": "#17806D", 584 | "name": "Tropical Rain Forest", 585 | "rgb": "(23, 128, 109)" 586 | }, 587 | { 588 | "hex": "#DEAA88", 589 | "name": "Tumbleweed", 590 | "rgb": "(222, 170, 136)" 591 | }, 592 | { 593 | "hex": "#77DDE7", 594 | "name": "Turquoise Blue", 595 | "rgb": "(119, 221, 231)" 596 | }, 597 | { 598 | "hex": "#FFFF66", 599 | "name": "Unmellow Yellow", 600 | "rgb": "(255, 255, 102)" 601 | }, 602 | { 603 | "hex": "#926EAE", 604 | "name": "Violet (Purple)", 605 | "rgb": "(146, 110, 174)" 606 | }, 607 | { 608 | "hex": "#324AB2", 609 | "name": "Violet Blue", 610 | "rgb": "(50, 74, 178)" 611 | }, 612 | { 613 | "hex": "#F75394", 614 | "name": "Violet Red", 615 | "rgb": "(247, 83, 148)" 616 | }, 617 | { 618 | "hex": "#FFA089", 619 | "name": "Vivid Tangerine", 620 | "rgb": "(255, 160, 137)" 621 | }, 622 | { 623 | "hex": "#8F509D", 624 | "name": "Vivid Violet", 625 | "rgb": "(143, 80, 157)" 626 | }, 627 | { 628 | "hex": "#FFFFFF", 629 | "name": "White", 630 | "rgb": "(255, 255, 255)" 631 | }, 632 | { 633 | "hex": "#A2ADD0", 634 | "name": "Wild Blue Yonder", 635 | "rgb": "(162, 173, 208)" 636 | }, 637 | { 638 | "hex": "#FF43A4", 639 | "name": "Wild Strawberry", 640 | "rgb": "(255, 67, 164)" 641 | }, 642 | { 643 | "hex": "#FC6C85", 644 | "name": "Wild Watermelon", 645 | "rgb": "(252, 108, 133)" 646 | }, 647 | { 648 | "hex": "#CDA4DE", 649 | "name": "Wisteria", 650 | "rgb": "(205, 164, 222)" 651 | }, 652 | { 653 | "hex": "#FCE883", 654 | "name": "Yellow", 655 | "rgb": "(252, 232, 131)" 656 | }, 657 | { 658 | "hex": "#C5E384", 659 | "name": "Yellow Green", 660 | "rgb": "(197, 227, 132)" 661 | }, 662 | { 663 | "hex": "#FFAE42", 664 | "name": "Yellow Orange", 665 | "rgb": "(255, 174, 66)" 666 | } 667 | ] -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.os.Bundle; 20 | import android.support.design.widget.NavigationView; 21 | import android.support.v4.app.Fragment; 22 | import android.support.v4.view.GravityCompat; 23 | import android.support.v4.widget.DrawerLayout; 24 | import android.support.v7.app.AppCompatActivity; 25 | import android.view.MenuItem; 26 | 27 | import com.arlib.floatingsearchview.FloatingSearchView; 28 | import com.arlib.floatingsearchviewdemo.fragment.BaseExampleFragment; 29 | import com.arlib.floatingsearchviewdemo.fragment.ScrollingSearchExampleFragment; 30 | import com.arlib.floatingsearchviewdemo.fragment.SlidingSearchResultsExampleFragment; 31 | import com.arlib.floatingsearchviewdemo.fragment.SlidingSearchViewExampleFragment; 32 | 33 | import java.util.List; 34 | 35 | public class MainActivity extends AppCompatActivity 36 | implements BaseExampleFragment.BaseExampleFragmentCallbacks, NavigationView.OnNavigationItemSelectedListener { 37 | 38 | private final String TAG = "MainActivity"; 39 | 40 | private DrawerLayout mDrawerLayout; 41 | 42 | @Override 43 | protected void onCreate(Bundle savedInstanceState) { 44 | super.onCreate(savedInstanceState); 45 | setContentView(R.layout.activity_main); 46 | 47 | mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 48 | NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 49 | navigationView.setNavigationItemSelectedListener(this); 50 | 51 | showFragment(new SlidingSearchResultsExampleFragment()); 52 | } 53 | 54 | @Override 55 | public void onAttachSearchViewToDrawer(FloatingSearchView searchView) { 56 | searchView.attachNavigationDrawerToMenuButton(mDrawerLayout); 57 | } 58 | 59 | @Override 60 | public void onBackPressed() { 61 | List fragments = getSupportFragmentManager().getFragments(); 62 | BaseExampleFragment currentFragment = (BaseExampleFragment) fragments.get(fragments.size() - 1); 63 | 64 | if (!currentFragment.onActivityBackPress()) { 65 | super.onBackPressed(); 66 | } 67 | } 68 | 69 | @Override 70 | public boolean onNavigationItemSelected(MenuItem menuItem) { 71 | mDrawerLayout.closeDrawer(GravityCompat.START); 72 | switch (menuItem.getItemId()) { 73 | case R.id.sliding_list_example: 74 | showFragment(new SlidingSearchResultsExampleFragment()); 75 | return true; 76 | case R.id.sliding_search_bar_example: 77 | showFragment(new SlidingSearchViewExampleFragment()); 78 | return true; 79 | case R.id.scrolling_search_bar_example: 80 | showFragment(new ScrollingSearchExampleFragment()); 81 | return true; 82 | default: 83 | return true; 84 | } 85 | } 86 | 87 | private void showFragment(Fragment fragment) { 88 | getSupportFragmentManager() 89 | .beginTransaction() 90 | .replace(R.id.fragment_container, fragment).commit(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/adapter/SearchResultsListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.adapter; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.app.Activity; 20 | import android.graphics.Color; 21 | import android.support.v7.graphics.Palette; 22 | import android.support.v7.widget.RecyclerView; 23 | import android.view.LayoutInflater; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.view.animation.DecelerateInterpolator; 27 | import android.widget.TextView; 28 | 29 | import com.arlib.floatingsearchview.util.Util; 30 | import com.arlib.floatingsearchviewdemo.R; 31 | import com.arlib.floatingsearchviewdemo.data.ColorWrapper; 32 | 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | public class SearchResultsListAdapter extends RecyclerView.Adapter { 37 | 38 | private List mDataSet = new ArrayList<>(); 39 | 40 | private int mLastAnimatedItemPosition = -1; 41 | 42 | public interface OnItemClickListener{ 43 | void onClick(ColorWrapper colorWrapper); 44 | } 45 | 46 | private OnItemClickListener mItemsOnClickListener; 47 | 48 | public static class ViewHolder extends RecyclerView.ViewHolder { 49 | public final TextView mColorName; 50 | public final TextView mColorValue; 51 | public final View mTextContainer; 52 | 53 | public ViewHolder(View view) { 54 | super(view); 55 | mColorName = (TextView) view.findViewById(R.id.color_name); 56 | mColorValue = (TextView) view.findViewById(R.id.color_value); 57 | mTextContainer = view.findViewById(R.id.text_container); 58 | } 59 | } 60 | 61 | public void swapData(List mNewDataSet) { 62 | mDataSet = mNewDataSet; 63 | notifyDataSetChanged(); 64 | } 65 | 66 | public void setItemsOnClickListener(OnItemClickListener onClickListener){ 67 | this.mItemsOnClickListener = onClickListener; 68 | } 69 | 70 | @Override 71 | public SearchResultsListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 72 | View view = LayoutInflater.from(parent.getContext()) 73 | .inflate(R.layout.search_results_list_item, parent, false); 74 | return new ViewHolder(view); 75 | } 76 | 77 | @Override 78 | public void onBindViewHolder(SearchResultsListAdapter.ViewHolder holder, final int position) { 79 | 80 | ColorWrapper colorSuggestion = mDataSet.get(position); 81 | holder.mColorName.setText(colorSuggestion.getName()); 82 | holder.mColorValue.setText(colorSuggestion.getHex()); 83 | 84 | int color = Color.parseColor(colorSuggestion.getHex()); 85 | holder.mColorName.setTextColor(color); 86 | holder.mColorValue.setTextColor(color); 87 | 88 | if(mLastAnimatedItemPosition < position){ 89 | animateItem(holder.itemView); 90 | mLastAnimatedItemPosition = position; 91 | } 92 | 93 | if(mItemsOnClickListener != null){ 94 | holder.itemView.setOnClickListener(new View.OnClickListener() { 95 | @Override 96 | public void onClick(View v) { 97 | mItemsOnClickListener.onClick(mDataSet.get(position)); 98 | } 99 | }); 100 | } 101 | } 102 | 103 | @Override 104 | public int getItemCount() { 105 | return mDataSet.size(); 106 | } 107 | 108 | private void animateItem(View view) { 109 | view.setTranslationY(Util.getScreenHeight((Activity) view.getContext())); 110 | view.animate() 111 | .translationY(0) 112 | .setInterpolator(new DecelerateInterpolator(3.f)) 113 | .setDuration(700) 114 | .start(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/data/ColorSuggestion.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.data; 2 | 3 | import android.os.Parcel; 4 | 5 | import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion; 6 | 7 | /** 8 | * Copyright (C) 2015 Ari C. 9 | *

10 | * Licensed under the Apache License, Version 2.0 (the "License"); 11 | * you may not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | *

14 | * http://www.apache.org/licenses/LICENSE-2.0 15 | *

16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an "AS IS" BASIS, 18 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | */ 22 | 23 | public class ColorSuggestion implements SearchSuggestion { 24 | 25 | private String mColorName; 26 | private boolean mIsHistory = false; 27 | 28 | public ColorSuggestion(String suggestion) { 29 | this.mColorName = suggestion.toLowerCase(); 30 | } 31 | 32 | public ColorSuggestion(Parcel source) { 33 | this.mColorName = source.readString(); 34 | this.mIsHistory = source.readInt() != 0; 35 | } 36 | 37 | public void setIsHistory(boolean isHistory) { 38 | this.mIsHistory = isHistory; 39 | } 40 | 41 | public boolean getIsHistory() { 42 | return this.mIsHistory; 43 | } 44 | 45 | @Override 46 | public String getBody() { 47 | return mColorName; 48 | } 49 | 50 | public static final Creator CREATOR = new Creator() { 51 | @Override 52 | public ColorSuggestion createFromParcel(Parcel in) { 53 | return new ColorSuggestion(in); 54 | } 55 | 56 | @Override 57 | public ColorSuggestion[] newArray(int size) { 58 | return new ColorSuggestion[size]; 59 | } 60 | }; 61 | 62 | @Override 63 | public int describeContents() { 64 | return 0; 65 | } 66 | 67 | @Override 68 | public void writeToParcel(Parcel dest, int flags) { 69 | dest.writeString(mColorName); 70 | dest.writeInt(mIsHistory ? 1 : 0); 71 | } 72 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/data/ColorWrapper.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.data; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.os.Parcel; 20 | import android.os.Parcelable; 21 | 22 | import com.google.gson.annotations.Expose; 23 | import com.google.gson.annotations.SerializedName; 24 | 25 | public class ColorWrapper implements Parcelable { 26 | 27 | @SerializedName("hex") 28 | @Expose 29 | private String hex; 30 | @SerializedName("name") 31 | @Expose 32 | private String name; 33 | @SerializedName("rgb") 34 | @Expose 35 | private String rgb; 36 | 37 | private ColorWrapper(Parcel in) { 38 | hex = in.readString(); 39 | name = in.readString(); 40 | rgb = in.readString(); 41 | } 42 | 43 | @Override 44 | public void writeToParcel(Parcel dest, int flags) { 45 | dest.writeString(hex); 46 | dest.writeString(name); 47 | dest.writeString(rgb); 48 | } 49 | 50 | @Override 51 | public int describeContents() { 52 | return 0; 53 | } 54 | 55 | /** 56 | * 57 | * @return 58 | * The hex 59 | */ 60 | public String getHex() { 61 | return hex; 62 | } 63 | 64 | /** 65 | * 66 | * @param hex 67 | * The hex 68 | */ 69 | public void setHex(String hex) { 70 | this.hex = hex; 71 | } 72 | 73 | /** 74 | * 75 | * @return 76 | * The name 77 | */ 78 | public String getName() { 79 | return name; 80 | } 81 | 82 | /** 83 | * 84 | * @param name 85 | * The name 86 | */ 87 | public void setName(String name) { 88 | this.name = name; 89 | } 90 | 91 | /** 92 | * 93 | * @return 94 | * The rgb 95 | */ 96 | public String getRgb() { 97 | return rgb; 98 | } 99 | 100 | /** 101 | * 102 | * @param rgb 103 | * The rgb 104 | */ 105 | public void setRgb(String rgb) { 106 | this.rgb = rgb; 107 | } 108 | 109 | public static final Creator CREATOR = new Creator() { 110 | @Override 111 | public ColorWrapper createFromParcel(Parcel in) { 112 | return new ColorWrapper(in); 113 | } 114 | 115 | @Override 116 | public ColorWrapper[] newArray(int size) { 117 | return new ColorWrapper[size]; 118 | } 119 | }; 120 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/data/DataHelper.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.data; 2 | 3 | /** 4 | * Copyright (C) 2015 Ari C. 5 | *

6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | *

10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | *

12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | import android.content.Context; 20 | import android.widget.Filter; 21 | 22 | import com.google.gson.Gson; 23 | import com.google.gson.reflect.TypeToken; 24 | 25 | import java.io.IOException; 26 | import java.io.InputStream; 27 | import java.lang.reflect.Type; 28 | import java.util.ArrayList; 29 | import java.util.Arrays; 30 | import java.util.Collections; 31 | import java.util.Comparator; 32 | import java.util.List; 33 | 34 | public class DataHelper { 35 | 36 | private static final String COLORS_FILE_NAME = "colors.json"; 37 | 38 | private static List sColorWrappers = new ArrayList<>(); 39 | 40 | private static List sColorSuggestions = 41 | new ArrayList<>(Arrays.asList( 42 | new ColorSuggestion("green"), 43 | new ColorSuggestion("blue"), 44 | new ColorSuggestion("pink"), 45 | new ColorSuggestion("purple"), 46 | new ColorSuggestion("brown"), 47 | new ColorSuggestion("gray"), 48 | new ColorSuggestion("Granny Smith Apple"), 49 | new ColorSuggestion("Indigo"), 50 | new ColorSuggestion("Periwinkle"), 51 | new ColorSuggestion("Mahogany"), 52 | new ColorSuggestion("Maize"), 53 | new ColorSuggestion("Mahogany"), 54 | new ColorSuggestion("Outer Space"), 55 | new ColorSuggestion("Melon"), 56 | new ColorSuggestion("Yellow"), 57 | new ColorSuggestion("Orange"), 58 | new ColorSuggestion("Red"), 59 | new ColorSuggestion("Orchid"))); 60 | 61 | public interface OnFindColorsListener { 62 | void onResults(List results); 63 | } 64 | 65 | public interface OnFindSuggestionsListener { 66 | void onResults(List results); 67 | } 68 | 69 | public static List getHistory(Context context, int count) { 70 | 71 | List suggestionList = new ArrayList<>(); 72 | ColorSuggestion colorSuggestion; 73 | for (int i = 0; i < sColorSuggestions.size(); i++) { 74 | colorSuggestion = sColorSuggestions.get(i); 75 | colorSuggestion.setIsHistory(true); 76 | suggestionList.add(colorSuggestion); 77 | if (suggestionList.size() == count) { 78 | break; 79 | } 80 | } 81 | return suggestionList; 82 | } 83 | 84 | public static void resetSuggestionsHistory() { 85 | for (ColorSuggestion colorSuggestion : sColorSuggestions) { 86 | colorSuggestion.setIsHistory(false); 87 | } 88 | } 89 | 90 | public static void findSuggestions(Context context, String query, final int limit, final long simulatedDelay, 91 | final OnFindSuggestionsListener listener) { 92 | new Filter() { 93 | 94 | @Override 95 | protected FilterResults performFiltering(CharSequence constraint) { 96 | 97 | try { 98 | Thread.sleep(simulatedDelay); 99 | } catch (InterruptedException e) { 100 | e.printStackTrace(); 101 | } 102 | 103 | DataHelper.resetSuggestionsHistory(); 104 | List suggestionList = new ArrayList<>(); 105 | if (!(constraint == null || constraint.length() == 0)) { 106 | 107 | for (ColorSuggestion suggestion : sColorSuggestions) { 108 | if (suggestion.getBody().toUpperCase() 109 | .startsWith(constraint.toString().toUpperCase())) { 110 | 111 | suggestionList.add(suggestion); 112 | if (limit != -1 && suggestionList.size() == limit) { 113 | break; 114 | } 115 | } 116 | } 117 | } 118 | 119 | FilterResults results = new FilterResults(); 120 | Collections.sort(suggestionList, new Comparator() { 121 | @Override 122 | public int compare(ColorSuggestion lhs, ColorSuggestion rhs) { 123 | return lhs.getIsHistory() ? -1 : 0; 124 | } 125 | }); 126 | results.values = suggestionList; 127 | results.count = suggestionList.size(); 128 | 129 | return results; 130 | } 131 | 132 | @Override 133 | protected void publishResults(CharSequence constraint, FilterResults results) { 134 | 135 | if (listener != null) { 136 | listener.onResults((List) results.values); 137 | } 138 | } 139 | }.filter(query); 140 | 141 | } 142 | 143 | 144 | public static void findColors(Context context, String query, final OnFindColorsListener listener) { 145 | initColorWrapperList(context); 146 | 147 | new Filter() { 148 | 149 | @Override 150 | protected FilterResults performFiltering(CharSequence constraint) { 151 | 152 | 153 | List suggestionList = new ArrayList<>(); 154 | 155 | if (!(constraint == null || constraint.length() == 0)) { 156 | 157 | for (ColorWrapper color : sColorWrappers) { 158 | if (color.getName().toUpperCase() 159 | .startsWith(constraint.toString().toUpperCase())) { 160 | 161 | suggestionList.add(color); 162 | } 163 | } 164 | 165 | } 166 | 167 | FilterResults results = new FilterResults(); 168 | results.values = suggestionList; 169 | results.count = suggestionList.size(); 170 | 171 | return results; 172 | } 173 | 174 | @Override 175 | protected void publishResults(CharSequence constraint, FilterResults results) { 176 | 177 | if (listener != null) { 178 | listener.onResults((List) results.values); 179 | } 180 | } 181 | }.filter(query); 182 | 183 | } 184 | 185 | private static void initColorWrapperList(Context context) { 186 | 187 | if (sColorWrappers.isEmpty()) { 188 | String jsonString = loadJson(context); 189 | sColorWrappers = deserializeColors(jsonString); 190 | } 191 | } 192 | 193 | private static String loadJson(Context context) { 194 | 195 | String jsonString; 196 | 197 | try { 198 | InputStream is = context.getAssets().open(COLORS_FILE_NAME); 199 | int size = is.available(); 200 | byte[] buffer = new byte[size]; 201 | is.read(buffer); 202 | is.close(); 203 | jsonString = new String(buffer, "UTF-8"); 204 | } catch (IOException ex) { 205 | ex.printStackTrace(); 206 | return null; 207 | } 208 | 209 | return jsonString; 210 | } 211 | 212 | private static List deserializeColors(String jsonString) { 213 | 214 | Gson gson = new Gson(); 215 | 216 | Type collectionType = new TypeToken>() { 217 | }.getType(); 218 | return gson.fromJson(jsonString, collectionType); 219 | } 220 | 221 | } -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/fragment/BaseExampleFragment.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.fragment; 2 | 3 | import android.content.Context; 4 | import android.support.v4.app.Fragment; 5 | 6 | import com.arlib.floatingsearchview.FloatingSearchView; 7 | 8 | /** 9 | * Created by ari on 8/16/16. 10 | */ 11 | public abstract class BaseExampleFragment extends Fragment { 12 | 13 | 14 | private BaseExampleFragmentCallbacks mCallbacks; 15 | 16 | public interface BaseExampleFragmentCallbacks{ 17 | 18 | void onAttachSearchViewToDrawer(FloatingSearchView searchView); 19 | } 20 | 21 | @Override 22 | public void onAttach(Context context) { 23 | super.onAttach(context); 24 | if (context instanceof BaseExampleFragmentCallbacks) { 25 | mCallbacks = (BaseExampleFragmentCallbacks) context; 26 | } else { 27 | throw new RuntimeException(context.toString() 28 | + " must implement BaseExampleFragmentCallbacks"); 29 | } 30 | } 31 | 32 | @Override 33 | public void onDetach() { 34 | super.onDetach(); 35 | mCallbacks = null; 36 | } 37 | 38 | protected void attachSearchViewActivityDrawer(FloatingSearchView searchView){ 39 | if(mCallbacks != null){ 40 | mCallbacks.onAttachSearchViewToDrawer(searchView); 41 | } 42 | } 43 | 44 | public abstract boolean onActivityBackPress(); 45 | } 46 | -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/fragment/ScrollingSearchExampleFragment.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.fragment; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.design.widget.AppBarLayout; 7 | import android.support.v4.content.res.ResourcesCompat; 8 | import android.text.Html; 9 | import android.util.Log; 10 | import android.view.LayoutInflater; 11 | import android.view.MenuItem; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.ImageView; 15 | import android.widget.TextView; 16 | import android.widget.Toast; 17 | 18 | import com.arlib.floatingsearchview.FloatingSearchView; 19 | import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter; 20 | import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion; 21 | import com.arlib.floatingsearchview.util.Util; 22 | import com.arlib.floatingsearchviewdemo.R; 23 | import com.arlib.floatingsearchviewdemo.data.ColorSuggestion; 24 | import com.arlib.floatingsearchviewdemo.data.ColorWrapper; 25 | import com.arlib.floatingsearchviewdemo.data.DataHelper; 26 | 27 | import java.util.List; 28 | 29 | 30 | public class ScrollingSearchExampleFragment extends BaseExampleFragment implements AppBarLayout.OnOffsetChangedListener { 31 | private final String TAG = "BlankFragment"; 32 | 33 | public static final long FIND_SUGGESTION_SIMULATED_DELAY = 250; 34 | 35 | private FloatingSearchView mSearchView; 36 | private AppBarLayout mAppBar; 37 | 38 | private boolean mIsDarkSearchTheme = false; 39 | 40 | private String mLastQuery = ""; 41 | 42 | public ScrollingSearchExampleFragment() { 43 | // Required empty public constructor 44 | } 45 | 46 | @Override 47 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 48 | Bundle savedInstanceState) { 49 | return inflater.inflate(R.layout.fragment_scrolling_search_example, container, false); 50 | } 51 | 52 | @Override 53 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 54 | super.onViewCreated(view, savedInstanceState); 55 | mSearchView = (FloatingSearchView) view.findViewById(R.id.floating_search_view); 56 | mAppBar = (AppBarLayout) view.findViewById(R.id.appbar); 57 | 58 | mAppBar.addOnOffsetChangedListener(this); 59 | 60 | setupDrawer(); 61 | setupSearchBar(); 62 | } 63 | 64 | private void setupSearchBar() { 65 | mSearchView.setOnQueryChangeListener(new FloatingSearchView.OnQueryChangeListener() { 66 | 67 | @Override 68 | public void onSearchTextChanged(String oldQuery, final String newQuery) { 69 | 70 | if (!oldQuery.equals("") && newQuery.equals("")) { 71 | mSearchView.clearSuggestions(); 72 | } else { 73 | 74 | //this shows the top left circular progress 75 | //you can call it where ever you want, but 76 | //it makes sense to do it when loading something in 77 | //the background. 78 | mSearchView.showProgress(); 79 | 80 | //simulates a query call to a data source 81 | //with a new query. 82 | DataHelper.findSuggestions(getActivity(), newQuery, 5, 83 | FIND_SUGGESTION_SIMULATED_DELAY, new DataHelper.OnFindSuggestionsListener() { 84 | 85 | @Override 86 | public void onResults(List results) { 87 | 88 | //this will swap the data and 89 | //render the collapse/expand animations as necessary 90 | mSearchView.swapSuggestions(results); 91 | 92 | //let the users know that the background 93 | //process has completed 94 | mSearchView.hideProgress(); 95 | } 96 | }); 97 | } 98 | 99 | Log.d(TAG, "onSearchTextChanged()"); 100 | } 101 | }); 102 | 103 | mSearchView.setOnSearchListener(new FloatingSearchView.OnSearchListener() { 104 | @Override 105 | public void onSuggestionClicked(final SearchSuggestion searchSuggestion) { 106 | 107 | ColorSuggestion colorSuggestion = (ColorSuggestion) searchSuggestion; 108 | DataHelper.findColors(getActivity(), colorSuggestion.getBody(), 109 | new DataHelper.OnFindColorsListener() { 110 | 111 | @Override 112 | public void onResults(List results) { 113 | //show search results 114 | } 115 | 116 | }); 117 | Log.d(TAG, "onSuggestionClicked()"); 118 | 119 | mLastQuery = searchSuggestion.getBody(); 120 | } 121 | 122 | @Override 123 | public void onSearchAction(String query) { 124 | mLastQuery = query; 125 | 126 | DataHelper.findColors(getActivity(), query, 127 | new DataHelper.OnFindColorsListener() { 128 | 129 | @Override 130 | public void onResults(List results) { 131 | //show search results 132 | } 133 | 134 | }); 135 | Log.d(TAG, "onSearchAction()"); 136 | } 137 | }); 138 | 139 | mSearchView.setOnFocusChangeListener(new FloatingSearchView.OnFocusChangeListener() { 140 | @Override 141 | public void onFocus() { 142 | 143 | //show suggestions when search bar gains focus (typically history suggestions) 144 | mSearchView.swapSuggestions(DataHelper.getHistory(getActivity(), 3)); 145 | 146 | Log.d(TAG, "onFocus()"); 147 | } 148 | 149 | @Override 150 | public void onFocusCleared() { 151 | 152 | //set the title of the bar so that when focus is returned a new query begins 153 | mSearchView.setSearchBarTitle(mLastQuery); 154 | 155 | //you can also set setSearchText(...) to make keep the query there when not focused and when focus returns 156 | //mSearchView.setSearchText(searchSuggestion.getBody()); 157 | 158 | Log.d(TAG, "onFocusCleared()"); 159 | } 160 | }); 161 | 162 | 163 | //handle menu clicks the same way as you would 164 | //in a regular activity 165 | mSearchView.setOnMenuItemClickListener(new FloatingSearchView.OnMenuItemClickListener() { 166 | @Override 167 | public void onActionMenuItemSelected(MenuItem item) { 168 | 169 | if (item.getItemId() == R.id.action_change_colors) { 170 | 171 | mIsDarkSearchTheme = true; 172 | 173 | //demonstrate setting colors for items 174 | mSearchView.setBackgroundColor(Color.parseColor("#787878")); 175 | mSearchView.setViewTextColor(Color.parseColor("#e9e9e9")); 176 | mSearchView.setHintTextColor(Color.parseColor("#e9e9e9")); 177 | mSearchView.setActionMenuOverflowColor(Color.parseColor("#e9e9e9")); 178 | mSearchView.setMenuItemIconColor(Color.parseColor("#e9e9e9")); 179 | mSearchView.setLeftActionIconColor(Color.parseColor("#e9e9e9")); 180 | mSearchView.setClearBtnColor(Color.parseColor("#e9e9e9")); 181 | mSearchView.setDividerColor(Color.parseColor("#BEBEBE")); 182 | mSearchView.setLeftActionIconColor(Color.parseColor("#e9e9e9")); 183 | } else { 184 | 185 | //just print action 186 | Toast.makeText(getActivity().getApplicationContext(), item.getTitle(), 187 | Toast.LENGTH_SHORT).show(); 188 | } 189 | 190 | } 191 | }); 192 | 193 | //use this listener to listen to menu clicks when app:floatingSearch_leftAction="showHome" 194 | mSearchView.setOnHomeActionClickListener(new FloatingSearchView.OnHomeActionClickListener() { 195 | @Override 196 | public void onHomeClicked() { 197 | 198 | Log.d(TAG, "onHomeClicked()"); 199 | } 200 | }); 201 | 202 | /* 203 | * Here you have access to the left icon and the text of a given suggestion 204 | * item after as it is bound to the suggestion list. You can utilize this 205 | * callback to change some properties of the left icon and the text. For example, you 206 | * can load the left icon images using your favorite image loading library, or change text color. 207 | * 208 | * 209 | * Important: 210 | * Keep in mind that the suggestion list is a RecyclerView, so views are reused for different 211 | * items in the list. 212 | */ 213 | mSearchView.setOnBindSuggestionCallback(new SearchSuggestionsAdapter.OnBindSuggestionCallback() { 214 | @Override 215 | public void onBindSuggestion(View suggestionView, ImageView leftIcon, 216 | TextView textView, SearchSuggestion item, int itemPosition) { 217 | ColorSuggestion colorSuggestion = (ColorSuggestion) item; 218 | 219 | String textColor = mIsDarkSearchTheme ? "#ffffff" : "#000000"; 220 | String textLight = mIsDarkSearchTheme ? "#bfbfbf" : "#787878"; 221 | 222 | if (colorSuggestion.getIsHistory()) { 223 | leftIcon.setImageDrawable(ResourcesCompat.getDrawable(getResources(), 224 | R.drawable.ic_history_black_24dp, null)); 225 | 226 | Util.setIconColor(leftIcon, Color.parseColor(textColor)); 227 | leftIcon.setAlpha(.36f); 228 | } else { 229 | leftIcon.setAlpha(0.0f); 230 | leftIcon.setImageDrawable(null); 231 | } 232 | 233 | textView.setTextColor(Color.parseColor(textColor)); 234 | String text = colorSuggestion.getBody() 235 | .replaceFirst(mSearchView.getQuery(), 236 | "" + mSearchView.getQuery() + ""); 237 | textView.setText(Html.fromHtml(text)); 238 | } 239 | 240 | }); 241 | } 242 | 243 | @Override 244 | public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { 245 | mSearchView.setTranslationY(verticalOffset); 246 | } 247 | 248 | @Override 249 | public boolean onActivityBackPress() { 250 | //if mSearchView.setSearchFocused(false) causes the focused search 251 | //to close, then we don't want to close the activity. if mSearchView.setSearchFocused(false) 252 | //returns false, we know that the search was already closed so the call didn't change the focus 253 | //state and it makes sense to call supper onBackPressed() and close the activity 254 | if (!mSearchView.setSearchFocused(false)) { 255 | return false; 256 | } 257 | return true; 258 | } 259 | 260 | private void setupDrawer() { 261 | attachSearchViewActivityDrawer(mSearchView); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/fragment/SlidingSearchResultsExampleFragment.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.fragment; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.content.res.ResourcesCompat; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.text.Html; 10 | import android.util.Log; 11 | import android.view.LayoutInflater; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.widget.ImageView; 16 | import android.widget.TextView; 17 | import android.widget.Toast; 18 | 19 | import com.arlib.floatingsearchview.FloatingSearchView; 20 | import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter; 21 | import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion; 22 | import com.arlib.floatingsearchview.util.Util; 23 | import com.arlib.floatingsearchviewdemo.R; 24 | import com.arlib.floatingsearchviewdemo.adapter.SearchResultsListAdapter; 25 | import com.arlib.floatingsearchviewdemo.data.ColorSuggestion; 26 | import com.arlib.floatingsearchviewdemo.data.ColorWrapper; 27 | import com.arlib.floatingsearchviewdemo.data.DataHelper; 28 | 29 | import java.util.List; 30 | 31 | 32 | public class SlidingSearchResultsExampleFragment extends BaseExampleFragment { 33 | private final String TAG = "BlankFragment"; 34 | 35 | public static final long FIND_SUGGESTION_SIMULATED_DELAY = 250; 36 | 37 | private FloatingSearchView mSearchView; 38 | 39 | private RecyclerView mSearchResultsList; 40 | private SearchResultsListAdapter mSearchResultsAdapter; 41 | 42 | private boolean mIsDarkSearchTheme = false; 43 | 44 | private String mLastQuery = ""; 45 | 46 | public SlidingSearchResultsExampleFragment() { 47 | // Required empty public constructor 48 | } 49 | 50 | @Override 51 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 52 | Bundle savedInstanceState) { 53 | return inflater.inflate(R.layout.fragment_sliding_search_results_example_fragment, container, false); 54 | } 55 | 56 | @Override 57 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 58 | super.onViewCreated(view, savedInstanceState); 59 | mSearchView = (FloatingSearchView) view.findViewById(R.id.floating_search_view); 60 | mSearchResultsList = (RecyclerView) view.findViewById(R.id.search_results_list); 61 | 62 | setupFloatingSearch(); 63 | setupResultsList(); 64 | setupDrawer(); 65 | } 66 | 67 | private void setupFloatingSearch() { 68 | mSearchView.setOnQueryChangeListener(new FloatingSearchView.OnQueryChangeListener() { 69 | 70 | @Override 71 | public void onSearchTextChanged(String oldQuery, final String newQuery) { 72 | 73 | if (!oldQuery.equals("") && newQuery.equals("")) { 74 | mSearchView.clearSuggestions(); 75 | } else { 76 | 77 | //this shows the top left circular progress 78 | //you can call it where ever you want, but 79 | //it makes sense to do it when loading something in 80 | //the background. 81 | mSearchView.showProgress(); 82 | 83 | //simulates a query call to a data source 84 | //with a new query. 85 | DataHelper.findSuggestions(getActivity(), newQuery, 5, 86 | FIND_SUGGESTION_SIMULATED_DELAY, new DataHelper.OnFindSuggestionsListener() { 87 | 88 | @Override 89 | public void onResults(List results) { 90 | 91 | //this will swap the data and 92 | //render the collapse/expand animations as necessary 93 | mSearchView.swapSuggestions(results); 94 | 95 | //let the users know that the background 96 | //process has completed 97 | mSearchView.hideProgress(); 98 | } 99 | }); 100 | } 101 | 102 | Log.d(TAG, "onSearchTextChanged()"); 103 | } 104 | }); 105 | 106 | mSearchView.setOnSearchListener(new FloatingSearchView.OnSearchListener() { 107 | @Override 108 | public void onSuggestionClicked(final SearchSuggestion searchSuggestion) { 109 | 110 | ColorSuggestion colorSuggestion = (ColorSuggestion) searchSuggestion; 111 | DataHelper.findColors(getActivity(), colorSuggestion.getBody(), 112 | new DataHelper.OnFindColorsListener() { 113 | 114 | @Override 115 | public void onResults(List results) { 116 | mSearchResultsAdapter.swapData(results); 117 | } 118 | 119 | }); 120 | Log.d(TAG, "onSuggestionClicked()"); 121 | 122 | mLastQuery = searchSuggestion.getBody(); 123 | } 124 | 125 | @Override 126 | public void onSearchAction(String query) { 127 | mLastQuery = query; 128 | 129 | DataHelper.findColors(getActivity(), query, 130 | new DataHelper.OnFindColorsListener() { 131 | 132 | @Override 133 | public void onResults(List results) { 134 | mSearchResultsAdapter.swapData(results); 135 | } 136 | 137 | }); 138 | Log.d(TAG, "onSearchAction()"); 139 | } 140 | }); 141 | 142 | mSearchView.setOnFocusChangeListener(new FloatingSearchView.OnFocusChangeListener() { 143 | @Override 144 | public void onFocus() { 145 | 146 | //show suggestions when search bar gains focus (typically history suggestions) 147 | mSearchView.swapSuggestions(DataHelper.getHistory(getActivity(), 3)); 148 | 149 | Log.d(TAG, "onFocus()"); 150 | } 151 | 152 | @Override 153 | public void onFocusCleared() { 154 | 155 | //set the title of the bar so that when focus is returned a new query begins 156 | mSearchView.setSearchBarTitle(mLastQuery); 157 | 158 | //you can also set setSearchText(...) to make keep the query there when not focused and when focus returns 159 | //mSearchView.setSearchText(searchSuggestion.getBody()); 160 | 161 | Log.d(TAG, "onFocusCleared()"); 162 | } 163 | }); 164 | 165 | 166 | //handle menu clicks the same way as you would 167 | //in a regular activity 168 | mSearchView.setOnMenuItemClickListener(new FloatingSearchView.OnMenuItemClickListener() { 169 | @Override 170 | public void onActionMenuItemSelected(MenuItem item) { 171 | 172 | if (item.getItemId() == R.id.action_change_colors) { 173 | 174 | mIsDarkSearchTheme = true; 175 | 176 | //demonstrate setting colors for items 177 | mSearchView.setBackgroundColor(Color.parseColor("#787878")); 178 | mSearchView.setViewTextColor(Color.parseColor("#e9e9e9")); 179 | mSearchView.setHintTextColor(Color.parseColor("#e9e9e9")); 180 | mSearchView.setActionMenuOverflowColor(Color.parseColor("#e9e9e9")); 181 | mSearchView.setMenuItemIconColor(Color.parseColor("#e9e9e9")); 182 | mSearchView.setLeftActionIconColor(Color.parseColor("#e9e9e9")); 183 | mSearchView.setClearBtnColor(Color.parseColor("#e9e9e9")); 184 | mSearchView.setDividerColor(Color.parseColor("#BEBEBE")); 185 | mSearchView.setLeftActionIconColor(Color.parseColor("#e9e9e9")); 186 | } else { 187 | 188 | //just print action 189 | Toast.makeText(getActivity().getApplicationContext(), item.getTitle(), 190 | Toast.LENGTH_SHORT).show(); 191 | } 192 | 193 | } 194 | }); 195 | 196 | //use this listener to listen to menu clicks when app:floatingSearch_leftAction="showHome" 197 | mSearchView.setOnHomeActionClickListener(new FloatingSearchView.OnHomeActionClickListener() { 198 | @Override 199 | public void onHomeClicked() { 200 | 201 | Log.d(TAG, "onHomeClicked()"); 202 | } 203 | }); 204 | 205 | /* 206 | * Here you have access to the left icon and the text of a given suggestion 207 | * item after as it is bound to the suggestion list. You can utilize this 208 | * callback to change some properties of the left icon and the text. For example, you 209 | * can load the left icon images using your favorite image loading library, or change text color. 210 | * 211 | * 212 | * Important: 213 | * Keep in mind that the suggestion list is a RecyclerView, so views are reused for different 214 | * items in the list. 215 | */ 216 | mSearchView.setOnBindSuggestionCallback(new SearchSuggestionsAdapter.OnBindSuggestionCallback() { 217 | @Override 218 | public void onBindSuggestion(View suggestionView, ImageView leftIcon, 219 | TextView textView, SearchSuggestion item, int itemPosition) { 220 | ColorSuggestion colorSuggestion = (ColorSuggestion) item; 221 | 222 | String textColor = mIsDarkSearchTheme ? "#ffffff" : "#000000"; 223 | String textLight = mIsDarkSearchTheme ? "#bfbfbf" : "#787878"; 224 | 225 | if (colorSuggestion.getIsHistory()) { 226 | leftIcon.setImageDrawable(ResourcesCompat.getDrawable(getResources(), 227 | R.drawable.ic_history_black_24dp, null)); 228 | 229 | Util.setIconColor(leftIcon, Color.parseColor(textColor)); 230 | leftIcon.setAlpha(.36f); 231 | } else { 232 | leftIcon.setAlpha(0.0f); 233 | leftIcon.setImageDrawable(null); 234 | } 235 | 236 | textView.setTextColor(Color.parseColor(textColor)); 237 | String text = colorSuggestion.getBody() 238 | .replaceFirst(mSearchView.getQuery(), 239 | "" + mSearchView.getQuery() + ""); 240 | textView.setText(Html.fromHtml(text)); 241 | } 242 | 243 | }); 244 | 245 | //listen for when suggestion list expands/shrinks in order to move down/up the 246 | //search results list 247 | mSearchView.setOnSuggestionsListHeightChanged(new FloatingSearchView.OnSuggestionsListHeightChanged() { 248 | @Override 249 | public void onSuggestionsListHeightChanged(float newHeight) { 250 | mSearchResultsList.setTranslationY(newHeight); 251 | } 252 | }); 253 | 254 | /* 255 | * When the user types some text into the search field, a clear button (and 'x' to the 256 | * right) of the search text is shown. 257 | * 258 | * This listener provides a callback for when this button is clicked. 259 | */ 260 | mSearchView.setOnClearSearchActionListener(new FloatingSearchView.OnClearSearchActionListener() { 261 | @Override 262 | public void onClearSearchClicked() { 263 | 264 | Log.d(TAG, "onClearSearchClicked()"); 265 | } 266 | }); 267 | } 268 | 269 | private void setupResultsList() { 270 | mSearchResultsAdapter = new SearchResultsListAdapter(); 271 | mSearchResultsList.setAdapter(mSearchResultsAdapter); 272 | mSearchResultsList.setLayoutManager(new LinearLayoutManager(getContext())); 273 | } 274 | 275 | @Override 276 | public boolean onActivityBackPress() { 277 | //if mSearchView.setSearchFocused(false) causes the focused search 278 | //to close, then we don't want to close the activity. if mSearchView.setSearchFocused(false) 279 | //returns false, we know that the search was already closed so the call didn't change the focus 280 | //state and it makes sense to call supper onBackPressed() and close the activity 281 | if (!mSearchView.setSearchFocused(false)) { 282 | return false; 283 | } 284 | return true; 285 | } 286 | 287 | private void setupDrawer() { 288 | attachSearchViewActivityDrawer(mSearchView); 289 | } 290 | 291 | } 292 | -------------------------------------------------------------------------------- /sample/src/main/java/com/arlib/floatingsearchviewdemo/fragment/SlidingSearchViewExampleFragment.java: -------------------------------------------------------------------------------- 1 | package com.arlib.floatingsearchviewdemo.fragment; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ObjectAnimator; 6 | import android.animation.ValueAnimator; 7 | import android.graphics.Color; 8 | import android.graphics.drawable.ColorDrawable; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | import android.support.annotation.Nullable; 12 | import android.support.v4.content.res.ResourcesCompat; 13 | import android.text.Html; 14 | import android.util.Log; 15 | import android.view.LayoutInflater; 16 | import android.view.MenuItem; 17 | import android.view.View; 18 | import android.view.ViewGroup; 19 | import android.widget.ImageView; 20 | import android.widget.TextView; 21 | import android.widget.Toast; 22 | 23 | import com.arlib.floatingsearchview.FloatingSearchView; 24 | import com.arlib.floatingsearchview.suggestions.SearchSuggestionsAdapter; 25 | import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion; 26 | import com.arlib.floatingsearchview.util.Util; 27 | import com.arlib.floatingsearchviewdemo.R; 28 | import com.arlib.floatingsearchviewdemo.data.ColorSuggestion; 29 | import com.arlib.floatingsearchviewdemo.data.DataHelper; 30 | 31 | import java.util.List; 32 | 33 | 34 | public class SlidingSearchViewExampleFragment extends BaseExampleFragment { 35 | private final String TAG = "BlankFragment"; 36 | 37 | public static final long FIND_SUGGESTION_SIMULATED_DELAY = 250; 38 | 39 | private static final long ANIM_DURATION = 350; 40 | 41 | private View mHeaderView; 42 | private View mDimSearchViewBackground; 43 | private ColorDrawable mDimDrawable; 44 | private FloatingSearchView mSearchView; 45 | 46 | private boolean mIsDarkSearchTheme = false; 47 | 48 | private String mLastQuery = ""; 49 | 50 | public SlidingSearchViewExampleFragment() { 51 | // Required empty public constructor 52 | } 53 | 54 | @Override 55 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 56 | Bundle savedInstanceState) { 57 | return inflater.inflate(R.layout.fragment_sliding_search_example, container, false); 58 | } 59 | 60 | @Override 61 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 62 | super.onViewCreated(view, savedInstanceState); 63 | mSearchView = (FloatingSearchView) view.findViewById(R.id.floating_search_view); 64 | mHeaderView = view.findViewById(R.id.header_view); 65 | 66 | mDimSearchViewBackground = view.findViewById(R.id.dim_background); 67 | mDimDrawable = new ColorDrawable(Color.BLACK); 68 | mDimDrawable.setAlpha(0); 69 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 70 | mDimSearchViewBackground.setBackground(mDimDrawable); 71 | } else { 72 | mDimSearchViewBackground.setBackgroundDrawable(mDimDrawable); 73 | } 74 | 75 | setupFloatingSearch(); 76 | setupDrawer(); 77 | } 78 | 79 | private void setupFloatingSearch() { 80 | mSearchView.setOnQueryChangeListener(new FloatingSearchView.OnQueryChangeListener() { 81 | 82 | @Override 83 | public void onSearchTextChanged(String oldQuery, final String newQuery) { 84 | 85 | if (!oldQuery.equals("") && newQuery.equals("")) { 86 | mSearchView.clearSuggestions(); 87 | } else { 88 | 89 | //this shows the top left circular progress 90 | //you can call it where ever you want, but 91 | //it makes sense to do it when loading something in 92 | //the background. 93 | mSearchView.showProgress(); 94 | 95 | //simulates a query call to a data source 96 | //with a new query. 97 | DataHelper.findSuggestions(getActivity(), newQuery, 5, 98 | FIND_SUGGESTION_SIMULATED_DELAY, new DataHelper.OnFindSuggestionsListener() { 99 | 100 | @Override 101 | public void onResults(List results) { 102 | 103 | //this will swap the data and 104 | //render the collapse/expand animations as necessary 105 | mSearchView.swapSuggestions(results); 106 | 107 | //let the users know that the background 108 | //process has completed 109 | mSearchView.hideProgress(); 110 | } 111 | }); 112 | } 113 | 114 | Log.d(TAG, "onSearchTextChanged()"); 115 | } 116 | }); 117 | 118 | mSearchView.setOnSearchListener(new FloatingSearchView.OnSearchListener() { 119 | @Override 120 | public void onSuggestionClicked(final SearchSuggestion searchSuggestion) { 121 | 122 | mLastQuery = searchSuggestion.getBody(); 123 | } 124 | 125 | @Override 126 | public void onSearchAction(String query) { 127 | mLastQuery = query; 128 | 129 | Log.d(TAG, "onSearchAction()"); 130 | } 131 | }); 132 | 133 | mSearchView.setOnFocusChangeListener(new FloatingSearchView.OnFocusChangeListener() { 134 | @Override 135 | public void onFocus() { 136 | int headerHeight = getResources().getDimensionPixelOffset(R.dimen.sliding_search_view_header_height); 137 | ObjectAnimator anim = ObjectAnimator.ofFloat(mSearchView, "translationY", 138 | headerHeight, 0); 139 | anim.setDuration(350); 140 | fadeDimBackground(0, 150, null); 141 | anim.addListener(new AnimatorListenerAdapter() { 142 | 143 | @Override 144 | public void onAnimationEnd(Animator animation) { 145 | //show suggestions when search bar gains focus (typically history suggestions) 146 | mSearchView.swapSuggestions(DataHelper.getHistory(getActivity(), 3)); 147 | 148 | } 149 | }); 150 | anim.start(); 151 | 152 | Log.d(TAG, "onFocus()"); 153 | } 154 | 155 | @Override 156 | public void onFocusCleared() { 157 | int headerHeight = getResources().getDimensionPixelOffset(R.dimen.sliding_search_view_header_height); 158 | ObjectAnimator anim = ObjectAnimator.ofFloat(mSearchView, "translationY", 159 | 0, headerHeight); 160 | anim.setDuration(350); 161 | anim.start(); 162 | fadeDimBackground(150, 0, null); 163 | 164 | //set the title of the bar so that when focus is returned a new query begins 165 | mSearchView.setSearchBarTitle(mLastQuery); 166 | 167 | //you can also set setSearchText(...) to make keep the query there when not focused and when focus returns 168 | //mSearchView.setSearchText(searchSuggestion.getBody()); 169 | 170 | Log.d(TAG, "onFocusCleared()"); 171 | } 172 | }); 173 | 174 | 175 | //handle menu clicks the same way as you would 176 | //in a regular activity 177 | mSearchView.setOnMenuItemClickListener(new FloatingSearchView.OnMenuItemClickListener() { 178 | @Override 179 | public void onActionMenuItemSelected(MenuItem item) { 180 | 181 | if (item.getItemId() == R.id.action_change_colors) { 182 | 183 | mIsDarkSearchTheme = true; 184 | 185 | //demonstrate setting colors for items 186 | mSearchView.setBackgroundColor(Color.parseColor("#787878")); 187 | mSearchView.setViewTextColor(Color.parseColor("#e9e9e9")); 188 | mSearchView.setHintTextColor(Color.parseColor("#e9e9e9")); 189 | mSearchView.setActionMenuOverflowColor(Color.parseColor("#e9e9e9")); 190 | mSearchView.setMenuItemIconColor(Color.parseColor("#e9e9e9")); 191 | mSearchView.setLeftActionIconColor(Color.parseColor("#e9e9e9")); 192 | mSearchView.setClearBtnColor(Color.parseColor("#e9e9e9")); 193 | mSearchView.setDividerColor(Color.parseColor("#BEBEBE")); 194 | mSearchView.setLeftActionIconColor(Color.parseColor("#e9e9e9")); 195 | } else { 196 | 197 | //just print action 198 | Toast.makeText(getActivity().getApplicationContext(), item.getTitle(), 199 | Toast.LENGTH_SHORT).show(); 200 | } 201 | 202 | } 203 | }); 204 | 205 | //use this listener to listen to menu clicks when app:floatingSearch_leftAction="showHome" 206 | mSearchView.setOnHomeActionClickListener(new FloatingSearchView.OnHomeActionClickListener() { 207 | @Override 208 | public void onHomeClicked() { 209 | 210 | Log.d(TAG, "onHomeClicked()"); 211 | } 212 | }); 213 | 214 | /* 215 | * Here you have access to the left icon and the text of a given suggestion 216 | * item after as it is bound to the suggestion list. You can utilize this 217 | * callback to change some properties of the left icon and the text. For example, you 218 | * can load the left icon images using your favorite image loading library, or change text color. 219 | * 220 | * 221 | * Important: 222 | * Keep in mind that the suggestion list is a RecyclerView, so views are reused for different 223 | * items in the list. 224 | */ 225 | mSearchView.setOnBindSuggestionCallback(new SearchSuggestionsAdapter.OnBindSuggestionCallback() { 226 | @Override 227 | public void onBindSuggestion(View suggestionView, ImageView leftIcon, 228 | TextView textView, SearchSuggestion item, int itemPosition) { 229 | ColorSuggestion colorSuggestion = (ColorSuggestion) item; 230 | 231 | String textColor = mIsDarkSearchTheme ? "#ffffff" : "#000000"; 232 | String textLight = mIsDarkSearchTheme ? "#bfbfbf" : "#787878"; 233 | 234 | if (colorSuggestion.getIsHistory()) { 235 | leftIcon.setImageDrawable(ResourcesCompat.getDrawable(getResources(), 236 | R.drawable.ic_history_black_24dp, null)); 237 | 238 | Util.setIconColor(leftIcon, Color.parseColor(textColor)); 239 | leftIcon.setAlpha(.36f); 240 | } else { 241 | leftIcon.setAlpha(0.0f); 242 | leftIcon.setImageDrawable(null); 243 | } 244 | 245 | textView.setTextColor(Color.parseColor(textColor)); 246 | String text = colorSuggestion.getBody() 247 | .replaceFirst(mSearchView.getQuery(), 248 | "" + mSearchView.getQuery() + ""); 249 | textView.setText(Html.fromHtml(text)); 250 | } 251 | 252 | }); 253 | 254 | /* 255 | * When the user types some text into the search field, a clear button (and 'x' to the 256 | * right) of the search text is shown. 257 | * 258 | * This listener provides a callback for when this button is clicked. 259 | */ 260 | mSearchView.setOnClearSearchActionListener(new FloatingSearchView.OnClearSearchActionListener() { 261 | @Override 262 | public void onClearSearchClicked() { 263 | 264 | Log.d(TAG, "onClearSearchClicked()"); 265 | } 266 | }); 267 | } 268 | 269 | 270 | @Override 271 | public boolean onActivityBackPress() { 272 | //if mSearchView.setSearchFocused(false) causes the focused search 273 | //to close, then we don't want to close the activity. if mSearchView.setSearchFocused(false) 274 | //returns false, we know that the search was already closed so the call didn't change the focus 275 | //state and it makes sense to call supper onBackPressed() and close the activity 276 | if (!mSearchView.setSearchFocused(false)) { 277 | return false; 278 | } 279 | return true; 280 | } 281 | 282 | private void setupDrawer() { 283 | attachSearchViewActivityDrawer(mSearchView); 284 | } 285 | 286 | private void fadeDimBackground(int from, int to, Animator.AnimatorListener listener) { 287 | ValueAnimator anim = ValueAnimator.ofInt(from, to); 288 | anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 289 | @Override 290 | public void onAnimationUpdate(ValueAnimator animation) { 291 | 292 | int value = (Integer) animation.getAnimatedValue(); 293 | mDimDrawable.setAlpha(value); 294 | } 295 | }); 296 | if (listener != null) { 297 | anim.addListener(listener); 298 | } 299 | anim.setDuration(ANIM_DURATION); 300 | anim.start(); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-hdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_keyboard_voice_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-hdpi/ic_keyboard_voice_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_lightbulb_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-hdpi/ic_lightbulb_outline_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_local_taxi_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-hdpi/ic_local_taxi_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_my_location_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-hdpi/ic_my_location_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-hdpi/ic_restaurant_menu_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-hdpi/ic_restaurant_menu_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-mdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_keyboard_voice_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-mdpi/ic_keyboard_voice_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_lightbulb_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-mdpi/ic_lightbulb_outline_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_local_taxi_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-mdpi/ic_local_taxi_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_my_location_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-mdpi/ic_my_location_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-mdpi/ic_restaurant_menu_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-mdpi/ic_restaurant_menu_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xhdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_keyboard_voice_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xhdpi/ic_keyboard_voice_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_lightbulb_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xhdpi/ic_lightbulb_outline_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_local_taxi_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xhdpi/ic_local_taxi_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_my_location_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xhdpi/ic_my_location_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xhdpi/ic_restaurant_menu_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xhdpi/ic_restaurant_menu_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxhdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_keyboard_voice_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxhdpi/ic_keyboard_voice_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_lightbulb_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxhdpi/ic_lightbulb_outline_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_local_taxi_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxhdpi/ic_local_taxi_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_my_location_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxhdpi/ic_my_location_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxhdpi/ic_restaurant_menu_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxhdpi/ic_restaurant_menu_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_invert_colors_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxxhdpi/ic_invert_colors_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_keyboard_voice_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxxhdpi/ic_keyboard_voice_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_lightbulb_outline_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxxhdpi/ic_lightbulb_outline_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_local_taxi_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxxhdpi/ic_local_taxi_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_my_location_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxxhdpi/ic_my_location_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable-xxxhdpi/ic_restaurant_menu_black_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/drawable-xxxhdpi/ic_restaurant_menu_black_24dp.png -------------------------------------------------------------------------------- /sample/src/main/res/drawable/circle_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 14 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_scrolling_search_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 22 | 23 | 28 | 29 | 30 | 31 | 36 | 37 | 43 | 44 | 45 | 46 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_sliding_search_example.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 21 | 22 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/fragment_sliding_search_results_example_fragment.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 26 | 27 | 42 | 43 | -------------------------------------------------------------------------------- /sample/src/main/res/layout/search_results_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 23 | 24 | 29 | 30 | -------------------------------------------------------------------------------- /sample/src/main/res/menu/menu_app.xml: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | 9 | 10 | 15 | 16 | 21 | 22 | -------------------------------------------------------------------------------- /sample/src/main/res/menu/menu_search_view.xml: -------------------------------------------------------------------------------- 1 | 4 | 9 | 14 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arimorty/floatingsearchview/a0f8fbc90d98eb1b629c6295dd2d3577412e7b1e/sample/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /sample/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /sample/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5dp 3 | 250dp 4 | 5 | -------------------------------------------------------------------------------- /sample/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | FloatingSearchView 3 | action voice rec 4 | action location 5 | action taxi 6 | change style 7 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, 8 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum 9 | 10 | 11 | Hello blank fragment 12 | Sliding list 13 | Sliding search view 14 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus dictum lorem ac leo tincidunt varius. Donec lacinia elementum lobortis. Nulla pellentesque cursus sem. Aliquam vestibulum lacinia metus, ac faucibus nunc fringilla a. Nullam mauris lorem, pharetra vitae mollis in, gravida a mi. Sed eu elit vitae lorem vestibulum volutpat eget blandit tortor. Duis dignissim porta dolor, ut porttitor lectus pretium vitae. Phasellus quis augue ante. Nam tempus egestas consectetur. Praesent nec placerat nisi, non malesuada dolor. Duis malesuada semper lorem, nec feugiat nisl. Nulla facilisi. Sed aliquam ex ut turpis malesuada dignissim. Nam risus mi, dapibus maximus nisl ac, efficitur suscipit ex. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec malesuada nisl eget faucibus mollis. Nam sit amet mauris a metus euismod porttitor et sed mi. Nunc vel vehicula arcu, eu lacinia odio. Fusce id lacus vel dui blandit maximus id eget neque. Sed eu porta diam. Nunc vitae egestas diam. Donec semper hendrerit laoreet. Aliquam quis aliquam nulla. Aenean euismod lacus sed pretium scelerisque. Suspendisse mollis arcu at ligula pulvinar, nec elementum velit fermentum. Sed sed mollis ligula, vel eleifend metus. Sed magna metus, tempus ut bibendum at, aliquam at nisi. Integer nec fringilla mauris, vel viverra augue. Morbi eu mi mauris. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Proin molestie ante nec tristique finibus. In hac habitasse platea dictumst. Maecenas sed risus condimentum, feugiat velit ac, dictum erat. Curabitur pharetra ac nulla sed lacinia. Curabitur rutrum dolor vestibulum magna ultrices congue ac sed libero. Nam semper mi a neque ultricies commodo. In condimentum in odio in porttitor. Suspendisse maximus vestibulum nunc, vel gravida dui fermentum eu. Morbi sed orci augue. Praesent dolor justo, cursus sit amet ex et, posuere mattis lorem. Donec in efficitur orci. Nam semper odio a interdum aliquet. Vivamus vitae luctus purus, in fermentum diam. Pellentesque quis orci vitae est placerat faucibus. Maecenas non gravida ipsum, sit amet ultrices sem. Phasellus fringilla ultrices erat, vel aliquam sapien varius ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam porta semper sapien. Pellentesque volutpat porta sapien, ut tristique metus. In hac habitasse platea dictumst. Aenean pharetra molestie dapibus. Nunc sed dolor elit. Quisque eget enim non tellus volutpat mollis a id dolor. Aenean sit amet sem sem. Nunc viverra efficitur lorem. Quisque quis metus dictum, mattis ante non, pellentesque sapien. Integer quis lectus feugiat, consectetur nulla quis, viverra nulla. Curabitur eu sodales nisl. Morbi non enim pellentesque, lobortis est id, dignissim mauris. Nulla et tempor lectus. 15 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus dictum lorem ac leo tincidunt varius. Donec lacinia elementum lobortis. Nulla pellentesque cursus sem. Aliquam vestibulum lacinia metus, ac faucibus nunc fringilla a. Nullam mauris lorem, pharetra vitae mollis in, gravida a mi. Sed eu elit vitae lorem vestibulum volutpat eget blandit tortor. Duis dignissim porta dolor, ut porttitor lectus pretium vitae. Phasellus quis augue ante. Nam tempus egestas consectetur. Praesent nec placerat nisi, non malesuada dolor. Duis malesuada semper lorem, nec feugiat nisl. Nulla facilisi. Sed aliquam ex ut turpis malesuada dignissim. Nam risus mi, dapibus maximus nisl ac, efficitur suscipit ex. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Donec malesuada nisl eget faucibus mollis. Nam sit amet mauris a metus euismod porttitor et sed mi. Nunc vel vehicula arcu, eu lacinia odio. Fusce id lacus vel dui blandit maximus id eget neque. Sed eu porta diam. Nunc vitae egestas diam. Donec semper hendrerit laoreet. Aliquam quis aliquam nulla. Aenean euismod lacus sed pretium scelerisque. Suspendisse mollis arcu at ligula pulvinar, nec elementum velit fermentum. Sed sed mollis ligula, vel eleifend metus. Sed magna metus, tempus ut bibendum at, aliquam at nisi. Integer nec fringilla mauris, vel viverra augue. Morbi eu mi mauris. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Proin molestie ante nec tristique finibus. In hac habitasse platea dictumst. Maecenas sed risus condimentum, feugiat velit ac, dictum erat. Curabitur pharetra ac nulla sed lacinia. Curabitur rutrum dolor vestibulum magna ultrices congue ac sed libero. Nam semper mi a neque ultricies commodo. In condimentum in odio in porttitor. Suspendisse maximus vestibulum nunc, vel gravida dui fermentum eu. Morbi sed orci augue. Praesent dolor justo, cursus sit amet ex et, posuere mattis lorem. Donec in efficitur orci. Nam semper odio a interdum aliquet. Vivamus vitae luctus purus, in fermentum diam. Pellentesque quis orci vitae est placerat faucibus. Maecenas non gravida ipsum, sit amet ultrices sem. Phasellus fringilla ultrices erat, vel aliquam sapien varius ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam porta semper sapien. Pellentesque volutpat porta sapien, ut tristique metus. In hac habitasse platea dictumst. Aenean pharetra molestie dapibus. Nunc sed dolor elit. Quisque eget enim non tellus volutpat mollis a id dolor. Aenean sit amet sem sem. Nunc viverra efficitur lorem. Quisque quis metus dictum, mattis ante non, pellentesque sapien. Integer quis lectus feugiat, consectetur nulla quis, viverra nulla. Curabitur eu sodales nisl. Morbi non enim pellentesque, lobortis est id, dignissim mauris. Nulla et tempor lectus. 16 | scrolling behavior 17 | 18 | -------------------------------------------------------------------------------- /sample/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':sample', ':library', ':library-rxbinding', ':library-rxbinding-kotlin' 2 | --------------------------------------------------------------------------------