├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── README.md
├── art
├── screenshot1.gif
└── screenshot2.gif
├── library
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── com
│ │ └── tuenti
│ │ └── buttonmenu
│ │ ├── ButtonMenu.java
│ │ ├── animator
│ │ ├── ObjectAnimatorFactory.java
│ │ └── ScrollAnimator.java
│ │ └── viewmodel
│ │ ├── button
│ │ ├── ButtonCommand.java
│ │ ├── ButtonVM.java
│ │ ├── ButtonVMListener.java
│ │ ├── ButtonWithCounterVM.java
│ │ ├── ButtonWithMutableSubjectAndResourceVM.java
│ │ ├── ButtonWithMutableSubjectVM.java
│ │ ├── ButtonWithProgressVM.java
│ │ ├── CounterButtonVM.java
│ │ ├── MutableResourceButtonVM.java
│ │ ├── MutableSubjectButtonVM.java
│ │ ├── NullButtonVMListener.java
│ │ ├── ProgressButtonVM.java
│ │ └── SimpleButtonVM.java
│ │ └── buttonmenu
│ │ ├── ButtonMenuVM.java
│ │ ├── OnButtonCommandExecuted.java
│ │ └── SimpleButtonMenuVM.java
│ └── test
│ └── java
│ └── com
│ └── tuenti
│ └── buttonmenu
│ ├── ButtonMenuTest.java
│ ├── animator
│ └── ScrollAnimatorTest.java
│ └── viewmodel
│ ├── button
│ ├── ButtonVMTest.java
│ ├── ButtonWithCounterVMTest.java
│ ├── ButtonWithMutableSubjectAndResourceVMTest.java
│ ├── ButtonWithMutableSubjectVMTest.java
│ ├── ButtonWithProgressVMTest.java
│ └── SimpleButtonVMTest.java
│ └── buttonmenu
│ └── SimpleButtonMenuVMTest.java
├── pom.xml
└── sample
├── AndroidManifest.xml
├── pom.xml
├── res
├── drawable-hdpi
│ ├── app_icon.png
│ ├── contact_icon.png
│ ├── moment_icon.png
│ ├── photo_icon.png
│ └── refresh_icon.png
├── drawable-mdpi
│ ├── app_icon.png
│ ├── contact_icon.png
│ ├── moment_icon.png
│ ├── photo_icon.png
│ └── refresh_icon.png
├── drawable-xhdpi
│ ├── app_icon.png
│ ├── contact_icon.png
│ ├── moment_icon.png
│ ├── photo_icon.png
│ └── refresh_icon.png
├── drawable
│ └── button_menu.xml
├── layout
│ ├── activity_main.xml
│ ├── activity_second.xml
│ ├── contact_button.xml
│ ├── contact_row.xml
│ ├── moment_button.xml
│ ├── photo_button.xml
│ ├── photo_with_subtitle_button.xml
│ └── progress_button.xml
└── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── main
└── java
└── com
└── tuenti
└── buttonmenu
└── sample
└── ui
├── Agenda.java
├── Contact.java
├── activity
├── MainActivity.java
└── SecondActivity.java
├── buttonmenu
├── CustomButtonMenuVM.java
├── SecondButtonMenuVM.java
└── command
│ └── ShowToastCommand.java
└── renderer
├── ContactRenderer.java
└── ContactRendererBuilder.java
/.gitignore:
--------------------------------------------------------------------------------
1 | # Copyright: Tuenti Technologies
2 |
3 | # built application files
4 | *.apk
5 | *.ap_
6 | *.jar
7 |
8 | # lint folder
9 | lint
10 |
11 | # files for the dex VM
12 | *.dex
13 |
14 | # Java class files
15 | *.class
16 |
17 | # generated files
18 | bin/
19 | gen/
20 | classes/
21 | gen-external-apklibs/
22 |
23 | # maven output folder
24 | target
25 |
26 | # Local configuration file (sdk path, etc)
27 | local.properties
28 |
29 | # Eclipse project files
30 | .classpath
31 | .project
32 | .metadata
33 | .settings
34 |
35 | # IntelliJ files
36 | .idea
37 | *.iml
38 |
39 | # OSX files
40 | .DS_Store
41 |
42 | # Windows files
43 | Thumbs.db
44 |
45 | # vi swap files
46 | *.swp
47 |
48 | # backup files
49 | *.bak
50 |
51 | # gradle directory
52 | .gradle
53 | gradlew
54 | gradlew.bat
55 | gradle/
56 | build/
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: android
2 |
3 | android:
4 | components:
5 | - build-tools-18.1.1
6 | - android-18
7 | - extra-android-support
8 | - extra-google-m2repository
9 | - extra-android-m2repository
10 |
11 | before_install:
12 | - cp -R $ANDROID_HOME/extras/android/m2repository/ ~/.m2/repository/
13 |
14 | install: mvn clean install
15 |
16 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Button Menu [](https://travis-ci.org/tuenti/ButtonMenu) [](https://maven-badges.herokuapp.com/maven-central/com.tuenti.buttonmenu/library) [](https://android-arsenal.com/details/1/887)
2 | ===========
3 |
4 | ButtonMenu is an Android library created to build user interfaces based on buttons. This library has been implemented
5 | using Model View ViewModel pattern combined with an Android custom view that extends LinearLayout.
6 |
7 | In this library you will find a custom view implementation called ButtonMenu and a custom animator called
8 | ScrollAnimator you can use to link the scroll of a ListView with your ButtonMenu to show or hide the view when the
9 | user uses the ListView scroll.
10 |
11 | This library works on Android 2.X or higher versions.
12 |
13 | Screenshots
14 | -----------
15 |
16 | ![Demo Screenshot 1][1]
17 | ![Demo Screenshot 2][2]
18 |
19 | Download
20 | --------
21 |
22 | Download the project, compile it using ``mvn clean install`` import ``buttonmenu-1.0.9.jar`` into your project.
23 |
24 | Or declare it into your pom.xml
25 |
26 | ```xml
27 |
28 | com.tuenti.buttonmenu
29 | library
30 | 1.0.9
31 |
32 | ```
33 |
34 |
35 | Or into your build.gradle
36 | ```groovy
37 | dependencies{
38 | compile 'com.tuenti.buttonmenu:library:1.0.9'
39 | }
40 | ```
41 |
42 |
43 | Usage
44 | -----
45 |
46 | * 1. Add a ``ButtonMenu`` to your layout.
47 |
48 | ```xml
49 |
52 | ```
53 |
54 | * 2. Initialize your ButtonMenu widget with a ButtonMenuVM implementation inside your Activity or Fragment. You can use
55 | our SimpleButtonMenuVM implementation or create your own ButtonMenuVM implementation.
56 |
57 | ```java
58 | private void initializeButtonMenu() {
59 | button_menu = (ButtonMenu) findViewById(R.id.button_menu);
60 | button_menu.setButtonMenuVM(buttonMenuVM);
61 | button_menu.initialize();
62 | }
63 | ```
64 |
65 | * 3. If you want to create your custom ButtonMenuVM implementation you can follow the sample implemented in
66 | CustomButtonMenuVM.
67 |
68 | ```java
69 | public class CustomButtonMenuVM extends SimpleButtonMenuVM {
70 |
71 | /*
72 | * Every ButtonVM implementation could be moved to a different file extending SimpleButtonVM if needed.
73 | */
74 | private final ButtonVM moment = new SimpleButtonVM(R.layout.moment_button, R.id.moment, null);
75 | private final ButtonVM photo = new SimpleButtonVM(R.layout.photo_button, R.id.photo, null);
76 | private final ButtonVM contact = new SimpleButtonVM(R.layout.contact_button, R.id.contact, null);
77 |
78 | public CustomButtonMenuVM() {
79 | super();
80 | addItem(moment);
81 | addItem(photo);
82 | addItem(contact);
83 | }
84 | ```
85 |
86 | * 4. Connect your ButtonMenu widget with the ScrollAnimator to attach the scroll animation effect.
87 |
88 | ```java
89 | private void initializeScrollAnimator() {
90 | ScrollAnimator scrollAnimator = new ScrollAnimator(button_menu, new ObjectAnimatorFactory());
91 | scrollAnimator.configureListView(lv_contacts);
92 | scrollAnimator.setDurationInMillis(300);
93 | }
94 | ```
95 |
96 | Review different ButtonVM implementations -like ``SimpleButtonVM`` or ``ButtonWithMutableSubjectVM`` - in this
97 | project if you want to create your custom ButtonVM.
98 |
99 | Credits & Contact
100 | -----------------
101 |
102 | ButtonMenu was created by [Android team at Tuenti Technologies S.L.](http://github.com/tuenti). You can follow Tuenti
103 | engineering team on Twitter [@tuentieng](http://twitter.com/tuentieng).
104 |
105 | License
106 | -------
107 |
108 | ButtonMenu is available under the Apache License, Version 2.0. See LICENSE.txt file for more info.
109 |
110 | [1]: ./art/screenshot1.gif
111 | [2]: ./art/screenshot2.gif
112 |
--------------------------------------------------------------------------------
/art/screenshot1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/art/screenshot1.gif
--------------------------------------------------------------------------------
/art/screenshot2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/art/screenshot2.gif
--------------------------------------------------------------------------------
/library/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | com.tuenti.buttonmenu
7 | buttonmenu-parent
8 | 1.0.10-SNAPSHOT
9 |
10 |
11 | library
12 | jar
13 |
14 | ButtonMenu - Library
15 |
16 |
17 |
18 |
19 | junit
20 | junit
21 |
22 |
23 |
24 | org.robolectric
25 | robolectric
26 |
27 |
28 |
29 | org.mockito
30 | mockito-all
31 |
32 |
33 |
34 | com.nineoldandroids
35 | library
36 |
37 |
38 |
39 |
40 |
41 |
42 | ${project.basedir}/src/test/java
43 |
44 |
45 | com.jayway.maven.plugins.android.generation2
46 | android-maven-plugin
47 | true
48 |
49 | false
50 |
51 | false
52 |
53 | ${project.basedir}/res
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/ButtonMenu.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu;
18 |
19 | import android.annotation.TargetApi;
20 | import android.content.Context;
21 | import android.os.Build.VERSION_CODES;
22 | import android.util.AttributeSet;
23 | import android.view.LayoutInflater;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 | import android.widget.Button;
27 | import android.widget.LinearLayout;
28 | import android.widget.TextView;
29 |
30 | import com.tuenti.buttonmenu.viewmodel.button.ButtonCommand;
31 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
32 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVMListener;
33 | import com.tuenti.buttonmenu.viewmodel.button.ButtonWithProgressVM;
34 | import com.tuenti.buttonmenu.viewmodel.button.CounterButtonVM;
35 | import com.tuenti.buttonmenu.viewmodel.button.MutableResourceButtonVM;
36 | import com.tuenti.buttonmenu.viewmodel.button.MutableSubjectButtonVM;
37 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.ButtonMenuVM;
38 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.ButtonMenuVM.ButtonMenuVMListener;
39 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.OnButtonCommandExecuted;
40 |
41 | import java.util.Collection;
42 | import java.util.HashMap;
43 | import java.util.Map;
44 | import java.util.Map.Entry;
45 | import java.util.Set;
46 |
47 | /**
48 | * Base custom view created extending LinearLayout. This class works as the core of ButtonMenu library.
49 | *
50 | * Add a ButtonMenuVM implementation to this component to show a list of buttons.
51 | *
52 | * @author "Pedro Vicente Gómez Sánchez"
53 | */
54 | public class ButtonMenu extends LinearLayout implements ButtonVMListener, ButtonMenuVMListener {
55 |
56 | private static final int MIN_WEIGHT_SUM = 0;
57 | static final float WEIGHT_SUM = 100.0f;
58 |
59 | private Map items;
60 | private ButtonMenuVM buttonMenuVM;
61 | private OnButtonCommandExecuted onButtonCommandExecutedListener;
62 |
63 | public ButtonMenu(Context context) {
64 | super(context);
65 | initializeView();
66 | }
67 |
68 | public ButtonMenu(Context context, AttributeSet attrs) {
69 | super(context, attrs);
70 | initializeView();
71 | }
72 |
73 | @TargetApi(VERSION_CODES.HONEYCOMB)
74 | public ButtonMenu(Context context, AttributeSet attrs, int defStyle) {
75 | super(context, attrs, defStyle);
76 | initializeView();
77 | }
78 |
79 | /**
80 | * Join the Activity/Fragment lifecycle to the ButtonMenu custom view lifecycle. Call this method from the
81 | * initialize of your Activity/Fragment.
82 | */
83 | public void initialize() {
84 | clean();
85 | renderButtonMenuVM();
86 | registerListeners();
87 | }
88 |
89 | /**
90 | * Join the Activity/Fragment lifecycle to the ButtonMenu custom view lifecycle. Call this method from the
91 | * release of your Activity/Fragment.
92 | */
93 | public void release() {
94 | unregisterListeners();
95 | clean();
96 | }
97 |
98 | /**
99 | * Set the view model to configure the button menu state.
100 | * This method should be called before initialize method.
101 | *
102 | * @param buttonMenuVM used to configure the custom view
103 | */
104 | public void setButtonMenuVM(ButtonMenuVM buttonMenuVM) {
105 | this.buttonMenuVM = buttonMenuVM;
106 | }
107 |
108 | /**
109 | * Obtain the ButtonMenuVM implementation associated to the ButtonMenu instance.
110 | */
111 | public ButtonMenuVM getButtonMenuVM() {
112 | return buttonMenuVM;
113 | }
114 |
115 | /**
116 | * Attach a OnActionCommandExecutedListener to the ButtonMenu.
117 | *
118 | * @param onButtonCommandExecutedListener - The OnActionCommandExecutedListener to be attached.
119 | */
120 | public void setOnButtonCommandExecutedListener(OnButtonCommandExecuted onButtonCommandExecutedListener) {
121 | this.onButtonCommandExecutedListener = onButtonCommandExecutedListener;
122 | }
123 |
124 | @Override
125 | public void onEnablePropertyChanged(boolean enabled, ButtonVM buttonVM) {
126 | View view = getViewForViewModel(buttonVM);
127 | setIsEnabled(buttonVM, view, enabled);
128 | }
129 |
130 | @Override
131 | public void onCounterValueChanged(int counterValue, CounterButtonVM buttonVM) {
132 | View view = getViewForViewModel(buttonVM);
133 | int counterResourceId = buttonVM.getCounterWidgetId();
134 | renderCounter(buttonVM, view, counterResourceId);
135 | }
136 |
137 | @Override
138 | public void onImageResourceChanged(int imageResourceId, MutableResourceButtonVM buttonVM) {
139 | View view = getViewForViewModel(buttonVM);
140 | int viewResourceToChange = buttonVM.getResIdToChangeResource();
141 | renderImageResource(view, viewResourceToChange, imageResourceId);
142 | }
143 |
144 | @Override
145 | public void onSubjectChanged(String subject, MutableSubjectButtonVM buttonVM) {
146 | View view = getViewForViewModel(buttonVM);
147 | int subjectResourceId = buttonVM.getResIdToInsertSubject();
148 | renderSubject(view, subject, subjectResourceId);
149 | }
150 |
151 | @Override
152 | public void onButtonVMAdded(final ButtonVM buttonVM) {
153 | add(buttonVM);
154 | addItem(buttonVM);
155 | }
156 |
157 | @Override
158 | public void onButtonVMRemoved(final ButtonVM buttonVM) {
159 | remove(buttonVM);
160 | removeItem(buttonVM);
161 | }
162 |
163 | @Override
164 | public void onProgressValueChanged(boolean loading, ButtonWithProgressVM buttonVM) {
165 | View view = getViewForViewModel(buttonVM);
166 | int imageId = buttonVM.getImage();
167 | int progressId = buttonVM.getProgress();
168 | renderProgress(view, imageId, progressId, loading);
169 | }
170 |
171 |
172 | private void renderButtonMenuVM() {
173 | if (buttonMenuVM != null && buttonMenuVM.getButtonVMs() != null) {
174 | Set buttonVMList = this.buttonMenuVM.getButtonVMs();
175 | for (ButtonVM buttonVM : buttonVMList) {
176 | addItem(buttonVM);
177 | }
178 | }
179 | }
180 |
181 | private void addItem(final ButtonVM buttonVM) {
182 | if (!items.containsKey(buttonVM)) {
183 | View view = renderItem(buttonVM);
184 | hookActions(view, buttonVM);
185 | items.put(buttonVM, view);
186 | updateWeight();
187 | }
188 | }
189 |
190 | private void removeItem(final ButtonVM buttonVM) {
191 | if (items.containsKey(buttonVM)) {
192 | items.remove(buttonVM);
193 | updateWeight();
194 | }
195 | }
196 |
197 | private void initializeView() {
198 | initItemsCollection();
199 | initWeightSum();
200 | }
201 |
202 | private void initItemsCollection() {
203 | items = new HashMap();
204 | }
205 |
206 | private LayoutInflater getLayoutInflater() {
207 | Context context = this.getContext();
208 | return LayoutInflater.from(context);
209 | }
210 |
211 | private void initWeightSum() {
212 | // If the weight is unset or is not valid, we set it.
213 | if (getWeightSum() <= MIN_WEIGHT_SUM) {
214 | setWeightSum(WEIGHT_SUM);
215 | }
216 | }
217 |
218 | private View renderItem(ButtonVM buttonVM) {
219 | LayoutInflater layoutInflater = getLayoutInflater();
220 | View view = layoutInflater.inflate(buttonVM.getLayoutId(), null);
221 | this.addView(view);
222 | if (!buttonVM.isEnabled()) {
223 | setIsEnabled(buttonVM, view, false);
224 | }
225 | return view;
226 | }
227 |
228 | private void hookActions(final View view, final ButtonVM buttonVM) {
229 | boolean isEnabled = buttonVM.isEnabled();
230 | view.setEnabled(isEnabled);
231 | View clickableView = view.findViewById(buttonVM.getClickableResId());
232 | if (clickableView != null) {
233 | clickableView.setOnClickListener(new OnClickListener() {
234 | @Override
235 | public void onClick(View view) {
236 | ButtonCommand actionCommand = buttonVM.getButtonCommand();
237 | if (actionCommand != null) {
238 | notifyActionCommandListener();
239 | actionCommand.execute();
240 | }
241 | }
242 | });
243 | }
244 | }
245 |
246 | private void notifyActionCommandListener() {
247 | if (onButtonCommandExecutedListener != null) {
248 | onButtonCommandExecutedListener.onActionCommandExecuted();
249 | }
250 | }
251 |
252 | private void updateWeight() {
253 | Collection views = items.values();
254 | int viewCount = views.size();
255 | float weight = getWeightSum() / viewCount;
256 | for (View view : views) {
257 | LinearLayout.LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,
258 | ViewGroup.LayoutParams.MATCH_PARENT, weight);
259 | view.setLayoutParams(layoutParams);
260 | }
261 |
262 | }
263 |
264 | private void unregisterListeners() {
265 | unregisterButtonMenuVMListener();
266 | unregisterButtonVMListener();
267 | }
268 |
269 | private void registerListeners() {
270 | registerButtonMenuVMListener();
271 | registerButtonVMListener();
272 | }
273 |
274 | private void registerButtonVMListener() {
275 | for (ButtonVM buttonVM : items.keySet()) {
276 | buttonVM.registerListener(this);
277 | }
278 | }
279 |
280 | private void unregisterButtonVMListener() {
281 | for (ButtonVM buttonVM : items.keySet()) {
282 | buttonVM.unregisterListener();
283 | }
284 | }
285 |
286 | private void registerButtonMenuVMListener() {
287 | if (buttonMenuVM != null) {
288 | buttonMenuVM.registerListener(this);
289 | }
290 | }
291 |
292 | private void unregisterButtonMenuVMListener() {
293 | buttonMenuVM.unregisterListener(this);
294 | }
295 |
296 | private void setIsEnabled(final ButtonVM buttonVM, final View view, final boolean enabled) {
297 | int[] viewsIdToChange = buttonVM.getViewIdsToEnableOrDisable();
298 | for (int viewIdToChange : viewsIdToChange) {
299 | View viewToChange = view.findViewById(viewIdToChange);
300 | if (viewToChange != null) {
301 | viewToChange.setEnabled(enabled);
302 | }
303 | }
304 | view.setEnabled(enabled);
305 | }
306 |
307 | @TargetApi(VERSION_CODES.CUPCAKE)
308 | private void renderImageResource(View view, int viewResourceToChange, int imageResourceId) {
309 | Button button = (Button) view.findViewById(viewResourceToChange);
310 | if (button != null) {
311 | button.setCompoundDrawablesWithIntrinsicBounds(0, imageResourceId, 0, 0);
312 | }
313 | }
314 |
315 | private void renderSubject(View view, String subject, int subjectResourceId) {
316 | Button button = (Button) view.findViewById(subjectResourceId);
317 | if (button != null) {
318 | button.setText(subject);
319 | }
320 | }
321 |
322 | private void renderCounter(CounterButtonVM viewModel, View view, int counterResourceId) {
323 | TextView counter = (TextView) view.findViewById(counterResourceId);
324 | int counterValue = viewModel.getCounterValue();
325 | if (counterValue <= 0) {
326 | counter.setVisibility(View.INVISIBLE);
327 | } else {
328 | counter.setVisibility(View.VISIBLE);
329 | }
330 | String newCounter = "" + counterValue;
331 | counter.setText(newCounter);
332 | }
333 |
334 | private void renderProgress(View view, int viewResourceId, int progressResourceId,
335 | boolean show) {
336 | View image = view.findViewById(viewResourceId);
337 | View progressBar = view.findViewById(progressResourceId);
338 | image.setVisibility(show ? View.GONE : View.VISIBLE);
339 | progressBar.setVisibility(show ? View.VISIBLE : View.GONE);
340 | }
341 |
342 | private View getViewForViewModel(final ButtonVM viewModel) {
343 | View view = null;
344 | Set> entries = items.entrySet();
345 | for (Entry entry : entries) {
346 | if (entry.getKey().equals(viewModel)) {
347 | view = entry.getValue();
348 | break;
349 | }
350 | }
351 | return view;
352 | }
353 |
354 | private void clean() {
355 | for (View view : items.values()) {
356 | this.removeView(view);
357 | }
358 | items = new HashMap();
359 | }
360 |
361 | private void add(final ButtonVM buttonVM) {
362 | View view = getViewForViewModel(buttonVM);
363 | if (view != null) {
364 | addView(view);
365 | }
366 | }
367 |
368 | private void remove(final ButtonVM buttonVM) {
369 | View view = getViewForViewModel(buttonVM);
370 | if (view != null) {
371 | removeView(view);
372 | }
373 | }
374 | }
375 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/animator/ObjectAnimatorFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.animator;
18 |
19 | import android.view.View;
20 |
21 | import com.nineoldandroids.animation.ObjectAnimator;
22 |
23 | /**
24 | * ObjectAnimator factory created to provide ObjectAnimator objects used in ScrollAnimator to perform push in / push
25 | * out animations.
26 | *
27 | * @author Pedro Vicente Gómez Sánchez
28 | */
29 | public class ObjectAnimatorFactory {
30 |
31 | public ObjectAnimator getObjectAnimator(View animatedView, String animationType, int translationY) {
32 | return ObjectAnimator.ofFloat(animatedView, animationType, translationY);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/animator/ScrollAnimator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.animator;
18 |
19 |
20 | import android.view.View;
21 | import android.widget.AbsListView;
22 | import android.widget.AbsListView.OnScrollListener;
23 | import android.widget.ListView;
24 |
25 | import com.nineoldandroids.animation.Animator;
26 | import com.nineoldandroids.animation.ObjectAnimator;
27 |
28 |
29 | /**
30 | * Animate a view with a "translationY" animation when the user scrolls a ListView. This class registers
31 | * a scroll listener when a ListView is associated using "configureListView" method.
32 | *
33 | * @author Pedro Vicente Gómez Sánchez
34 | */
35 | public class ScrollAnimator {
36 |
37 | private static final int SCROLL_DIRECTION_CHANGE_THRESHOLD = 5;
38 | private static final String ANIMATION_TYPE = "translationY";
39 | private static final int DEFAULT_ANIMATION_DURATION_IN_MILLISECONDS = 200;
40 | private static final int HIDDEN_Y_POSITION = 0;
41 | protected static final int SCROLL_TO_TOP = -1;
42 | protected static final int SCROLL_TO_BOTTOM = 1;
43 |
44 | private final View animatedView;
45 | private final ObjectAnimatorFactory objectAnimatorFactory;
46 | private ListView listView;
47 | private OnScrollListener additionalScrollListener;
48 | private int scrollDirection = 0;
49 | private long durationInMillis = DEFAULT_ANIMATION_DURATION_IN_MILLISECONDS;
50 |
51 | public ScrollAnimator(View animatedView, ObjectAnimatorFactory objectAnimatorFactory) {
52 | this.animatedView = animatedView;
53 | this.objectAnimatorFactory = objectAnimatorFactory;
54 | }
55 |
56 | /**
57 | * Configure an additional scroll listener to be notified when the ListView scroll is updated.
58 | *
59 | * @param additionalScrollListener to notify.
60 | */
61 | public void setAdditionalScrollListener(OnScrollListener additionalScrollListener) {
62 | this.additionalScrollListener = additionalScrollListener;
63 | }
64 |
65 | /**
66 | * Associate a ListView to listen in order to perform the "translationY" animation when the ListView scroll is
67 | * updated. This method is going to set a "OnScrollListener" to the ListView passed as argument.
68 | *
69 | * @param listView to listen.
70 | */
71 | public void configureListView(ListView listView) {
72 | this.listView = listView;
73 | this.listView.setOnScrollListener(new OnScrollListener() {
74 |
75 | int scrollPosition;
76 |
77 | @Override
78 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
79 | notifyScrollToAdditionalScrollListener(view, firstVisibleItem, visibleItemCount, totalItemCount);
80 | View topChild = view.getChildAt(0);
81 |
82 | int newScrollPosition;
83 | if (topChild == null) {
84 | newScrollPosition = 0;
85 | } else {
86 | newScrollPosition = view.getFirstVisiblePosition() * topChild.getHeight() - topChild.getTop();
87 | }
88 | if (Math.abs(newScrollPosition - scrollPosition) >= SCROLL_DIRECTION_CHANGE_THRESHOLD) {
89 | onScrollPositionChanged(scrollPosition, newScrollPosition);
90 | }
91 |
92 | scrollPosition = newScrollPosition;
93 | }
94 |
95 | @Override
96 | public void onScrollStateChanged(AbsListView view, int scrollState) {
97 | notifyScrollStateChangedToAdditionalScrollListener(view, scrollState);
98 |
99 | }
100 | });
101 | }
102 |
103 | /**
104 | * Configure the "translationY" animation duration.
105 | *
106 | * @param duration in milliseconds.
107 | */
108 | public void setDurationInMillis(long duration) {
109 | this.durationInMillis = duration;
110 | }
111 |
112 | /**
113 | * Remove the scroll listener associated to the configured ListView.
114 | */
115 | public void release() {
116 | listView.setOnScrollListener(null);
117 | }
118 |
119 | /**
120 | * Show the animated view using a "translationY" animation.
121 | */
122 | public void showWithAnimation() {
123 | showWithAnimationWithListener(null);
124 | }
125 |
126 | /**
127 | * Show the animated view using a "translationY" animation and configure an AnimatorListener to be notified during
128 | * the animation.
129 | */
130 | public void showWithAnimationWithListener(Animator.AnimatorListener animatorListener) {
131 | scrollDirection = SCROLL_TO_TOP;
132 | ObjectAnimator objectAnimator = objectAnimatorFactory.getObjectAnimator(animatedView, ANIMATION_TYPE, HIDDEN_Y_POSITION);
133 | if (animatorListener != null) {
134 | objectAnimator.addListener(animatorListener);
135 | }
136 | objectAnimator.setDuration(durationInMillis);
137 | objectAnimator.start();
138 | }
139 |
140 | /**
141 | * Hide the animated view using a "translationY" animation.
142 | */
143 | public void hideWithAnimation() {
144 | hideWithAnimationWithListener(null);
145 | }
146 |
147 | /**
148 | * Hide the animated view using a "translationY" animation and configure an AnimatorListener to be notified
149 | * during the animation.
150 | */
151 | public void hideWithAnimationWithListener(Animator.AnimatorListener animatorListener) {
152 | scrollDirection = SCROLL_TO_BOTTOM;
153 | ObjectAnimator objectAnimator = objectAnimatorFactory.getObjectAnimator(animatedView, ANIMATION_TYPE, animatedView.getHeight());
154 | if (animatorListener != null) {
155 | objectAnimator.addListener(animatorListener);
156 | }
157 | objectAnimator.setDuration(durationInMillis);
158 | objectAnimator.start();
159 | }
160 |
161 | /**
162 | * Animate animated view from the current position to a "translationY" position.
163 | *
164 | * @param translationY final position.
165 | */
166 | protected void animate(int translationY) {
167 | ObjectAnimator animator = objectAnimatorFactory.getObjectAnimator(animatedView, ANIMATION_TYPE, translationY);
168 | animator.setDuration(durationInMillis);
169 | animator.start();
170 | }
171 |
172 | private void notifyScrollToAdditionalScrollListener(AbsListView view, int firstVisibleItem, int visibleItemCount,
173 | int totalItemCount) {
174 | if (additionalScrollListener != null) {
175 | additionalScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
176 | }
177 | }
178 |
179 | private void notifyScrollStateChangedToAdditionalScrollListener(AbsListView view, int scrollState) {
180 | if (additionalScrollListener != null) {
181 | additionalScrollListener.onScrollStateChanged(view, scrollState);
182 | }
183 | }
184 |
185 | /**
186 | * Perform the "translateY" animation using the new scroll position and the old scroll position to show or hide
187 | * the animated view.
188 | *
189 | * @param oldScrollPosition
190 | * @param newScrollPosition
191 | */
192 | private void onScrollPositionChanged(int oldScrollPosition, int newScrollPosition) {
193 | int newScrollDirection;
194 |
195 | if (newScrollPosition < oldScrollPosition) {
196 | newScrollDirection = SCROLL_TO_TOP;
197 | } else {
198 | newScrollDirection = SCROLL_TO_BOTTOM;
199 | }
200 |
201 | if (directionHasChanged(newScrollDirection)) {
202 | translateYAnimatedView(newScrollDirection);
203 | }
204 | }
205 |
206 | private boolean directionHasChanged(int newScrollDirection) {
207 | return newScrollDirection != scrollDirection;
208 | }
209 |
210 | private void translateYAnimatedView(int newScrollDirection) {
211 | scrollDirection = newScrollDirection;
212 | animatedView.post(new Runnable() {
213 |
214 | @Override
215 | public void run() {
216 | int translationY = hasScrolledToTop() ? HIDDEN_Y_POSITION : animatedView.getHeight();
217 | animate(translationY);
218 | }
219 | });
220 | }
221 |
222 | private boolean hasScrolledToTop() {
223 | return scrollDirection == SCROLL_TO_TOP;
224 | }
225 | }
226 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Command pattern implementation created to associate actions to ButtonVMs.
21 | *
22 | * @author Pedro Vicente Gómez Sánchez
23 | */
24 | public interface ButtonCommand {
25 |
26 | public void execute();
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 |
20 | /**
21 | * Interface created to represent a ButtonVM. This interface have to be implemented by each item added to
22 | * ButtonMenuVM implementations.
23 | *
24 | * This view model contains information for each item in a ButtonMenu. Contains the presentation state for each item
25 | * and have to be used to modify the item.
26 | *
27 | * @author "Pedro Vicente Gómez Sánchez"
28 | */
29 | public interface ButtonVM {
30 |
31 | /**
32 | * Method used to check if the item should be shown as enabled or disabled.
33 | *
34 | * @return true if enabled; otherwise false;
35 | */
36 | boolean isEnabled();
37 |
38 | /**
39 | * Disable the item and notify the ButtonVMListener.
40 | */
41 | void disable();
42 |
43 | /**
44 | * Enable the item and notify the ButtonVMListener.
45 | */
46 | void enable();
47 |
48 | /**
49 | * Method used by the ButtonMenu to inflate the view when a new item it's added to this component.
50 | *
51 | * @return an integer that represents the R.layout identifier.
52 | */
53 | int getLayoutId();
54 |
55 | /**
56 | * Method used by the ButtonMenu to execute a command with the onClickListener for one item has been executed.
57 | * This method can return a NULL ActionCommand if the implementation doesn't contains one.
58 | *
59 | * @return an ActionCommand implementation or null.
60 | */
61 | ButtonCommand getButtonCommand();
62 |
63 | /**
64 | * Register a listener to notify some changes like the enable or disable change.
65 | *
66 | * @param listener to register.
67 | */
68 | void registerListener(ButtonVMListener listener);
69 |
70 | /**
71 | * Un-register a listener from the listener collection.
72 | */
73 | void unregisterListener();
74 |
75 | /**
76 | * Method used by the ButtonMenu to hook the View.OnClickListenerMethod.
77 | *
78 | * @return an integer that represents the R.id identifier.
79 | */
80 | int getClickableResId();
81 |
82 | /**
83 | * Method used by the ButtonMenu to retrieve information about which widgets must be enabled or disabled when the
84 | * client code execute a disable or enable methods.
85 | *
86 | * @return a integer array that represents the R.id identifier to be disabled or enabled.
87 | */
88 | int[] getViewIdsToEnableOrDisable();
89 |
90 | /**
91 | * Method used to update the action command stored in a ButtonMenu.
92 | *
93 | * @param actionCommand
94 | */
95 | void setButtonCommand(ButtonCommand actionCommand);
96 | }
97 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonVMListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Interface created to work as a listener for ButtonVM. This interface contains some methods called when the client
21 | * code interacts with a ButtonVM.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public interface ButtonVMListener {
26 |
27 | /**
28 | * Method executed when the enable() or disable() method it's executed in a ButtonVM.
29 | *
30 | * @param enabled boolean represents the new ButtonVM state.
31 | * @param buttonVM that has suffer the change.
32 | */
33 | void onEnablePropertyChanged(final boolean enabled, final ButtonVM buttonVM);
34 |
35 | /**
36 | * Method executed when the counter value has changed in a CounterButtonVM.
37 | *
38 | * @param counterValue new counterValue change in the view model.
39 | * @param buttonVM that has suffer the change.
40 | */
41 | void onCounterValueChanged(final int counterValue, final CounterButtonVM buttonVM);
42 |
43 | /**
44 | * Method executed when the image resource has changed in a ImageResourceChangeVM.
45 | *
46 | * @param imageResourceId new image identifier.
47 | * @param buttonVM that has suffer the change.
48 | */
49 | void onImageResourceChanged(final int imageResourceId, final MutableResourceButtonVM buttonVM);
50 |
51 | /**
52 | * Method executed when the subject value change in the view model.
53 | *
54 | * @param subject new subject value.
55 | * @param buttonVm that has suffer the change.
56 | */
57 | void onSubjectChanged(final String subject, final MutableSubjectButtonVM buttonVm);
58 |
59 | /**
60 | * Method executed when the progress value change in the view model.
61 | *
62 | * @param loading new state of progressbar loading
63 | * @param buttonVm that has suffer the change.
64 | */
65 | void onProgressValueChanged(boolean loading, final ButtonWithProgressVM buttonVm);
66 | }
67 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithCounterVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * CounterButtonVM implementation based on SimpleButtonVM. This entity can be used by different components to
21 | * represent a simple button that can change the counter associated.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public class ButtonWithCounterVM extends SimpleButtonVM implements CounterButtonVM {
26 |
27 | private int counterValue;
28 | private final int counterWidgetId;
29 |
30 | public ButtonWithCounterVM(int layoutId, boolean enabled, int clickableResId, int[] enableDisableResIds,
31 | ButtonCommand actionCommand,
32 | int counterValue, int counterWidgetId) {
33 | super(layoutId, enabled, clickableResId, enableDisableResIds, actionCommand);
34 | this.counterValue = counterValue;
35 | this.counterWidgetId = counterWidgetId;
36 | }
37 |
38 | @Override
39 | public int getCounterValue() {
40 | return counterValue;
41 | }
42 |
43 | @Override
44 | public void setCounterValue(final int counterValue) {
45 | this.counterValue = counterValue;
46 | notifyCounterListener(counterValue);
47 | }
48 |
49 | @Override
50 | public int getCounterWidgetId() {
51 | return counterWidgetId;
52 | }
53 |
54 | private void notifyCounterListener(final int counterValue) {
55 | getListener().onCounterValueChanged(counterValue, this);
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithMutableSubjectAndResourceVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 |
20 | /**
21 | * ButtonVM implementation. This entity can be used by different components to represent a simple button that can
22 | * change this subject and image resource associated. The component that use this implementation must declare the
23 | * interface ButtonVM.
24 | *
25 | * @author "Pedro Vicente Gómez Sánchez"
26 | */
27 | public class ButtonWithMutableSubjectAndResourceVM extends SimpleButtonVM implements MutableSubjectButtonVM,
28 | MutableResourceButtonVM {
29 |
30 | private int imageId;
31 | private int imageResourceId;
32 | private String subject;
33 | private int subjectResourceId;
34 |
35 |
36 | public ButtonWithMutableSubjectAndResourceVM(int layoutId, boolean enabled,
37 | int clickableResId, int[]
38 | enableDisableResIds, ButtonCommand actionCommand, int imageResourceId,
39 | int subjectResourceId) {
40 | super(layoutId, enabled, clickableResId, enableDisableResIds, actionCommand);
41 | this.imageResourceId = imageResourceId;
42 | this.subjectResourceId = subjectResourceId;
43 | }
44 |
45 | @Override
46 | public int getImageResourceId() {
47 | return imageId;
48 | }
49 |
50 | @Override
51 | public void setImageResourceId(final int imageId) {
52 | this.imageId = imageId;
53 | notifyImageResourceChanged();
54 | }
55 |
56 | @Override
57 | public int getResIdToChangeResource() {
58 | return imageResourceId;
59 | }
60 |
61 | @Override
62 | public String getSubject() {
63 | return subject;
64 | }
65 |
66 | @Override
67 | public void setSubject(final String subject) {
68 | this.subject = subject;
69 | notifySubjectChanged();
70 | }
71 |
72 |
73 | @Override
74 | public int getResIdToInsertSubject() {
75 | return subjectResourceId;
76 | }
77 |
78 | private void notifyImageResourceChanged() {
79 | ButtonVMListener buttonVMListener = getListener();
80 | buttonVMListener.onImageResourceChanged(this.imageId, this);
81 | }
82 |
83 | private void notifySubjectChanged() {
84 | ButtonVMListener buttonVMListener = getListener();
85 | buttonVMListener.onSubjectChanged(this.subject, this);
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithMutableSubjectVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * ButtonWithMutableSubjectVM implementation based on SimpleButtonVM. This entity can be used by different components to
21 | * represent a simple button that can change the subject associated.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public class ButtonWithMutableSubjectVM extends SimpleButtonVM implements MutableSubjectButtonVM {
26 |
27 | private String subject;
28 | private int subjectResourceId;
29 |
30 | public ButtonWithMutableSubjectVM(int layoutId, int clickableResId, ButtonCommand actionCommand) {
31 | this(layoutId, true, clickableResId, new int[]{clickableResId}, clickableResId, actionCommand);
32 | }
33 |
34 | public ButtonWithMutableSubjectVM(int layoutId, boolean enabled, int clickableResId,
35 | int[] enableDisableResIds, int subjectResourceId, ButtonCommand actionCommand) {
36 | super(layoutId, enabled, clickableResId, enableDisableResIds, actionCommand);
37 | this.subjectResourceId = subjectResourceId;
38 | }
39 |
40 | @Override
41 | public String getSubject() {
42 | return subject;
43 | }
44 |
45 | @Override
46 | public void setSubject(final String subject) {
47 | this.subject = subject;
48 | notifySubjectChanged();
49 | }
50 |
51 | @Override
52 | public int getResIdToInsertSubject() {
53 | return subjectResourceId;
54 | }
55 |
56 | private void notifySubjectChanged() {
57 | ButtonVMListener buttonVMListener = getListener();
58 | buttonVMListener.onSubjectChanged(this.subject, this);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithProgressVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * ButtonWithProgressVM implementation based on SimpleButtonVM. This entity can be used by different components to
21 | * represent a simple button with a progressBar associated.
22 | *
23 | * @author "Iñaki Villar Algaba"
24 | */
25 | public class ButtonWithProgressVM extends SimpleButtonVM implements ProgressButtonVM {
26 |
27 | private int imageViewId;
28 | private int progressViewId;
29 | private boolean loading;
30 |
31 | public ButtonWithProgressVM(int layoutId, boolean enabled, int clickableResId,
32 | int[] enableDisableResIds, ButtonCommand actionCommand, int imageViewId,
33 | int progressBarId) {
34 | super(layoutId, enabled, clickableResId, enableDisableResIds, actionCommand);
35 | this.imageViewId = imageViewId;
36 | this.progressViewId = progressBarId;
37 | this.loading = false;
38 | }
39 |
40 | @Override
41 | public void showLoading() {
42 | loading = true;
43 | notifyShowProgress();
44 | }
45 |
46 | @Override
47 | public void closeLoading() {
48 | loading = false;
49 | notifyCloseProgress();
50 | }
51 |
52 | @Override
53 | public int getProgress() {
54 | return progressViewId;
55 | }
56 |
57 | @Override
58 | public int getImage() {
59 | return imageViewId;
60 | }
61 |
62 | @Override
63 | public boolean isLoading() {
64 | return loading;
65 | }
66 |
67 | private void notifyShowProgress() {
68 | ButtonVMListener buttonVMListener = getListener();
69 | buttonVMListener.onProgressValueChanged(true, this);
70 | }
71 |
72 | private void notifyCloseProgress() {
73 | ButtonVMListener buttonVMListener = getListener();
74 | buttonVMListener.onProgressValueChanged(false, this);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/CounterButtonVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Interface created to represent a ButtonVM that supports a counter. This interface have to be implemented by each
21 | * item added to ButtonMenuVM that use a counter inside the button.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public interface CounterButtonVM extends ButtonVM {
26 |
27 | /**
28 | * @return an integer with the counter value stored in this ButtonVM.
29 | */
30 | int getCounterValue();
31 |
32 | /**
33 | * Modify the counter value stored in this ButtonVM and notify the ButtonVMListener that the value has changed.
34 | *
35 | * @param counterValue with the new value.
36 | */
37 | void setCounterValue(final int counterValue);
38 |
39 | /**
40 | * @return the identifier associated to the widget that works as counter.
41 | */
42 | int getCounterWidgetId();
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/MutableResourceButtonVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Interface created to represent a ButtonVM that supports a image that can change. This interface have to be
21 | * implemented by each item added to ButtonMenuVM that use a image that can change inside the button.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public interface MutableResourceButtonVM extends ButtonVM {
26 |
27 | /**
28 | * @return the resource id associated to the image.
29 | */
30 | int getImageResourceId();
31 |
32 | /**
33 | * Change the resource id associated to the image stored in the ButtonVM and notify the ButtonVMListener.
34 | *
35 | * @param imageId to store.
36 | */
37 | public void setImageResourceId(final int imageId);
38 |
39 | /**
40 | * @return an integer with the widget identifier that it's going to change the source image using the image
41 | * resource identifier.
42 | */
43 | public int getResIdToChangeResource();
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/MutableSubjectButtonVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Interface created to represent a ButtonVM that supports a subject. This interface have to be implemented by each
21 | * item added to ButtonMenuVM that use a subject inside the button.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public interface MutableSubjectButtonVM extends ButtonVM {
26 |
27 | /**
28 | * @return the subject stored in the ButtonVM
29 | */
30 | String getSubject();
31 |
32 | /**
33 | * Change the subject stored in the view model and notify the ButtonVMListener the change.
34 | *
35 | * @param subject changed.
36 | */
37 | void setSubject(final String subject);
38 |
39 | /**
40 | * @return an integer associated to the resource id that it's going to store the image change.
41 | */
42 | int getResIdToInsertSubject();
43 |
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/NullButtonVMListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Null Object pattern implementation used to avoid null checks in ButtonVM.
21 | *
22 | * @author "Pedro Vicente Gómez Sánchez"
23 | */
24 | class NullButtonVMListener implements ButtonVMListener {
25 |
26 | @Override
27 | public void onEnablePropertyChanged(boolean enabled, ButtonVM buttonVM) {
28 | //Empty
29 | }
30 |
31 | @Override
32 | public void onCounterValueChanged(int counterValue, CounterButtonVM buttonVM) {
33 | //Empty
34 | }
35 |
36 | @Override
37 | public void onImageResourceChanged(int imageResourceId, MutableResourceButtonVM buttonVM) {
38 | //Empty
39 | }
40 |
41 | @Override
42 | public void onSubjectChanged(String subject, MutableSubjectButtonVM buttonVm) {
43 | //Empty
44 | }
45 |
46 | @Override
47 | public void onProgressValueChanged(boolean view, ButtonWithProgressVM buttonVm) {
48 | //Empty
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/ProgressButtonVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Interface created to represent a ButtonVM that supports a progressBar. This interface have to be
21 | * implemented by each item added to ButtonMenuVM that use a progressBar inside the button.
22 | *
23 | * @author "Iñaki Villar Algaba"
24 | */
25 | public interface ProgressButtonVM extends ButtonVM {
26 |
27 | /**
28 | * Change the state starting loading in the view model and notify the ButtonVMListener the
29 | * change.
30 | */
31 | void showLoading();
32 |
33 | /**
34 | * Change the state finishing loading in the view model and notify the ButtonVMListener the
35 | * change
36 | */
37 | void closeLoading();
38 |
39 | /**
40 | * @return the resource id associated to the progress
41 | */
42 | int getProgress();
43 |
44 | /**
45 | * @return the resource id associated to the image.
46 | */
47 | int getImage();
48 |
49 | /**
50 | * @return the state of loading of ProgressBar.
51 | */
52 | boolean isLoading();
53 | }
54 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/button/SimpleButtonVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | /**
20 | * Base ButtonVM implementation. This entity can be used by different components to represent a simple button that can't
21 | * change and contains an button command associated.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public class SimpleButtonVM implements ButtonVM {
26 |
27 | private final int layoutId;
28 | private boolean enabled;
29 | private final int clickableResId;
30 | private final int[] enableDisableResIds;
31 | private ButtonCommand buttonCommand;
32 | private ButtonVMListener listener;
33 |
34 | public SimpleButtonVM() {
35 | this(0, 0, null);
36 | }
37 |
38 | public SimpleButtonVM(int layoutId, int clickableResId, ButtonCommand buttonCommand) {
39 | this(layoutId, true, clickableResId, new int[]{clickableResId}, buttonCommand);
40 | }
41 |
42 | public SimpleButtonVM(int layoutId, boolean enabled, int clickableResId, int[] enableDisableResIds,
43 | ButtonCommand buttonCommand) {
44 | this.layoutId = layoutId;
45 | this.enabled = enabled;
46 | this.clickableResId = clickableResId;
47 | this.enableDisableResIds = enableDisableResIds;
48 | this.buttonCommand = buttonCommand;
49 | this.listener = new NullButtonVMListener();
50 | }
51 |
52 | @Override
53 | public boolean isEnabled() {
54 | return enabled;
55 | }
56 |
57 | @Override
58 | public void disable() {
59 | final boolean enabled = false;
60 | setEnabled(enabled);
61 | notifyIsEnabledListener(enabled);
62 | }
63 |
64 | @Override
65 | public void enable() {
66 | final boolean enabled = true;
67 | setEnabled(enabled);
68 | notifyIsEnabledListener(enabled);
69 | }
70 |
71 | @Override
72 | public int getLayoutId() {
73 | return layoutId;
74 | }
75 |
76 | @Override
77 | public ButtonCommand getButtonCommand() {
78 | return buttonCommand;
79 | }
80 |
81 | @Override
82 | public void registerListener(ButtonVMListener listener) {
83 | this.listener = listener;
84 | }
85 |
86 | @Override
87 | public void unregisterListener() {
88 | this.listener = new NullButtonVMListener();
89 | }
90 |
91 | @Override
92 | public int getClickableResId() {
93 | return clickableResId;
94 | }
95 |
96 | @Override
97 | public int[] getViewIdsToEnableOrDisable() {
98 | return enableDisableResIds;
99 | }
100 |
101 | @Override
102 | public void setButtonCommand(ButtonCommand buttonCommand) {
103 | this.buttonCommand = buttonCommand;
104 | }
105 |
106 | protected ButtonVMListener getListener() {
107 | return listener;
108 | }
109 |
110 | private void setEnabled(boolean enabled) {
111 | this.enabled = enabled;
112 | }
113 |
114 | private void notifyIsEnabledListener(final boolean enabled) {
115 | this.listener.onEnablePropertyChanged(enabled, this);
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/buttonmenu/ButtonMenuVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.buttonmenu;
18 |
19 | import java.util.Set;
20 |
21 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
22 |
23 |
24 | /**
25 | * Interface created to represent a ButtonMenu view model with some ButtonVM inside.
26 | * This view model supports the addition and removal of ButtonVM items.
27 | *
28 | * @author "Pedro Vicente Gómez Sánchez"
29 | */
30 | public interface ButtonMenuVM {
31 |
32 | /**
33 | * @return a list of ButtonVM stored in this view model.
34 | */
35 | Set getButtonVMs();
36 |
37 | /**
38 | * Registers a ButtonMenuVMListener item that will be notified when a ButtonVM is
39 | * added to/removed from the ButtonMenuVM.
40 | *
41 | * @param ButtonMenuVMListener to register.
42 | */
43 | void registerListener(ButtonMenuVMListener listener);
44 |
45 | /**
46 | * Un-registers a ButtonMenuVMListener.
47 | *
48 | * @param ButtonMenuVMListener to un-register.
49 | */
50 | void unregisterListener(ButtonMenuVMListener listener);
51 |
52 | /**
53 | * Enable every ButtonVM in the ButtonMenuVM.
54 | */
55 | void enable();
56 |
57 | /**
58 | * Disable every ButtonVM in the ButtonMenuVM.
59 | */
60 | void disable();
61 |
62 | /**
63 | * Interface created to represent a listener for the addition/removal of ButtonVM items.
64 | */
65 | interface ButtonMenuVMListener {
66 |
67 | /**
68 | * Notifies of a ButtonVM addition.
69 | *
70 | * @param buttonVM to notify it's addition.
71 | */
72 | void onButtonVMAdded(ButtonVM buttonVM);
73 |
74 | /**
75 | * Notifies of a ButtonVM removal.
76 | *
77 | * @param buttonVM to notify it's removal.
78 | */
79 | void onButtonVMRemoved(ButtonVM buttonVM);
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/buttonmenu/OnButtonCommandExecuted.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.buttonmenu;
18 |
19 | /**
20 | * Listener created to be executed when a ButtonVm ActionCommand it's executed.
21 | *
22 | * @author "Pedro Vicente Gómez Sánchez"
23 | */
24 | public interface OnButtonCommandExecuted {
25 |
26 | /**
27 | * Method executed when an action command it's executed.
28 | */
29 | void onActionCommandExecuted();
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/library/src/main/java/com/tuenti/buttonmenu/viewmodel/buttonmenu/SimpleButtonMenuVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.buttonmenu;
18 |
19 | import java.util.Collection;
20 | import java.util.LinkedHashSet;
21 | import java.util.LinkedList;
22 | import java.util.Set;
23 |
24 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
25 |
26 | /**
27 | * Main implementation of ButtonMenuVM. This entity contain the business logic associated to store ButtonVM's.
28 | * This class it's going to be extended by GroupConversationButtonMenuVm and IndividualConversationButtonMenuVm. This
29 | * entity has been created to avoid duplicate code.
30 | *
31 | * @author "Pedro Vicente Gómez Sánchez"
32 | */
33 | public class SimpleButtonMenuVM implements ButtonMenuVM {
34 |
35 | private final Set buttonVMs;
36 | private ButtonMenuVMListener listener;
37 |
38 | public SimpleButtonMenuVM() {
39 | this(new LinkedList());
40 | }
41 |
42 | public SimpleButtonMenuVM(ButtonVM buttonVM) {
43 | this.buttonVMs = new LinkedHashSet();
44 | this.buttonVMs.add(buttonVM);
45 | }
46 |
47 | public SimpleButtonMenuVM(Collection buttons) {
48 | this.buttonVMs = new LinkedHashSet();
49 | this.buttonVMs.addAll(buttons);
50 | }
51 |
52 | @Override
53 | public Set getButtonVMs() {
54 | return buttonVMs;
55 | }
56 |
57 | @Override
58 | public void enable() {
59 | for (ButtonVM buttonVM : buttonVMs) {
60 | buttonVM.enable();
61 | }
62 | }
63 |
64 | @Override
65 | public void disable() {
66 | for (ButtonVM buttonVM : buttonVMs) {
67 | buttonVM.disable();
68 | }
69 | }
70 |
71 | public void addItem(final ButtonVM buttonVM) {
72 | if (buttonVMs.add(buttonVM)) {
73 | notifyItemAdded(buttonVM);
74 | }
75 | }
76 |
77 | public void removeItem(final ButtonVM buttonVM) {
78 | if (buttonVMs.remove(buttonVM)) {
79 | notifyItemRemoved(buttonVM);
80 | }
81 | }
82 |
83 | @Override
84 | public void registerListener(ButtonMenuVMListener listener) {
85 | this.listener = listener;
86 | }
87 |
88 | @Override
89 | public void unregisterListener(ButtonMenuVMListener listener) {
90 | if (this.listener == listener) {
91 | this.listener = null;
92 | }
93 | }
94 |
95 | private void notifyItemAdded(ButtonVM buttonVM) {
96 | if (this.listener != null) {
97 | this.listener.onButtonVMAdded(buttonVM);
98 | }
99 | }
100 |
101 | private void notifyItemRemoved(ButtonVM buttonVM) {
102 | if (this.listener != null) {
103 | this.listener.onButtonVMRemoved(buttonVM);
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/ButtonMenuTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu;
18 |
19 | import android.view.View;
20 | import android.widget.LinearLayout.LayoutParams;
21 | import android.widget.TextView;
22 |
23 | import com.tuenti.buttonmenu.viewmodel.button.ButtonCommand;
24 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
25 | import com.tuenti.buttonmenu.viewmodel.button.ButtonWithCounterVM;
26 | import com.tuenti.buttonmenu.viewmodel.button.ButtonWithProgressVM;
27 | import com.tuenti.buttonmenu.viewmodel.button.SimpleButtonVM;
28 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.ButtonMenuVM;
29 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.OnButtonCommandExecuted;
30 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.SimpleButtonMenuVM;
31 |
32 | import org.junit.Before;
33 | import org.junit.Test;
34 | import org.junit.runner.RunWith;
35 | import org.mockito.Mock;
36 | import org.mockito.MockitoAnnotations;
37 | import org.robolectric.Robolectric;
38 | import org.robolectric.RobolectricTestRunner;
39 | import org.robolectric.annotation.Config;
40 |
41 | import java.util.LinkedList;
42 | import java.util.List;
43 |
44 | import static org.junit.Assert.assertEquals;
45 | import static org.junit.Assert.assertFalse;
46 | import static org.junit.Assert.assertTrue;
47 | import static org.mockito.Mockito.mock;
48 | import static org.mockito.Mockito.never;
49 | import static org.mockito.Mockito.verify;
50 |
51 | /**
52 | * Test created to check the correctness of ButtonMenu custom view working with ButtonMenuVM implementations.
53 | *
54 | * @author "Pedro Vicente Gómez Sánchez"
55 | */
56 | @Config(manifest = Config.NONE)
57 | @RunWith(RobolectricTestRunner.class)
58 | public class ButtonMenuTest {
59 |
60 | private static final int ANY_COUNTER_VALUE = 6;
61 | private static final double DELTA = 0.01;
62 |
63 | private List buttonVMs;
64 | private ButtonMenu buttonMenu;
65 | private SimpleButtonMenuVM buttonMenuVM;
66 | private ButtonMenuVM buttonMenuVMWithProgress;
67 | private ButtonMenuVM buttonMenuVMWithCounter;
68 | private ButtonWithCounterVM buttonVMWithCounter;
69 | private ButtonWithProgressVM buttonVMWithProgress;
70 |
71 | @Mock
72 | private ButtonCommand mockedButtonCommand1;
73 | @Mock
74 | private ButtonCommand mockedButtonCommand2;
75 | @Mock
76 | private ButtonCommand mockedButtonCommand3;
77 |
78 | @Before
79 | public void setUp() {
80 | MockitoAnnotations.initMocks(this);
81 | buttonMenu = new ButtonMenu(Robolectric.application);
82 |
83 | buttonVMs = new LinkedList();
84 | buttonVMs.add(new SimpleButtonVM(android.R.layout.simple_list_item_1, android.R.id.text1,
85 | mockedButtonCommand1));
86 | buttonVMs.add(new SimpleButtonVM(android.R.layout.activity_list_item, android.R.id.icon,
87 | mockedButtonCommand2));
88 | buttonMenuVM = new SimpleButtonMenuVM(buttonVMs);
89 |
90 | buttonVMWithCounter = new ButtonWithCounterVM(android.R.layout.simple_list_item_1,
91 | true, android.R.id.text1, new int[]{android.R.id.text1}, null, ANY_COUNTER_VALUE, android.R.id.text1);
92 | buttonMenuVMWithCounter = new SimpleButtonMenuVM(buttonVMWithCounter);
93 |
94 | buttonVMWithProgress = new ButtonWithProgressVM( android.R.layout.simple_expandable_list_item_2, true,
95 | android.R.id.text1, new int[] { android.R.id.text1, android.R.id.text2 },
96 | mockedButtonCommand1, android.R.id.text1,android.R.id.text2);
97 | buttonMenuVMWithProgress = new SimpleButtonMenuVM(buttonVMWithProgress);
98 | }
99 |
100 | @Test
101 | public void shouldBeEmptyIfNoButtonMenuVMIsAssociated() {
102 | buttonMenu.initialize();
103 |
104 | assertEquals(0, buttonMenu.getChildCount());
105 | }
106 |
107 | @Test
108 | public void shouldNotInflateButtonVMIfButtonMenuVmIsEmpty() {
109 | buttonMenu.setButtonMenuVM(new SimpleButtonMenuVM());
110 | buttonMenu.initialize();
111 |
112 | assertEquals(0, buttonMenu.getChildCount());
113 | }
114 |
115 | @Test
116 | public void shouldInflateButtonVMs() {
117 | initializeButtonMenu();
118 |
119 | assertEquals(2, buttonMenu.getChildCount());
120 | }
121 |
122 | @Test
123 | public void shouldExecuteActionCommandIfButtonsAreEnabled() {
124 | initializeButtonMenu();
125 |
126 | View view = buttonMenu.findViewById(android.R.id.text1);
127 | view.performClick();
128 |
129 | verify(mockedButtonCommand1).execute();
130 | }
131 |
132 |
133 | @Test
134 | public void shouldExecuteOnlyOneButtonVMCommand() {
135 | initializeButtonMenu();
136 |
137 | View view = buttonMenu.findViewById(android.R.id.icon);
138 | view.performClick();
139 |
140 | verify(mockedButtonCommand2).execute();
141 | verify(mockedButtonCommand1, never()).execute();
142 | }
143 |
144 | @Test
145 | public void shouldDisableButtonVMs() {
146 | initializeButtonMenu();
147 |
148 | buttonMenuVM.disable();
149 |
150 | assertFalse(buttonMenu.findViewById(android.R.id.text1).isEnabled());
151 | assertFalse(buttonMenu.findViewById(android.R.id.icon).isEnabled());
152 | }
153 |
154 | @Test
155 | public void shouldEnableButtonMenuVM() {
156 | initializeButtonMenu();
157 |
158 | buttonMenuVM.disable();
159 | buttonMenuVM.enable();
160 |
161 | assertTrue(buttonMenu.findViewById(android.R.id.text1).isEnabled());
162 | assertTrue(buttonMenu.findViewById(android.R.id.icon).isEnabled());
163 | }
164 |
165 | @Test
166 | public void shouldDisableButtonsOneByOne() {
167 | initializeButtonMenu();
168 |
169 | for (ButtonVM buttonVM : buttonMenuVM.getButtonVMs()) {
170 | buttonVM.disable();
171 | }
172 |
173 | assertFalse(buttonMenu.findViewById(android.R.id.icon).isEnabled());
174 | assertFalse(buttonMenu.findViewById(android.R.id.text1).isEnabled());
175 | }
176 |
177 | @Test
178 | public void shouldNotifyOnButtonCommandExecuted() {
179 | initializeButtonMenu();
180 | OnButtonCommandExecuted mockedOnButtonCommandExecuted = mock(OnButtonCommandExecuted.class);
181 | buttonMenu.setOnButtonCommandExecutedListener(mockedOnButtonCommandExecuted);
182 |
183 | buttonMenu.findViewById(android.R.id.text1).performClick();
184 |
185 | verify(mockedOnButtonCommandExecuted).onActionCommandExecuted();
186 | }
187 |
188 | @Test
189 | public void shouldReleaseButtonRemovingButtons() {
190 | initializeButtonMenu();
191 |
192 | buttonMenu.release();
193 |
194 | assertEquals(0, buttonMenu.getChildCount());
195 | }
196 |
197 | @Test
198 | public void everyChildShouldHaveTheSameWeightWithCorrectSum() {
199 | initializeButtonMenu();
200 |
201 | assertEveryChildHasTheSameWeightWithCorrectSum();
202 | }
203 |
204 | @Test
205 | public void everyChildShouldHaveTheSameWeightWithCorrectSumAfterAddingButton() {
206 | initializeButtonMenu();
207 |
208 | buttonMenuVM.addItem(new SimpleButtonVM(android.R.layout.simple_list_item_2,
209 | android.R.id.text2, mockedButtonCommand3));
210 |
211 | assertEveryChildHasTheSameWeightWithCorrectSum();
212 | }
213 |
214 | @Test
215 | public void everyChildShouldHaveTheSameWeightWithCorrectSumAfterRemovingButton() {
216 | initializeButtonMenu();
217 |
218 | buttonMenuVM.removeItem(buttonVMs.get(0));
219 |
220 | assertEveryChildHasTheSameWeightWithCorrectSum();
221 | }
222 |
223 | private void assertEveryChildHasTheSameWeightWithCorrectSum() {
224 | float weightSum = 0;
225 | float commonWeight = -1;
226 | for (int i = 0; i < buttonMenu.getChildCount(); i++) {
227 | View button = buttonMenu.getChildAt(i);
228 | float buttonWeight = ((LayoutParams) button.getLayoutParams()).weight;
229 | weightSum += buttonWeight;
230 | if (commonWeight == -1) {
231 | commonWeight = buttonWeight;
232 | } else {
233 | assertEquals(commonWeight, buttonWeight, DELTA);
234 | }
235 | }
236 | assertEquals(ButtonMenu.WEIGHT_SUM, weightSum, DELTA);
237 | }
238 |
239 | @Test
240 | public void shouldUpdateCounterValue() {
241 | initializeButtonMenuWithButtonMenuVM(buttonMenuVMWithCounter);
242 |
243 | buttonVMWithCounter.setCounterValue(ANY_COUNTER_VALUE);
244 |
245 | TextView counter = (TextView) buttonMenu.findViewById(android.R.id.text1);
246 | assertEquals(ANY_COUNTER_VALUE, Integer.parseInt((String) counter.getText()));
247 | }
248 |
249 | private void initializeButtonMenu() {
250 | initializeButtonMenuWithButtonMenuVM(buttonMenuVM);
251 | }
252 |
253 | @Test
254 | public void shouldUpdateProgressValue() {
255 | initializeButtonMenuWithButtonMenuVM(buttonMenuVMWithProgress);
256 |
257 | buttonVMWithProgress.showLoading();
258 |
259 | assertTrue(buttonVMWithProgress.isLoading());
260 | }
261 |
262 | @Test
263 | public void shouldUpdateProgressCloseValue() {
264 | initializeButtonMenuWithButtonMenuVM(buttonMenuVMWithProgress);
265 |
266 | buttonVMWithProgress.closeLoading();
267 |
268 | assertFalse(buttonVMWithProgress.isLoading());
269 | }
270 |
271 | private void initializeButtonMenuWithButtonMenuVM(ButtonMenuVM buttonMenuVM) {
272 | buttonMenu.setButtonMenuVM(buttonMenuVM);
273 | buttonMenu.initialize();
274 | }
275 |
276 | }
277 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/animator/ScrollAnimatorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.animator;
18 |
19 | import org.junit.Before;
20 | import org.junit.Test;
21 | import org.junit.runner.RunWith;
22 | import org.mockito.ArgumentCaptor;
23 | import org.mockito.Captor;
24 | import org.mockito.Mock;
25 | import org.mockito.MockitoAnnotations;
26 | import org.mockito.Spy;
27 | import org.robolectric.RobolectricTestRunner;
28 | import org.robolectric.annotation.Config;
29 |
30 | import static org.mockito.Mockito.mock;
31 | import static org.mockito.Mockito.verify;
32 | import static org.mockito.Mockito.when;
33 | import android.view.View;
34 | import android.widget.AbsListView.OnScrollListener;
35 | import android.widget.ListView;
36 |
37 | /**
38 | * Test created to check the correctness of ScrollAnimator implementation.
39 | *
40 | * @author "Pedro Vicente Gómez Sánchez"
41 | */
42 | @Config(manifest = Config.NONE)
43 | @RunWith(RobolectricTestRunner.class)
44 | public class ScrollAnimatorTest {
45 |
46 | private static final int ANIMATED_VIEW_HEIGHT = 100;
47 | private static final String ANIMATION_TYPE_TRANSLATION_Y = "translationY";
48 | private static final int TOTAL_ITEM_COUNT = 10;
49 | private static final int ANY_FIRST_VISIBLE_ITEM = 2;
50 | private static final int ANY_VISIBLE_ITEM_COUNT = 3;
51 | private static final int ANY_SCROLL_ACTION = 0;
52 | private static final int HIDDEN_Y_POSITION = 0;
53 | private static final int SHOW_Y_POSITION = ANIMATED_VIEW_HEIGHT;
54 |
55 | private ScrollAnimator scrollAnimator;
56 | private OnScrollListener scrollListener;
57 |
58 | @Spy
59 | private ObjectAnimatorFactory objectAnimatorFactory;
60 | @Mock
61 | private ListView listView;
62 | @Spy
63 | private View animatedView;
64 | @Captor
65 | private ArgumentCaptor scrollListenerCaptor;
66 |
67 | @Before
68 | public void setUp() {
69 | MockitoAnnotations.initMocks(this);
70 |
71 | scrollAnimator = new ScrollAnimator(animatedView, objectAnimatorFactory);
72 |
73 | setUpListView();
74 | }
75 |
76 | @Test
77 | public void shouldHideViewOnScrollToBottom() {
78 | scrollAnimator.configureListView(listView);
79 |
80 | scrollToBottom();
81 |
82 | verify(objectAnimatorFactory).getObjectAnimator(animatedView, ANIMATION_TYPE_TRANSLATION_Y, SHOW_Y_POSITION);
83 |
84 | }
85 |
86 | @Test
87 | public void shouldShowViewOnScrollToBottomAndThenToTop() {
88 | scrollAnimator.configureListView(listView);
89 |
90 | scrollToBottom();
91 | scrollToTop();
92 |
93 | verify(objectAnimatorFactory).getObjectAnimator(animatedView, ANIMATION_TYPE_TRANSLATION_Y, 0);
94 | }
95 |
96 | @Test
97 | public void shouldNotifyAdditionalScrollListenerOnScroll() {
98 | OnScrollListener mockedScrollListener = mock(OnScrollListener.class);
99 | scrollAnimator.setAdditionalScrollListener(mockedScrollListener);
100 | scrollAnimator.configureListView(listView);
101 |
102 | scrollToAnyPosition(ANY_FIRST_VISIBLE_ITEM, ANY_VISIBLE_ITEM_COUNT, TOTAL_ITEM_COUNT);
103 |
104 | verify(mockedScrollListener).onScroll(listView, ANY_FIRST_VISIBLE_ITEM, ANY_VISIBLE_ITEM_COUNT, TOTAL_ITEM_COUNT);
105 | }
106 |
107 | @Test
108 | public void shouldNotifyAdditionalScrollListenerOnScrollStateChanged() {
109 | OnScrollListener mockedScrollListener = mock(OnScrollListener.class);
110 | scrollAnimator.setAdditionalScrollListener(mockedScrollListener);
111 | scrollAnimator.configureListView(listView);
112 |
113 | doAnyScrollAction();
114 |
115 | verify(mockedScrollListener).onScrollStateChanged(listView, ANY_SCROLL_ACTION);
116 | }
117 |
118 | @Test
119 | public void shouldReleaseListViewScrollListener() {
120 | scrollAnimator.configureListView(listView);
121 |
122 | scrollAnimator.release();
123 |
124 | verify(listView).setOnScrollListener(null);
125 | }
126 |
127 | @Test
128 | public void shouldShowAnimatedView() {
129 | scrollAnimator.configureListView(listView);
130 |
131 | scrollAnimator.showWithAnimation();
132 |
133 | verify(objectAnimatorFactory).getObjectAnimator(animatedView, ANIMATION_TYPE_TRANSLATION_Y, HIDDEN_Y_POSITION);
134 | }
135 |
136 | @Test
137 | public void shouldHideAnimatedView() {
138 | scrollAnimator.configureListView(listView);
139 |
140 | scrollAnimator.hideWithAnimation();
141 |
142 | verify(objectAnimatorFactory).getObjectAnimator(animatedView, ANIMATION_TYPE_TRANSLATION_Y, SHOW_Y_POSITION);
143 | }
144 |
145 | private void scrollToBottom() {
146 | when(listView.getFirstVisiblePosition()).thenReturn(2);
147 | verify(listView).setOnScrollListener(scrollListenerCaptor.capture());
148 | scrollListener = scrollListenerCaptor.getValue();
149 | scrollListener.onScroll(listView, 0, 5, TOTAL_ITEM_COUNT);
150 | }
151 |
152 |
153 | private void scrollToTop() {
154 | when(listView.getFirstVisiblePosition()).thenReturn(1);
155 | verify(listView).setOnScrollListener(scrollListenerCaptor.capture());
156 | scrollListener = scrollListenerCaptor.getValue();
157 | scrollListener.onScroll(listView, 5, 0, TOTAL_ITEM_COUNT);
158 | }
159 |
160 | private void scrollToAnyPosition(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
161 | when(listView.getFirstVisiblePosition()).thenReturn(2);
162 | verify(listView).setOnScrollListener(scrollListenerCaptor.capture());
163 | scrollListener = scrollListenerCaptor.getValue();
164 | scrollListener.onScroll(listView, firstVisibleItem, visibleItemCount, totalItemCount);
165 | }
166 |
167 | private void doAnyScrollAction() {
168 | verify(listView).setOnScrollListener(scrollListenerCaptor.capture());
169 | scrollListener = scrollListenerCaptor.getValue();
170 | scrollListener.onScrollStateChanged(listView, ANY_SCROLL_ACTION);
171 | }
172 |
173 | private void setUpListView() {
174 | View topChild = mock(View.class);
175 | when(topChild.getHeight()).thenReturn(ANIMATED_VIEW_HEIGHT);
176 | when(animatedView.getHeight()).thenReturn(ANIMATED_VIEW_HEIGHT);
177 | when(topChild.getTop()).thenReturn(1);
178 | when(listView.getChildAt(0)).thenReturn(topChild);
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/button/ButtonVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | import org.junit.Before;
20 | import org.junit.Test;
21 | import org.mockito.Mock;
22 | import org.mockito.MockitoAnnotations;
23 |
24 | import static junit.framework.Assert.assertEquals;
25 | import static junit.framework.Assert.assertFalse;
26 | import static junit.framework.Assert.assertTrue;
27 | import static org.mockito.Mockito.times;
28 | import static org.mockito.Mockito.verify;
29 |
30 | /**
31 | * Test created to check the correctness of ButtonVM implementation. Every ButtonVM implementation should pass this
32 | * tests.
33 | *
34 | * @author "Pedro Vicente Gómez Sánchez"
35 | */
36 | public abstract class ButtonVMTest {
37 |
38 | protected static final int DEFAULT_LAYOUT_ID = 0;
39 | protected static final boolean DEFAULT_ENABLED_VALUE = true;
40 | protected static final int DEFAULT_CLICKABLE_RES_ID = 1;
41 | protected static final int[] DEFAULT_ENABLE_DISABLES_RES_IDS = {2};
42 |
43 | protected ButtonVM buttonVM;
44 |
45 | @Mock
46 | protected ButtonCommand mockedButtonCommand;
47 | @Mock
48 | protected ButtonVMListener mockedButtonVMListener;
49 |
50 | @Before
51 | public void setUp() {
52 | MockitoAnnotations.initMocks(this);
53 | buttonVM = getButtonVM();
54 | }
55 |
56 | @Test
57 | public void shouldContainsDefaultLayoutId() {
58 | assertEquals(DEFAULT_LAYOUT_ID, buttonVM.getLayoutId());
59 | }
60 |
61 | @Test
62 | public void shouldBeEnabledByDefault() {
63 | assertEquals(DEFAULT_ENABLED_VALUE, buttonVM.isEnabled());
64 | }
65 |
66 | @Test
67 | public void shouldContainDefaultClickableResId() {
68 | assertEquals(DEFAULT_CLICKABLE_RES_ID, buttonVM.getClickableResId());
69 | }
70 |
71 | @Test
72 | public void shouldContainsDefaultEnableDisableResIds() {
73 | assertEquals(DEFAULT_ENABLE_DISABLES_RES_IDS, buttonVM.getViewIdsToEnableOrDisable());
74 | }
75 |
76 | @Test
77 | public void shouldHaveDefaultActionCommandSet() {
78 | assertEquals(mockedButtonCommand, buttonVM.getButtonCommand());
79 | }
80 |
81 | @Test
82 | public void shouldDisableSimpleButtonVM() {
83 | buttonVM.disable();
84 |
85 | assertFalse(buttonVM.isEnabled());
86 | }
87 |
88 | @Test
89 | public void shouldEnableSimpleButtonVM() {
90 | buttonVM.disable();
91 |
92 | buttonVM.enable();
93 |
94 | assertTrue(buttonVM.isEnabled());
95 | }
96 |
97 | @Test
98 | public void shouldNotifyButtonVMListenerWhenEnable() {
99 | buttonVM.registerListener(mockedButtonVMListener);
100 |
101 | buttonVM.enable();
102 |
103 | verify(mockedButtonVMListener, times(1)).onEnablePropertyChanged(true, buttonVM);
104 | }
105 |
106 | @Test
107 | public void shouldNotifyButtonVMListenerWhenDisable() {
108 | buttonVM.registerListener(mockedButtonVMListener);
109 |
110 | buttonVM.disable();
111 |
112 | verify(mockedButtonVMListener).onEnablePropertyChanged(false, buttonVM);
113 | }
114 |
115 | protected abstract ButtonVM getButtonVM();
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithCounterVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | import org.junit.Test;
20 |
21 | import static junit.framework.Assert.assertEquals;
22 | import static org.mockito.Mockito.times;
23 | import static org.mockito.Mockito.verify;
24 |
25 | /**
26 | * Test created to check the correctness of ButtonWithCounterVM.
27 | *
28 | * @author "Pedro Vicente Gómez Sánchez"
29 | */
30 | public class ButtonWithCounterVMTest extends ButtonVMTest {
31 |
32 | private static final int DEFAULT_COUNTER_VALUE = 3;
33 | private static final int DEFAULT_COUNTER_WIDGET_ID = 4;
34 | private static final int ANY_OTHER_COUNTER_VALUE = 9;
35 |
36 | @Override
37 | protected ButtonVM getButtonVM() {
38 | return new ButtonWithCounterVM(DEFAULT_LAYOUT_ID, DEFAULT_ENABLED_VALUE,
39 | DEFAULT_CLICKABLE_RES_ID,
40 | DEFAULT_ENABLE_DISABLES_RES_IDS, mockedButtonCommand, DEFAULT_COUNTER_VALUE,
41 | DEFAULT_COUNTER_WIDGET_ID);
42 | }
43 |
44 | @Test
45 | public void shouldContainsDefaultCounterId() {
46 | ButtonWithCounterVM buttonWithCounterVM = (ButtonWithCounterVM) buttonVM;
47 |
48 | assertEquals(DEFAULT_COUNTER_VALUE, buttonWithCounterVM.getCounterValue());
49 | }
50 |
51 | @Test
52 | public void shouldContainsDefaultCounterWidgetResourceId() {
53 | ButtonWithCounterVM buttonWithCounterVM = (ButtonWithCounterVM) buttonVM;
54 |
55 | assertEquals(DEFAULT_COUNTER_WIDGET_ID, buttonWithCounterVM.getCounterWidgetId());
56 | }
57 |
58 | @Test
59 | public void shouldChangeCounterValue() {
60 | ButtonWithCounterVM buttonWithCounterVM = (ButtonWithCounterVM) buttonVM;
61 |
62 | buttonWithCounterVM.setCounterValue(ANY_OTHER_COUNTER_VALUE);
63 |
64 | assertEquals(ANY_OTHER_COUNTER_VALUE, buttonWithCounterVM.getCounterValue());
65 | }
66 |
67 | @Test
68 | public void shouldNotifyButtonVMListener() {
69 | ButtonWithCounterVM buttonWithCounterVM = (ButtonWithCounterVM) buttonVM;
70 | buttonWithCounterVM.registerListener(mockedButtonVMListener);
71 |
72 | buttonWithCounterVM.setCounterValue(ANY_OTHER_COUNTER_VALUE);
73 |
74 | verify(mockedButtonVMListener, times(1)).onCounterValueChanged(ANY_OTHER_COUNTER_VALUE, buttonWithCounterVM);
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithMutableSubjectAndResourceVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 |
20 | import org.junit.Test;
21 |
22 | import static junit.framework.Assert.assertEquals;
23 | import static org.mockito.Mockito.verify;
24 |
25 | /**
26 | * Test created to check the correctness of ButtonWithMutableSubjectAndResourceVM.
27 | *
28 | * @author "Pedro Vicente Gómez Sánchez"
29 | */
30 | public class ButtonWithMutableSubjectAndResourceVMTest extends ButtonWithMutableSubjectVMTest {
31 |
32 | private static final int DEFAULT_IMAGE_RESOURCE_ID = 11;
33 | private static final int ANY_IMAGE_ID = 12;
34 |
35 | @Override
36 | protected ButtonVM getButtonVM() {
37 | return new ButtonWithMutableSubjectAndResourceVM(DEFAULT_LAYOUT_ID, DEFAULT_ENABLED_VALUE,
38 | DEFAULT_CLICKABLE_RES_ID, DEFAULT_ENABLE_DISABLES_RES_IDS, mockedButtonCommand, DEFAULT_IMAGE_RESOURCE_ID,
39 | DEFAULT_SUBJECT_WIDGET_ID);
40 | }
41 |
42 | @Test
43 | public void shouldContainsDefaultResourceWidgetResourceId() {
44 | MutableResourceButtonVM buttonWithMutableResource = (MutableResourceButtonVM) buttonVM;
45 |
46 | assertEquals(DEFAULT_IMAGE_RESOURCE_ID, buttonWithMutableResource.getResIdToChangeResource());
47 | }
48 |
49 | @Test
50 | public void shouldChangeSubjectValue() {
51 | MutableResourceButtonVM buttonWithMutableResource = (MutableResourceButtonVM) buttonVM;
52 |
53 | buttonWithMutableResource.setImageResourceId(ANY_IMAGE_ID);
54 |
55 | assertEquals(ANY_IMAGE_ID, buttonWithMutableResource.getImageResourceId());
56 | }
57 |
58 | @Test
59 | public void shouldNotifyButtonVMListener() {
60 | MutableResourceButtonVM buttonWithMutableResource = (MutableResourceButtonVM) buttonVM;
61 | buttonWithMutableResource.registerListener(mockedButtonVMListener);
62 |
63 | buttonWithMutableResource.setImageResourceId(ANY_IMAGE_ID);
64 |
65 | verify(mockedButtonVMListener).onImageResourceChanged(ANY_IMAGE_ID, buttonWithMutableResource);
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithMutableSubjectVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 |
20 | import org.junit.Test;
21 |
22 | import static junit.framework.Assert.assertEquals;
23 | import static org.mockito.Mockito.verify;
24 |
25 | /**
26 | * Test created to check the correctness of ButtonWithMutableSubjectVM.
27 | *
28 | * @author "Pedro Vicente Gómez Sánchez"
29 | */
30 | public class ButtonWithMutableSubjectVMTest extends ButtonVMTest {
31 |
32 | protected static final int DEFAULT_SUBJECT_WIDGET_ID = 4;
33 | private static final String ANY_SUBJECT = "pgomez@tuenti.com";
34 |
35 | @Override
36 | protected ButtonVM getButtonVM() {
37 | return new ButtonWithMutableSubjectVM(DEFAULT_LAYOUT_ID, DEFAULT_ENABLED_VALUE, DEFAULT_CLICKABLE_RES_ID,
38 | DEFAULT_ENABLE_DISABLES_RES_IDS, DEFAULT_SUBJECT_WIDGET_ID, mockedButtonCommand);
39 | }
40 |
41 | @Test
42 | public void shouldContainsDefaultSubjectWidgetResourceId() {
43 | MutableSubjectButtonVM buttonWithMutableSubjectVM = (MutableSubjectButtonVM) buttonVM;
44 |
45 | assertEquals(DEFAULT_SUBJECT_WIDGET_ID, buttonWithMutableSubjectVM.getResIdToInsertSubject());
46 | }
47 |
48 | @Test
49 | public void shouldChangeSubjectValue() {
50 | MutableSubjectButtonVM buttonWithMutableSubjectVM = (MutableSubjectButtonVM) buttonVM;
51 |
52 | buttonWithMutableSubjectVM.setSubject(ANY_SUBJECT);
53 |
54 | assertEquals(ANY_SUBJECT, buttonWithMutableSubjectVM.getSubject());
55 | }
56 |
57 | @Test
58 | public void shouldNotifyButtonVMListener() {
59 | MutableSubjectButtonVM buttonWithMutableSubjectVM = (MutableSubjectButtonVM) buttonVM;
60 | buttonWithMutableSubjectVM.registerListener(mockedButtonVMListener);
61 |
62 | buttonWithMutableSubjectVM.setSubject(ANY_SUBJECT);
63 |
64 | verify(mockedButtonVMListener).onSubjectChanged(ANY_SUBJECT, buttonWithMutableSubjectVM);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/button/ButtonWithProgressVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.button;
18 |
19 | import org.junit.Test;
20 |
21 | import static junit.framework.Assert.assertEquals;
22 | import static junit.framework.Assert.assertTrue;
23 | import static junit.framework.Assert.assertFalse;
24 | import static org.mockito.Mockito.verify;
25 |
26 | /**
27 | * Test created to check the correctness of ButtonWithProgressVM.
28 | *
29 | * @author "Iñaki Villar Algaba"
30 | */
31 | public class ButtonWithProgressVMTest extends ButtonVMTest {
32 |
33 | protected static final int DEFAULT_IMAGE_ID = 5;
34 | protected static final int DEFAULT_PROGRESS_IMAGE_ID = 6;
35 |
36 | @Override
37 | protected ButtonVM getButtonVM() {
38 | return new ButtonWithProgressVM(DEFAULT_LAYOUT_ID, DEFAULT_ENABLED_VALUE,
39 | DEFAULT_CLICKABLE_RES_ID,
40 | DEFAULT_ENABLE_DISABLES_RES_IDS, mockedButtonCommand, DEFAULT_IMAGE_ID,
41 | DEFAULT_PROGRESS_IMAGE_ID);
42 | }
43 |
44 | @Test
45 | public void shouldContainsDefaultSubjectWidgetResourceId() {
46 | ButtonWithProgressVM buttonWithProgressVM = (ButtonWithProgressVM) buttonVM;
47 |
48 | assertEquals(DEFAULT_IMAGE_ID, buttonWithProgressVM.getImage());
49 | assertEquals(DEFAULT_PROGRESS_IMAGE_ID, buttonWithProgressVM.getProgress());
50 | }
51 |
52 | @Test
53 | public void shouldChangeProgressStartValue() {
54 | ButtonWithProgressVM buttonWithMutableSubjectVM = (ButtonWithProgressVM) buttonVM;
55 |
56 | buttonWithMutableSubjectVM.showLoading();
57 |
58 | assertTrue(buttonWithMutableSubjectVM.isLoading());
59 | }
60 |
61 | @Test
62 | public void shouldChangeProgressFinishValue() {
63 | ButtonWithProgressVM buttonWithMutableSubjectVM = (ButtonWithProgressVM) buttonVM;
64 |
65 | buttonWithMutableSubjectVM.closeLoading();
66 |
67 | assertFalse(buttonWithMutableSubjectVM.isLoading());
68 | }
69 |
70 | @Test
71 | public void shouldNotifyButtonVMListener() {
72 | ButtonWithProgressVM buttonWithProgressVM = (ButtonWithProgressVM) buttonVM;
73 | buttonWithProgressVM.registerListener(mockedButtonVMListener);
74 |
75 | buttonWithProgressVM.showLoading();
76 |
77 | verify(mockedButtonVMListener).onProgressValueChanged(true,
78 | buttonWithProgressVM);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/button/SimpleButtonVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 |
18 | package com.tuenti.buttonmenu.viewmodel.button;
19 |
20 | /**
21 | * Test created to check the correctness of SimpleButtonVM implementation.
22 | *
23 | * @author "Pedro Vicente Gómez Sánchez"
24 | */
25 | public class SimpleButtonVMTest extends ButtonVMTest {
26 |
27 | @Override
28 | protected ButtonVM getButtonVM() {
29 | return new SimpleButtonVM(DEFAULT_LAYOUT_ID, DEFAULT_ENABLED_VALUE, DEFAULT_CLICKABLE_RES_ID,
30 | DEFAULT_ENABLE_DISABLES_RES_IDS, mockedButtonCommand);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/library/src/test/java/com/tuenti/buttonmenu/viewmodel/buttonmenu/SimpleButtonMenuVMTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.viewmodel.buttonmenu;
18 |
19 |
20 | import java.util.Set;
21 |
22 | import org.junit.Before;
23 | import org.junit.Test;
24 | import org.mockito.Mock;
25 | import org.mockito.MockitoAnnotations;
26 |
27 | import static org.junit.Assert.assertEquals;
28 | import static org.junit.Assert.assertTrue;
29 |
30 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
31 |
32 | /**
33 | * Test created to check the correctness of SimpleButtonMenuVM.
34 | *
35 | * @author "Pedro Vicente Gómez Sánchez"
36 | */
37 | public class SimpleButtonMenuVMTest {
38 |
39 | private SimpleButtonMenuVM simpleButtonMenuVM;
40 |
41 | @Mock
42 | private ButtonVM mockedButtonVM;
43 |
44 | @Before
45 | public void setUp() {
46 | MockitoAnnotations.initMocks(this);
47 | initializeSimpleButtonMenuVM();
48 | }
49 |
50 | @Test
51 | public void shouldBeEmptyAfterConstruction() {
52 | assertTrue(simpleButtonMenuVM.getButtonVMs().isEmpty());
53 | }
54 |
55 |
56 | @Test
57 | public void shouldContainsAllTheAddedButtonVM() {
58 | simpleButtonMenuVM.addItem(mockedButtonVM);
59 |
60 | Set buttonVMs = simpleButtonMenuVM.getButtonVMs();
61 |
62 | assertEquals(1, buttonVMs.size());
63 | assertTrue(buttonVMs.contains(mockedButtonVM));
64 | }
65 |
66 | @Test
67 | public void shouldContainsNoRepeatedElements() {
68 | simpleButtonMenuVM.addItem(mockedButtonVM);
69 | simpleButtonMenuVM.addItem(mockedButtonVM);
70 |
71 | Set buttonVMs = simpleButtonMenuVM.getButtonVMs();
72 |
73 | assertEquals(1, buttonVMs.size());
74 | assertTrue(buttonVMs.contains(mockedButtonVM));
75 | }
76 |
77 | private void initializeSimpleButtonMenuVM() {
78 | simpleButtonMenuVM = new SimpleButtonMenuVM();
79 | }
80 |
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | ButtonMenu - Parent
6 | Android Custom View created to work with button menus easily.
7 | http://github.com/tuenti/ButtonMenu/
8 | 2014
9 |
10 | Tuenti Technologies S.L.
11 | http://corporate.tuenti.com/es/dev/blog
12 |
13 |
14 | library
15 | sample
16 |
17 |
18 | com.tuenti.buttonmenu
19 | buttonmenu-parent
20 | 1.0.10-SNAPSHOT
21 | pom
22 |
23 |
24 | org.sonatype.oss
25 | oss-parent
26 | 7
27 |
28 |
29 |
30 |
31 | UTF-8
32 | 4.1.1.4
33 | 3.9.0-rc.3
34 | 4.11
35 | 2.3
36 | 1.1.1
37 | 2.1.1
38 | 1.1.1
39 | 2.4.0
40 | 1.9.5
41 |
42 |
43 |
44 |
45 |
46 |
47 | com.tuenti.buttonmenu
48 | library
49 | ${project.version}
50 | jar
51 |
52 |
53 |
54 | junit
55 | junit
56 | ${junit.version}
57 | test
58 |
59 |
60 |
61 | com.google.android
62 | android
63 | ${android.version}
64 | provided
65 |
66 |
67 |
68 | com.google.android
69 | android-test
70 | ${android.version}
71 | test
72 |
73 |
74 |
75 | org.robolectric
76 | robolectric
77 | ${robolectric.version}
78 | test
79 |
80 |
81 |
82 | org.mockito
83 | mockito-all
84 | ${mockito-all.version}
85 |
86 |
87 |
88 | com.github.pedrovgs
89 | renderers
90 | ${renderers.version}
91 |
92 |
93 |
94 | com.squareup.picasso
95 | picasso
96 | ${picasso.version}
97 |
98 |
99 |
100 | com.nineoldandroids
101 | library
102 | ${library.version}
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | com.google.android
111 | android
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 | com.jayway.maven.plugins.android.generation2
120 | android-maven-plugin
121 | ${android-maven-plugin.version}
122 |
123 |
124 | 18
125 |
126 | true
127 |
128 |
129 |
130 | org.apache.maven.plugins
131 | maven-gpg-plugin
132 |
133 |
134 | sign-artifacts
135 | verify
136 |
137 | sign
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | Apache 2.0
149 | http://www.apache.org/licenses/LICENSE-2.0.txt
150 |
151 |
152 |
153 |
154 | https://github.com/tuenti/ButtonMenu/
155 | scm:git:git://github.com/tuenti/ButtonMenu.git
156 | scm:git:git@github.com:tuenti/ButtonMenu.git
157 | 1.0.0
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/sample/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/sample/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | com.tuenti.buttonmenu
7 | buttonmenu-parent
8 | 1.0.10-SNAPSHOT
9 |
10 |
11 | sample
12 | apk
13 |
14 | ButtonMenu - Sample
15 |
16 |
17 |
18 |
19 | com.tuenti.buttonmenu
20 | library
21 |
22 |
23 |
24 | com.github.pedrovgs
25 | renderers
26 |
27 |
28 |
29 |
30 | com.squareup.picasso
31 | picasso
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | com.jayway.maven.plugins.android.generation2
41 | android-maven-plugin
42 | true
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-hdpi/app_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/contact_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-hdpi/contact_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/moment_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-hdpi/moment_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/photo_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-hdpi/photo_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-hdpi/refresh_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-hdpi/refresh_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-mdpi/app_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/contact_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-mdpi/contact_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/moment_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-mdpi/moment_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/photo_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-mdpi/photo_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-mdpi/refresh_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-mdpi/refresh_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-xhdpi/app_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/contact_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-xhdpi/contact_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/moment_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-xhdpi/moment_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/photo_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-xhdpi/photo_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable-xhdpi/refresh_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tuenti/ButtonMenu/95791383f6f976933496542b54e8c6dbdd73e669/sample/res/drawable-xhdpi/refresh_icon.png
--------------------------------------------------------------------------------
/sample/res/drawable/button_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
15 |
16 |
--------------------------------------------------------------------------------
/sample/res/layout/activity_second.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
16 |
17 |
22 |
23 |
24 |
29 |
30 |
31 |
36 |
37 |
42 |
43 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/sample/res/layout/contact_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/sample/res/layout/contact_row.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
10 |
11 |
15 |
16 |
21 |
22 |
27 |
28 |
--------------------------------------------------------------------------------
/sample/res/layout/moment_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/sample/res/layout/photo_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/sample/res/layout/photo_with_subtitle_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/sample/res/layout/progress_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
9 |
10 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/sample/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FF0071CD
4 | #FF005EAA
5 | #80000000
6 | #FFFFFFFF
7 |
--------------------------------------------------------------------------------
/sample/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 48dip
4 | 44dip
5 | 14dip
6 | 10dip
7 | 8dip
8 | 16sp
9 | 12sp
10 | 4dip
11 |
--------------------------------------------------------------------------------
/sample/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Button Menu
4 | Remove/Add moment ButtonVM
5 | Enable/Disable
6 | Enable/Disable photo ButtonVM
7 | Change icon
8 | Change subtitle
9 | Start progress
10 | Stop progress
11 | Take a picture
12 | Contacts
13 |
14 |
--------------------------------------------------------------------------------
/sample/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
13 |
14 |
21 |
22 |
25 |
26 |
29 |
32 |
33 |
36 |
37 |
38 |
44 |
45 |
52 |
53 |
60 |
61 |
67 |
68 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/Agenda.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui;
18 |
19 | import java.util.ArrayList;
20 | import java.util.Collection;
21 | import java.util.List;
22 |
23 | import com.pedrogomez.renderers.AdapteeCollection;
24 |
25 | /**
26 | * Class created to contain Contact instances.
27 | */
28 | public class Agenda implements AdapteeCollection {
29 |
30 | private List contacts = new ArrayList();
31 |
32 | /*
33 | * Add fake info to the contacts collection to be used in the sample.
34 | */
35 | public Agenda() {
36 | add(new Contact("Jamie Torres ", "16:40", "Can you call me?", "http://api.randomuser.me/portraits/men/30.jpg"));
37 | add(new Contact("Rachel Phillips", "16:59", "Ey! Do you have something to do today?",
38 | "http://api.randomuser.me/portraits/women/49.jpg"));
39 | add(new Contact("Keith Gilbert", "18:15", "jajajaja ;)", "http://api.randomuser.me/portraits/men/79.jpg"));
40 | add(new Contact("Joaquin José", "18:50", "ok! See you tomorrow :)",
41 | "http://api.randomuser.me/portraits/men/58.jpg"));
42 | add(new Contact("David Saint", "18:50", "ok! See you tomorrow :)",
43 | "http://api.randomuser.me/portraits/men/11.jpg"));
44 | add(new Contact("Dawn Moreno ", "yesterday", "........ are you kidding?",
45 | "http://api.randomuser.me/portraits/women/66" +
46 | ".jpg"));
47 | add(new Contact("Kina Gregory ", "yesterday", "Do you have the last preproduction version?",
48 | "http://api.randomuser.me/portraits/women/89.jpg"));
49 | add(new Contact("Jake Gómez", "yesterday", "This library is awesome!!", "http://api.randomuser.me/portraits/men/60" +
50 | ".jpg"));
51 | add(new Contact("Leticia Jackson ", "two days ago", "I miss you :_(",
52 | "http://api.randomuser.me/portraits/women/39.jpg"));
53 | add(new Contact("Eva Rodriguez", "four days ago", "Ok, have a nice day! ;)",
54 | "http://api.randomuser.me/portraits/women/7.jpg"));
55 | add(new Contact("Jamie Torres ", "16:40", "Can you call me?", "http://api.randomuser.me/portraits/men/30.jpg"));
56 | add(new Contact("Rachel Phillips", "16:59", "Ey! Do you have something to do today?",
57 | "http://api.randomuser.me/portraits/women/49.jpg"));
58 | add(new Contact("Keith Gilbert", "18:15", "jajajaja ;)", "http://api.randomuser.me/portraits/men/79.jpg"));
59 | add(new Contact("Joaquin José", "18:50", "ok! See you tomorrow :)",
60 | "http://api.randomuser.me/portraits/men/58.jpg"));
61 | add(new Contact("David Saint", "18:50", "ok! See you tomorrow :)",
62 | "http://api.randomuser.me/portraits/men/11.jpg"));
63 | add(new Contact("Dawn Moreno ", "yesterday", "........ are you kidding?",
64 | "http://api.randomuser.me/portraits/women/66" +
65 | ".jpg"));
66 | add(new Contact("Kina Gregory ", "yesterday", "Do you have the last preproduction version?",
67 | "http://api.randomuser.me/portraits/women/89.jpg"));
68 | add(new Contact("Jake Gómez", "yesterday", "This library is awesome!!", "http://api.randomuser.me/portraits/men/60" +
69 | ".jpg"));
70 | add(new Contact("Leticia Jackson ", "two days ago", "I miss you :_(",
71 | "http://api.randomuser.me/portraits/women/39.jpg"));
72 | add(new Contact("Eva Rodriguez", "four days ago", "Ok, have a nice day! ;)",
73 | "http://api.randomuser.me/portraits/women/7.jpg"));
74 | }
75 |
76 | @Override
77 | public int size() {
78 | return contacts.size();
79 | }
80 |
81 | @Override
82 | public Contact get(int index) {
83 | return contacts.get(index);
84 | }
85 |
86 | @Override
87 | public void add(Contact element) {
88 | contacts.add(element);
89 | }
90 |
91 | @Override
92 | public void remove(Contact element) {
93 | contacts.remove(element);
94 | }
95 |
96 | @Override
97 | public void addAll(Collection elements) {
98 | contacts.addAll(elements);
99 | }
100 |
101 | @Override
102 | public void removeAll(Collection elements) {
103 | contacts.removeAll(elements);
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/Contact.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui;
18 |
19 | /**
20 | * Contains all the information needed of a contact.
21 | */
22 | public class Contact {
23 |
24 | private final String name;
25 | private final String lastDate;
26 | private final String lastMessage;
27 | private final String avatar;
28 |
29 | public Contact(String name, String lastDate, String lastMessage, String avatar) {
30 | this.name = name;
31 | this.lastDate = lastDate;
32 | this.lastMessage = lastMessage;
33 | this.avatar = avatar;
34 | }
35 |
36 | public String getName() {
37 | return name;
38 | }
39 |
40 | public String getLastDate() {
41 | return lastDate;
42 | }
43 |
44 | public String getLastMessage() {
45 | return lastMessage;
46 | }
47 |
48 | public String getAvatar() {
49 | return avatar;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/activity/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui.activity;
18 |
19 | import java.util.ArrayList;
20 | import java.util.List;
21 |
22 | import android.app.Activity;
23 | import android.content.Intent;
24 | import android.os.Bundle;
25 | import android.view.View;
26 | import android.widget.AdapterView;
27 | import android.widget.AdapterView.OnItemClickListener;
28 | import android.widget.ListView;
29 |
30 | import com.pedrogomez.renderers.Renderer;
31 | import com.pedrogomez.renderers.RendererAdapter;
32 | import com.tuenti.buttonmenu.ButtonMenu;
33 | import com.tuenti.buttonmenu.animator.ObjectAnimatorFactory;
34 | import com.tuenti.buttonmenu.animator.ScrollAnimator;
35 | import com.tuenti.buttonmenu.sample.R;
36 | import com.tuenti.buttonmenu.sample.ui.Agenda;
37 | import com.tuenti.buttonmenu.sample.ui.Contact;
38 | import com.tuenti.buttonmenu.sample.ui.buttonmenu.CustomButtonMenuVM;
39 | import com.tuenti.buttonmenu.sample.ui.renderer.ContactRenderer;
40 | import com.tuenti.buttonmenu.sample.ui.renderer.ContactRendererBuilder;
41 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.ButtonMenuVM;
42 |
43 | public class MainActivity extends Activity {
44 |
45 | private final ButtonMenuVM buttonMenuVM = new CustomButtonMenuVM();
46 |
47 | private ButtonMenu button_menu;
48 | private ListView lv_contacts;
49 |
50 | private Agenda agenda = new Agenda();
51 |
52 | @Override
53 | protected void onCreate(Bundle savedInstanceState) {
54 | super.onCreate(savedInstanceState);
55 | setContentView(R.layout.activity_main);
56 | mapGui();
57 | hookListeners();
58 | initializeButtonMenu();
59 | initializeContactsList();
60 | }
61 |
62 | private void mapGui() {
63 | button_menu = (ButtonMenu) findViewById(R.id.button_menu);
64 | lv_contacts = (ListView) findViewById(R.id.lv_contacts);
65 | }
66 |
67 | private void hookListeners() {
68 | lv_contacts.setOnItemClickListener(new OnItemClickListener() {
69 | @Override
70 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
71 | openSecondActivity();
72 | }
73 | });
74 | }
75 |
76 | private void openSecondActivity() {
77 | Intent intent = new Intent(this, SecondActivity.class);
78 | startActivity(intent);
79 | }
80 |
81 | /**
82 | * Set the ButtonMenuVM implementation to the ButtonMenu custom view and initialize it.
83 | */
84 | private void initializeButtonMenu() {
85 | button_menu = (ButtonMenu) findViewById(R.id.button_menu);
86 | button_menu.setButtonMenuVM(buttonMenuVM);
87 | button_menu.initialize();
88 | }
89 |
90 | private void initializeContactsList() {
91 | List> prototypes = new ArrayList>();
92 | prototypes.add(new ContactRenderer(this));
93 | ContactRendererBuilder contactRendererBuilder = new ContactRendererBuilder(prototypes);
94 |
95 | RendererAdapter adapter = new RendererAdapter(getLayoutInflater(), contactRendererBuilder, agenda);
96 | lv_contacts.setAdapter(adapter);
97 |
98 | initializeScrollAnimator();
99 | }
100 |
101 | /**
102 | * Initialize ScrollAnimator to work with ButtonMenu custom view, the ListView used in this sample and an
103 | * animation duration of 200 milliseconds.
104 | */
105 | private void initializeScrollAnimator() {
106 | ScrollAnimator scrollAnimator = new ScrollAnimator(button_menu, new ObjectAnimatorFactory());
107 | scrollAnimator.configureListView(lv_contacts);
108 | scrollAnimator.setDurationInMillis(300);
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/activity/SecondActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui.activity;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.view.View;
22 | import android.view.View.OnClickListener;
23 | import android.widget.Button;
24 |
25 | import com.tuenti.buttonmenu.ButtonMenu;
26 | import com.tuenti.buttonmenu.sample.R;
27 | import com.tuenti.buttonmenu.sample.ui.buttonmenu.SecondButtonMenuVM;
28 |
29 | public class SecondActivity extends Activity {
30 |
31 | private final SecondButtonMenuVM buttonMenuVM = new SecondButtonMenuVM(this);
32 |
33 | private ButtonMenu button_menu;
34 | private Button bt_remove_add_button;
35 | private Button bt_enable_disable_all;
36 | private Button bt_enable_disable_photo;
37 | private Button bt_change_icon;
38 | private Button bt_change_subtitle;
39 | private Button bt_start_progress;
40 |
41 | @Override
42 | protected void onCreate(Bundle savedInstanceState) {
43 | super.onCreate(savedInstanceState);
44 | setContentView(R.layout.activity_second);
45 | mapGui();
46 | hookListeners();
47 | initializeButtonMenu();
48 | }
49 |
50 | private void mapGui() {
51 | button_menu = (ButtonMenu) findViewById(R.id.button_menu);
52 | bt_remove_add_button = (Button) findViewById(R.id.bt_remove_add_button);
53 | bt_enable_disable_all = (Button) findViewById(R.id.bt_enable_disable_all);
54 | bt_enable_disable_photo = (Button) findViewById(R.id.bt_enable_disable_photo);
55 | bt_change_icon = (Button) findViewById(R.id.bt_change_icon);
56 | bt_change_subtitle = (Button) findViewById(R.id.bt_change_subtitle);
57 | bt_start_progress = (Button) findViewById(R.id.bt_start_progress);
58 | }
59 |
60 | private void initializeButtonMenu() {
61 | button_menu.setButtonMenuVM(buttonMenuVM);
62 | button_menu.initialize();
63 | }
64 |
65 | private void hookListeners() {
66 | bt_remove_add_button.setOnClickListener(new OnClickListener() {
67 | @Override
68 | public void onClick(View v) {
69 | /*
70 | * Display or remove just one element inside the ButtonMenuVM implementation.
71 | */
72 | if (buttonMenuVM.isMomentButtonInMenu()) {
73 | buttonMenuVM.removeMomentButton();
74 | } else {
75 | buttonMenuVM.addMomentButton();
76 | }
77 | }
78 | });
79 | bt_enable_disable_all.setOnClickListener(new OnClickListener() {
80 | @Override
81 | public void onClick(View v) {
82 | boolean enable = !button_menu.getChildAt(0).isEnabled();
83 | if (enable) {
84 | buttonMenuVM.enable();
85 | } else {
86 | buttonMenuVM.disable();
87 | }
88 | }
89 | });
90 |
91 | bt_enable_disable_photo.setOnClickListener(new OnClickListener() {
92 | @Override
93 | public void onClick(View v) {
94 | /*
95 | * Enable or disable just one element inside the ButtonMenuVM implementation.
96 | */
97 | if (buttonMenuVM.isPhotoButtonEnabled()) {
98 | buttonMenuVM.disablePhotoButton();
99 | } else {
100 | buttonMenuVM.enablePhotoButton();
101 | }
102 | }
103 | });
104 |
105 | bt_change_icon.setOnClickListener(new OnClickListener() {
106 | @Override
107 | public void onClick(View v) {
108 | /*
109 | * Change the icon of one element inside the ButtonMenuVM implementation
110 | */
111 | buttonMenuVM.changePhotoIcon();
112 | }
113 | });
114 |
115 | bt_change_subtitle.setOnClickListener(new OnClickListener() {
116 | @Override
117 | public void onClick(View v) {
118 | /*
119 | * Change the subtitle of one element inside the ButtonMenuVM implementation
120 | */
121 | buttonMenuVM.changePhotoIconSubtitle();
122 | }
123 | });
124 |
125 | bt_start_progress.setOnClickListener(new OnClickListener() {
126 | @Override
127 | public void onClick(View v) {
128 | /*
129 | * Start progress loading of one element inside the ButtonVM implementation
130 | */
131 | if(buttonMenuVM.isLoading()) {
132 | buttonMenuVM.closeLoading();
133 | bt_start_progress.setText(getResources().getString(R.string.
134 | button_text_start_progress));
135 | } else {
136 | buttonMenuVM.showLoading();
137 | bt_start_progress.setText(getResources().getString(R.string
138 | .button_text_stop_progress));
139 | }
140 | }
141 | });
142 |
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/buttonmenu/CustomButtonMenuVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui.buttonmenu;
18 |
19 | import com.tuenti.buttonmenu.sample.R;
20 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
21 | import com.tuenti.buttonmenu.viewmodel.button.SimpleButtonVM;
22 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.SimpleButtonMenuVM;
23 |
24 | /**
25 | * ButtonMenu implementation used in the sample project. This class has been created to encapsulate the
26 | * implementation of this ButtonMenu and to group the initialization if ButtonVM implementations out of activities
27 | * and fragments.
28 | */
29 | public class CustomButtonMenuVM extends SimpleButtonMenuVM {
30 |
31 | /*
32 | * Every ButtonVM implementation could be moved to a different file extending SimpleButtonVM if needed.
33 | */
34 | private final ButtonVM moment = new SimpleButtonVM(R.layout.moment_button, R.id.moment, null);
35 | private final ButtonVM photo = new SimpleButtonVM(R.layout.photo_button, R.id.photo, null);
36 | private final ButtonVM contact = new SimpleButtonVM(R.layout.contact_button, R.id.contact, null);
37 |
38 | public CustomButtonMenuVM() {
39 | super();
40 | addItem(moment);
41 | addItem(photo);
42 | addItem(contact);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/buttonmenu/SecondButtonMenuVM.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui.buttonmenu;
18 |
19 | import android.content.Context;
20 |
21 | import com.tuenti.buttonmenu.viewmodel.button.ButtonVM;
22 | import com.tuenti.buttonmenu.viewmodel.button.ButtonWithMutableSubjectAndResourceVM;
23 | import com.tuenti.buttonmenu.viewmodel.button.ButtonWithProgressVM;
24 | import com.tuenti.buttonmenu.viewmodel.buttonmenu.SimpleButtonMenuVM;
25 | import com.tuenti.buttonmenu.viewmodel.button.SimpleButtonVM;
26 | import com.tuenti.buttonmenu.sample.R;
27 | import com.tuenti.buttonmenu.sample.ui.buttonmenu.command.ShowToastCommand;
28 |
29 | /**
30 | * ButtonMenu implementation used in the sample project. This class has been created to encapsulate the
31 | * implementation of this ButtonMenu and to group the initialization out of activities of fragments.
32 | */
33 | public class SecondButtonMenuVM extends SimpleButtonMenuVM {
34 |
35 | private final Context context;
36 |
37 | /*
38 | * Every ButtonVM implementation could be moved to a different file extending SimpleButtonVM
39 | */
40 | private final ButtonVM moment;
41 | private final ButtonWithMutableSubjectAndResourceVM photo;
42 | private final ButtonWithProgressVM loading;
43 |
44 | public SecondButtonMenuVM(Context context) {
45 | super();
46 | this.context = context;
47 | moment = new SimpleButtonVM(R.layout.moment_button, true, R.id.moment, new int[]{R.id.moment},
48 | new ShowToastCommand(context, "Moment button clicked"));
49 |
50 | photo = new ButtonWithMutableSubjectAndResourceVM(R.layout.photo_with_subtitle_button, true, R.id.photo,
51 | new int[]{R.id.photo}, new ShowToastCommand(context, "Photo button clicked"), R.id.photo,
52 | R.id.photo);
53 |
54 | loading = new ButtonWithProgressVM(R.layout.progress_button, true,
55 | R.id.refresh, new int[] { R.id.refresh, R.id.progress },
56 | new ShowToastCommand(context,"Progress button clicked"), R.id.refresh,
57 | R.id.progress);
58 |
59 | addItem(moment);
60 | addItem(photo);
61 | addItem(loading);
62 | }
63 |
64 | public boolean isMomentButtonInMenu() {
65 | return getButtonVMs().contains(moment);
66 | }
67 |
68 | public void addMomentButton() {
69 | addItem(moment);
70 | }
71 |
72 | public void removeMomentButton() {
73 | removeItem(moment);
74 | }
75 |
76 | public boolean isPhotoButtonEnabled() {
77 | return photo.isEnabled();
78 | }
79 |
80 | public void enablePhotoButton() {
81 | photo.enable();
82 | }
83 |
84 | public void disablePhotoButton() {
85 | photo.disable();
86 | }
87 |
88 | public void changePhotoIcon() {
89 | if (photo.getImageResourceId() == R.drawable.photo_icon) {
90 | photo.setImageResourceId(R.drawable.contact_icon);
91 | } else {
92 | photo.setImageResourceId(R.drawable.photo_icon);
93 | }
94 | }
95 |
96 | public void changePhotoIconSubtitle() {
97 | String takePictureSubtitle = context.getString(R.string.photo_button_subtitle);
98 | if (takePictureSubtitle.equals(photo.getSubject())) {
99 | photo.setSubject(context.getString(R.string.photo_button_second_subtitle));
100 | } else {
101 | photo.setSubject(takePictureSubtitle);
102 | }
103 | }
104 |
105 | public void showLoading() {
106 | loading.showLoading();
107 | }
108 |
109 | public void closeLoading() {
110 | loading.closeLoading();
111 | }
112 |
113 | public boolean isLoading(){
114 | return loading.isLoading();
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/buttonmenu/command/ShowToastCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui.buttonmenu.command;
18 |
19 | import android.content.Context;
20 | import android.widget.Toast;
21 |
22 | import com.tuenti.buttonmenu.viewmodel.button.ButtonCommand;
23 |
24 | /**
25 | * ButtonCommand implementation created to show a toast with a message.
26 | */
27 | public class ShowToastCommand implements ButtonCommand {
28 |
29 | private final Context context;
30 | private final String text;
31 |
32 | public ShowToastCommand(Context context, String text) {
33 | this.context = context;
34 | this.text = text;
35 | }
36 |
37 | @Override
38 | public void execute() {
39 | Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/renderer/ContactRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 |
18 | package com.tuenti.buttonmenu.sample.ui.renderer;
19 |
20 | import android.content.Context;
21 | import android.view.LayoutInflater;
22 | import android.view.View;
23 | import android.view.ViewGroup;
24 | import android.widget.ImageView;
25 | import android.widget.TextView;
26 |
27 | import com.pedrogomez.renderers.Renderer;
28 | import com.squareup.picasso.Picasso;
29 | import com.tuenti.buttonmenu.sample.R;
30 | import com.tuenti.buttonmenu.sample.ui.Contact;
31 |
32 | /**
33 | * ContactRenderer implementation created to show a Contact information inside a ListView row.
34 | *
35 | * If you want to lear more about how to use Renderers take a look to this project:
36 | * https://github.com/pedrovgs/Renderers
37 | *
38 | * @author Pedro Vicente Gómez Sánchez
39 | */
40 |
41 | public class ContactRenderer extends Renderer {
42 |
43 | private final Context context;
44 |
45 | private TextView tv_name;
46 | private TextView tv_date;
47 | private TextView tv_last_message;
48 | private ImageView iv_avatar;
49 |
50 | public ContactRenderer(Context context) {
51 | this.context = context;
52 | }
53 |
54 | @Override
55 | protected View inflate(LayoutInflater inflater, ViewGroup parent) {
56 | return inflater.inflate(R.layout.contact_row, parent, false);
57 | }
58 |
59 | @Override
60 | protected void setUpView(View rootView) {
61 | tv_name = (TextView) rootView.findViewById(R.id.tv_name);
62 | tv_date = (TextView) rootView.findViewById(R.id.tv_date);
63 | tv_last_message = (TextView) rootView.findViewById(R.id.tv_last_message);
64 | iv_avatar = (ImageView) rootView.findViewById(R.id.iv_avatar);
65 | }
66 |
67 | @Override
68 | protected void hookListeners(View rootView) {
69 | //Empty
70 | }
71 |
72 | @Override
73 | public void render() {
74 | Contact contact = getContent();
75 | Picasso.with(context).load(contact.getAvatar()).into(iv_avatar);
76 | tv_name.setText(contact.getName());
77 | tv_date.setText(contact.getLastDate());
78 | tv_last_message.setText(contact.getLastMessage());
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/sample/src/main/java/com/tuenti/buttonmenu/sample/ui/renderer/ContactRendererBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Tuenti Technologies S.L. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.tuenti.buttonmenu.sample.ui.renderer;
18 |
19 | import java.util.Collection;
20 |
21 | import com.pedrogomez.renderers.Renderer;
22 | import com.pedrogomez.renderers.RendererBuilder;
23 | import com.tuenti.buttonmenu.sample.ui.Contact;
24 |
25 | /**
26 | * RendererBuilder implementation created to map Contacts to Renderer implementations.
27 | *
28 | * *
29 | * If you want to lear more about how to use Renderers take a look to this project:
30 | * https://github.com/pedrovgs/Renderers
31 | *
32 | * @author Pedro Vicente Gómez Sánchez
33 | */
34 | public class ContactRendererBuilder extends RendererBuilder {
35 |
36 | public ContactRendererBuilder(Collection> prototypes) {
37 | super(prototypes);
38 | }
39 |
40 | @Override
41 | protected Class getPrototypeClass(Contact content) {
42 | return ContactRenderer.class;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------