├── .gitignore
├── FilterViewSipmle
├── .gitignore
├── .idea
│ ├── checkstyle-idea.xml
│ ├── compiler.xml
│ ├── copyright
│ │ └── profiles_settings.xml
│ ├── gradle.xml
│ ├── misc.xml
│ ├── modules.xml
│ └── runConfigurations.xml
├── app
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── androidTest
│ │ └── java
│ │ │ └── widget
│ │ │ └── tamic
│ │ │ └── com
│ │ │ └── filterviewsipmle
│ │ │ └── ExampleInstrumentedTest.java
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ │ └── testcaselist.json
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── tamic
│ │ │ │ └── widget
│ │ │ │ ├── filter
│ │ │ │ ├── BaseBean.java
│ │ │ │ ├── BaseFilterItem.java
│ │ │ │ ├── CategoryBar.java
│ │ │ │ ├── CategoryButton.java
│ │ │ │ ├── CategoryCheckable.java
│ │ │ │ ├── ConditionContainer.java
│ │ │ │ ├── DataSelectContainer.java
│ │ │ │ ├── DateSelectConditionItem.java
│ │ │ │ ├── DateView.java
│ │ │ │ ├── FilterBean.java
│ │ │ │ ├── FilterContainer.java
│ │ │ │ ├── FilterMode.java
│ │ │ │ ├── FliterResultItem.java
│ │ │ │ ├── GridContainer.java
│ │ │ │ ├── GroupFilterItem.java
│ │ │ │ ├── ListFilterBean.java
│ │ │ │ ├── NewConditionItem.java
│ │ │ │ ├── RangeConditionItem.java
│ │ │ │ ├── RangeContainer.java
│ │ │ │ ├── RangeSeekBar.java
│ │ │ │ ├── RegionContainer.java
│ │ │ │ ├── SorterContainer.java
│ │ │ │ └── UIUtil.java
│ │ │ │ └── filterviewsipmle
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── Test.java
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── less.png
│ │ │ ├── more_unfold.png
│ │ │ ├── range_seek_bar_thumb.png
│ │ │ ├── selector_item_condition_background.xml
│ │ │ ├── selector_item_condition_grid_background.xml
│ │ │ ├── selector_item_condition_grid_text_color.xml
│ │ │ ├── selector_item_condition_text2_color.xml
│ │ │ ├── selector_item_condition_text_color.xml
│ │ │ ├── shape_btn_standard_3b4263_rectangle.xml
│ │ │ └── shape_list_divider.xml
│ │ │ ├── layout
│ │ │ ├── activity_main.xml
│ │ │ ├── content_main.xml
│ │ │ ├── item_condition_1.xml
│ │ │ ├── item_condition_2.xml
│ │ │ ├── item_condition_3.xml
│ │ │ ├── item_condition_grid.xml
│ │ │ ├── layout_category_bar_mode_brand_list.xml
│ │ │ ├── layout_category_button.xml
│ │ │ ├── layout_category_button_new.xml
│ │ │ ├── layout_condition_data_select.xml
│ │ │ ├── layout_condition_divider.xml
│ │ │ ├── layout_condition_filter.xml
│ │ │ ├── layout_condition_grid.xml
│ │ │ ├── layout_condition_range.xml
│ │ │ ├── layout_condition_region.xml
│ │ │ └── layout_condition_sorter.xml
│ │ │ ├── menu
│ │ │ └── menu_main.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-v21
│ │ │ └── styles.xml
│ │ │ ├── values-w820dp
│ │ │ └── dimens.xml
│ │ │ └── values
│ │ │ ├── attrs-rangeseekbar.xml
│ │ │ ├── attrs.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ │ └── test
│ │ └── java
│ │ └── widget
│ │ └── tamic
│ │ └── com
│ │ └── filterviewsipmle
│ │ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | *.jks
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
56 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/checkstyle-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 1.8
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/FilterViewSipmle/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 | defaultConfig {
7 | applicationId "com.tamic.widget"
8 | minSdkVersion 17
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 |
21 | lintOptions {
22 | abortOnError false
23 | checkReleaseBuilds false
24 | }
25 | }
26 |
27 | dependencies {
28 | compile fileTree(dir: 'libs', include: ['*.jar'])
29 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
30 | exclude group: 'com.android.support', module: 'support-annotations'
31 | })
32 | compile 'com.google.code.gson:gson:2.8.1'
33 | compile 'com.android.support:appcompat-v7:25.3.1'
34 | compile 'com.android.support:design:25.3.1'
35 | testCompile 'junit:junit:4.12'
36 | compile 'com.alibaba:fastjson:1.1.60.android'
37 |
38 | //compile 'com.google.android.gms:play-services-appindexing:8.4.0'
39 | }
40 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Users\liuyongkui726\AppData\Local\Android\android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/androidTest/java/widget/tamic/com/filterviewsipmle/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package widget.tamic.com.filterviewsipmle;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("widget.tamic.com.filterviewsipmle", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/assets/testcaselist.json:
--------------------------------------------------------------------------------
1 | [[{"keyName":"支付条件","value":"hjjjj"},{"keyName":"金额","value":"8666"}],[{"keyName":"支付条件","value":"hjjjj"},{"keyName":"金额","value":"8666"}]]
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/BaseBean.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 |
4 | /**
5 | * Created by tamic on 2017-08-03.
6 | */
7 | public abstract class BaseBean {
8 | }
9 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/BaseFilterItem.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | /**
7 | * Created by tamic on 2017-08-03.
8 | *
9 | * @link {https://github.com/Tamicer/FilterBar}
10 | */
11 | public class BaseFilterItem extends BaseBean implements Parcelable {
12 |
13 | private int id;
14 | private String name;
15 | private int code;
16 | private String value;
17 |
18 | public BaseFilterItem() {
19 | }
20 |
21 | protected BaseFilterItem(Parcel in) {
22 | id = in.readInt();
23 | name = in.readString();
24 | code = in.readInt();
25 | value = in.readString();
26 | }
27 |
28 | @Override
29 | public void writeToParcel(Parcel dest, int flags) {
30 | dest.writeInt(id);
31 | dest.writeString(name);
32 | dest.writeInt(code);
33 | dest.writeString(value);
34 | }
35 |
36 | @Override
37 | public int describeContents() {
38 | return 0;
39 | }
40 |
41 | public static final Creator CREATOR = new Creator() {
42 |
43 | @Override
44 | public BaseFilterItem createFromParcel(Parcel in) {
45 | return new BaseFilterItem(in);
46 | }
47 |
48 | @Override
49 | public BaseFilterItem[] newArray(int size) {
50 | return new BaseFilterItem[size];
51 | }
52 | };
53 |
54 | public int getId() {
55 | return id;
56 | }
57 |
58 | public void setId(int id) {
59 | this.id = id;
60 | }
61 |
62 | public String getName() {
63 | return name;
64 | }
65 |
66 | public void setName(String name) {
67 | this.name = name;
68 | }
69 |
70 | public int getCode() {
71 | return code;
72 | }
73 |
74 | public void setCode(int code) {
75 | this.code = code;
76 | }
77 |
78 | public String getValue() {
79 | return value;
80 | }
81 |
82 | public void setValue(String value) {
83 | this.value = value;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/CategoryBar.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.graphics.drawable.ColorDrawable;
5 | import android.util.AttributeSet;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.FrameLayout;
10 | import android.widget.PopupWindow;
11 |
12 |
13 | import java.util.HashMap;
14 |
15 | import widget.tamic.com.filterviewsipmle.R;
16 |
17 |
18 | /**
19 | * Created by tamic on 2017-08-03.
20 | *
21 | * @link {https://github.com/Tamicer/FilterBar}
22 | */
23 | public class CategoryBar extends FrameLayout implements ConditionContainer.Controller, ConditionContainer.FiterModeCallback {
24 |
25 | static final int MODE_LIST = 0;
26 | static final int MODE_MAP = 1;
27 | static final int MODE_BRAND_LIST = 2;
28 | static final int MODE_ED = 2;
29 |
30 | public static final String FILTER_ROOT = "filterRoot";
31 | public static final String REGION_ROOT = "regionRoot";
32 | public static final String SORTER_ROOT = "sorterRoot";
33 |
34 |
35 | private FilterMode filterMode;
36 | private FiterModeCallback mCallback;
37 | private int mMode = MODE_LIST;
38 | CategoryButton mRegion;
39 | CategoryButton mFilter;
40 | CategoryButton mSorter;
41 | PopupWindow mPopup;
42 |
43 | boolean isShowRegion = true;
44 | boolean isShowFilter = true;
45 | boolean isShowSorter = true;
46 |
47 | @Override
48 | public boolean isShown() {
49 | return super.isShown();
50 | }
51 |
52 | HashMap mBtnMap = new HashMap<>();
53 |
54 | private ControllerListener mControllerListener;
55 |
56 | public CategoryBar(Context context) {
57 | super(context);
58 | init();
59 | }
60 |
61 | public CategoryBar(Context context, FiterModeCallback callback) {
62 | super(context);
63 | mCallback = callback;
64 | init();
65 | }
66 |
67 | public CategoryBar(Context context, AttributeSet attrs) {
68 | super(context, attrs);
69 | init();
70 | }
71 |
72 | private void init() {
73 |
74 | LayoutInflater.from(getContext()).inflate(R.layout.layout_category_bar_mode_brand_list, this);
75 | mRegion = (CategoryButton) findViewById(R.id.btn_region_category_bar);
76 |
77 | if (mRegion != null) {
78 | mRegion.setText("区域");
79 | mRegion.setOnCheckedChangedListener(mButtonOnChecked);
80 | mRegionContainer = new RegionContainer(getContext(), geFiterMode());
81 | mRegionContainer.setController(this);
82 | mRegionContainer.setModeCallback(this);
83 | mBtnMap.put(mRegion, mRegionContainer);
84 | }
85 |
86 | mFilter = (CategoryButton) findViewById(R.id.btn_filter_category_bar);
87 |
88 | if (mFilter != null) {
89 | mFilter.setText("筛选");
90 | mFilter.setOnCheckedChangedListener(mButtonOnChecked);
91 | mFilterContainer = new FilterContainer(getContext());
92 | mFilterContainer.setController(this);
93 | mBtnMap.put(mFilter, mFilterContainer);
94 | }
95 |
96 | mSorter = (CategoryButton) findViewById(R.id.btn_sorter_category_bar);
97 |
98 | if (mSorter != null) {
99 | mSorter.setText("排序");
100 | mSorter.setOnCheckedChangedListener(mButtonOnChecked);
101 | mSorterContainer = new SorterContainer(getContext());
102 | mSorterContainer.setController(this);
103 | mBtnMap.put(mSorter, mSorterContainer);
104 | }
105 | if (!isShowSorter) {
106 | mSorter.setVisibility(GONE);
107 | }
108 |
109 | mPopup = new PopupWindow();
110 | }
111 |
112 | public CategoryBar setRegionShow(boolean isShow) {
113 |
114 | if (isShow) {
115 | mRegion.setVisibility(VISIBLE);
116 | } else {
117 | mRegion.setVisibility(GONE);
118 | }
119 | return this;
120 | }
121 |
122 | public CategoryBar setFilterShow(boolean isShow) {
123 |
124 | if (isShow) {
125 | mFilter.setVisibility(VISIBLE);
126 | } else {
127 | mFilter.setVisibility(GONE);
128 | }
129 | return this;
130 | }
131 |
132 | public CategoryBar setSorterShow(boolean isShow) {
133 |
134 | if (isShow) {
135 | mSorter.setVisibility(VISIBLE);
136 | } else {
137 | mSorter.setVisibility(GONE);
138 | }
139 | return this;
140 | }
141 |
142 | public CategoryBar setFristTabText(String text) {
143 | if (mRegion != null) {
144 | mRegion.setText(text);
145 | }
146 | return this;
147 | }
148 |
149 | public CategoryBar setSecondTabText(String text) {
150 | if (mFilter != null) {
151 | mFilter.setText(text);
152 | }
153 | return this;
154 | }
155 |
156 | public CategoryBar setThreeTabText(String text) {
157 | if (mSorter != null) {
158 | mSorter.setText(text);
159 | }
160 | return this;
161 | }
162 |
163 | public void setFilterCallback(FiterModeCallback callback) {
164 | mCallback = callback;
165 | }
166 |
167 | private void cancelBtn(CategoryCheckable btn) {
168 | if (btn != null && btn.isChecked()) {
169 | btn.setChecked(false);
170 | }
171 | }
172 |
173 | final private CategoryCheckable.OnCheckedChangeListener mButtonOnChecked =
174 | new CategoryCheckable.OnCheckedChangeListener() {
175 |
176 | @Override
177 | public void onCheckedChanged(CategoryCheckable button, boolean isChecked) {
178 | if (isChecked) {
179 | CategoryCheckable[] checkables = new CategoryCheckable[] {
180 | mRegion, mFilter, mSorter
181 | };
182 | for (CategoryCheckable checkable : checkables) {
183 | if (checkable != button) {
184 | cancelBtn(checkable);
185 | }
186 | }
187 | }
188 | ConditionContainer container = mBtnMap.get(button);
189 | if (container == null) {
190 | return;
191 | }
192 | if (isChecked) {
193 | if (mControllerListener != null) {
194 | mControllerListener.onOpen(container);
195 | }
196 | mActive = button;
197 | int[] location = new int[2];
198 | getLocationInWindow(location);
199 | int winWidth = UIUtil.getWindowWidth(getContext());
200 | int winHeight = UIUtil.getWindowHeight(getContext());
201 |
202 |
203 | View empty = new View(getContext());
204 | ViewGroup.LayoutParams lp = new LayoutParams(
205 | ViewGroup.LayoutParams.MATCH_PARENT,
206 | ViewGroup.LayoutParams.MATCH_PARENT);
207 | empty.setLayoutParams(lp);
208 |
209 | mPopup.setWidth(winWidth);
210 | mPopup.setHeight(winHeight - getHeight() - location[1]);
211 | mPopup.setContentView(container);
212 | mPopup.setBackgroundDrawable(new ColorDrawable(0xcc000000));
213 | mPopup.showAsDropDown(CategoryBar.this);
214 | } else {
215 | mPopup.dismiss();
216 | mActive = null;
217 | if (mControllerListener != null) {
218 | mControllerListener.onCancel(container);
219 | }
220 | }
221 | }
222 | };
223 |
224 | private CategoryCheckable mActive;
225 | private ConditionContainer mRegionContainer;
226 | private ConditionContainer mFilterContainer;
227 | private ConditionContainer mSorterContainer;
228 | private ConditionContainer mDNAContainer;
229 |
230 | public static int getModeList() {
231 | return MODE_LIST;
232 | }
233 |
234 | public ConditionContainer getRegionContainer() {
235 | return mRegionContainer;
236 | }
237 |
238 | public void addFristContainer(ConditionContainer container) {
239 | this.mRegionContainer = container;
240 | mRegionContainer.setController(this);
241 | mRegionContainer.setModeCallback(this);
242 | mBtnMap.put(mRegion, mRegionContainer);
243 | }
244 |
245 | public ConditionContainer getFilterContainer() {
246 | return mFilterContainer;
247 | }
248 |
249 | public void addSecondContainer(ConditionContainer container) {
250 | this.mFilterContainer = container;
251 | mFilterContainer.setController(this);
252 | mFilterContainer.setModeCallback(this);
253 | mBtnMap.put(mFilter, mFilterContainer);
254 | }
255 |
256 | public void addThreeContainer(ConditionContainer container) {
257 | this.mSorterContainer = container;
258 | mSorterContainer.setController(this);
259 | mSorterContainer.setModeCallback(this);
260 | mBtnMap.put(mSorter, mSorterContainer);
261 | }
262 |
263 | public ConditionContainer getSorterContainer() {
264 | return mSorterContainer;
265 | }
266 |
267 | public ConditionContainer getDNAContainer() {
268 | return mDNAContainer;
269 | }
270 |
271 | public void setDNAContainer(ConditionContainer mDNAContainer) {
272 | this.mDNAContainer = mDNAContainer;
273 | }
274 |
275 | private void setHandle(ConditionContainer container) {
276 | container.setController(this);
277 | container.setModeCallback(this);
278 | }
279 |
280 | @Override
281 | public void confirm(ConditionContainer container) {
282 | if (mControllerListener != null) {
283 | mControllerListener.onConfirm(container);
284 | }
285 | if (mActive != null) {
286 | mActive.setChecked(false);
287 | }
288 | }
289 |
290 | @Override
291 | public void cancel(ConditionContainer container) {
292 | if (mActive != null) {
293 | mActive.setChecked(false);
294 | }
295 | }
296 |
297 | @Override
298 | public void onItemClick(ConditionContainer container, int id) {
299 |
300 | if (mControllerListener != null) {
301 | mControllerListener.onSpecial(container, id);
302 | }
303 | }
304 |
305 | public void setMode(FilterMode mode) {
306 | filterMode = mode;
307 | }
308 |
309 | public void setOnConfirmListener(ControllerListener listener) {
310 | mControllerListener = listener;
311 | }
312 |
313 | @Override
314 | public FilterMode geFiterMode() {
315 | if (mCallback == null) {
316 | return FilterMode.ENTER;
317 | }
318 | return mCallback.setFiterMode();
319 | }
320 |
321 | public interface ControllerListener {
322 |
323 | void onConfirm(ConditionContainer container);
324 |
325 | void onOpen(ConditionContainer container);
326 |
327 | void onCancel(ConditionContainer container);
328 |
329 | void onSpecial(ConditionContainer container, int id);
330 | }
331 |
332 | public interface FiterModeCallback {
333 |
334 | FilterMode setFiterMode();
335 | }
336 |
337 | @Override
338 | public void setVisibility(int visibility) {
339 | super.setVisibility(visibility);
340 | if (visibility != VISIBLE) { //需要关闭popup
341 | mPopup.dismiss();
342 | }
343 | }
344 | }
345 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/CategoryButton.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.Gravity;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.widget.FrameLayout;
9 | import android.widget.TextView;
10 |
11 | import widget.tamic.com.filterviewsipmle.R;
12 |
13 |
14 | /**
15 | * Created by Tamic on 2016-08-24.
16 | */
17 | public class CategoryButton extends FrameLayout implements CategoryCheckable {
18 |
19 | public CategoryButton(Context context) {
20 | super(context);
21 | init();
22 | }
23 |
24 | public CategoryButton(Context context, AttributeSet attrs) {
25 | super(context, attrs);
26 | init();
27 | }
28 |
29 | static private final int COLOR_TEXT_CHECK = 0xff6281c2;
30 | static private final int COLOR_TEXT_UNCHECK = 0xff555555;
31 | static private final int COLOR_ICON_CHECK = 0xff6281c2;
32 | static private final int COLOR_ICON_UNCHECK = 0xff555555;
33 | static private final int TEXT_SIZE = 14; //sp
34 |
35 | private View mContent;
36 | private TextView mTvText;
37 | private TextView mTvIcon;
38 | private boolean mChecked = false;
39 | private String mText;
40 | private OnCheckedChangeListener mOnCheckedChangedListener;
41 | private OnClickListener mOnClickListener = new OnClickListener() {
42 |
43 | @Override
44 | public void onClick(View v) {
45 | setChecked(!mChecked);
46 |
47 | }
48 | };
49 |
50 | private void init() {
51 | LayoutInflater.from(getContext()).inflate(R.layout.layout_category_button, this);
52 | mContent = findViewById(R.id.content_layout_category_button);
53 | mTvText = (TextView) findViewById(R.id.tv_text_layout_category_button);
54 | mTvIcon = (TextView) findViewById(R.id.tv_icon_layout_category_button);
55 | mTvText.setTextSize(TEXT_SIZE);
56 | mTvIcon.setTextSize(TEXT_SIZE);
57 | mContent.setOnClickListener(mOnClickListener);
58 | update();
59 |
60 | }
61 |
62 | public void setChecked(boolean checked) {
63 | if (mChecked != checked) {
64 | mChecked = checked;
65 | update();
66 | if (mOnCheckedChangedListener != null) {
67 | mOnCheckedChangedListener.onCheckedChanged(this, mChecked);
68 | }
69 | }
70 | }
71 |
72 | public boolean isChecked() {
73 | return mChecked;
74 | }
75 |
76 | public void setText(String text) {
77 | mText = text;
78 | mTvText.setText(mText);
79 | }
80 |
81 | public String getText() {
82 | return mTvText.getText().toString();
83 | }
84 |
85 | public void setOnCheckedChangedListener(OnCheckedChangeListener listener) {
86 | mOnCheckedChangedListener = listener;
87 | }
88 |
89 | private void update() {
90 | if (mChecked) {
91 | mTvText.setTextColor(COLOR_TEXT_CHECK);
92 | mTvIcon.setTextColor(COLOR_ICON_CHECK);
93 | mTvIcon.setBackground(getContext().getResources().getDrawable(R.drawable.more_unfold));
94 | } else {
95 | mTvText.setTextColor(COLOR_TEXT_UNCHECK);
96 | mTvIcon.setTextColor(COLOR_ICON_UNCHECK);
97 | mTvIcon.setBackground(getContext().getResources().getDrawable(R.drawable.less));
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/CategoryCheckable.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | /**
4 | * Created by tamic on 2016-08-26.
5 | *
6 | * @link {https://github.com/Tamicer/FilterBar}
7 | */
8 | public interface CategoryCheckable {
9 |
10 | interface OnCheckedChangeListener {
11 |
12 | void onCheckedChanged(CategoryCheckable button, boolean isChecked);
13 | }
14 |
15 | void setChecked(boolean checked);
16 |
17 | boolean isChecked();
18 |
19 | void setText(String text);
20 |
21 | void setOnCheckedChangedListener(OnCheckedChangeListener listener);
22 | }
23 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/ConditionContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 | import android.widget.FrameLayout;
7 |
8 | import java.util.List;
9 |
10 |
11 | /**
12 | * update by Tamic on 2017-07-26.
13 | * ----------------------
14 | */
15 | public abstract class ConditionContainer extends FrameLayout {
16 |
17 | public interface Controller {
18 |
19 | void confirm(ConditionContainer container);
20 |
21 | void cancel(ConditionContainer container);
22 |
23 | void onItemClick(ConditionContainer container, int id);
24 | }
25 |
26 | public ConditionContainer(Context context) {
27 | super(context);
28 | }
29 |
30 | public ConditionContainer(Context context, AttributeSet attrs) {
31 | super(context, attrs);
32 | }
33 |
34 | abstract public NewConditionItem getConditionItem();
35 |
36 | abstract public void setConditionItem(NewConditionItem item);
37 |
38 | abstract public NewConditionItem create(List itemList);
39 |
40 | abstract public void addContentView(View view);
41 |
42 | protected Controller mController;
43 | protected FiterModeCallback mCallback;
44 |
45 | public void setController(Controller controller) {
46 | mController = controller;
47 | }
48 |
49 | public void setModeCallback(FiterModeCallback controller) {
50 | mCallback = controller;
51 | }
52 |
53 | public void onItemClick(ConditionContainer container) {
54 |
55 | }
56 |
57 | public interface FiterModeCallback {
58 |
59 | FilterMode geFiterMode();
60 | }
61 |
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/DataSelectContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.LayoutRes;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.CompoundButton;
8 | import android.widget.TextView;
9 | import android.widget.Toast;
10 |
11 |
12 | import java.util.List;
13 |
14 | import widget.tamic.com.filterviewsipmle.R;
15 |
16 | /**
17 | * Created by Tamic on 2017-07-28
18 | */
19 | public class DataSelectContainer extends ConditionContainer {
20 |
21 | public DataSelectContainer(Context context) {
22 | super(context);
23 | init();
24 | }
25 |
26 | private TextView mTvTitle;
27 | private CompoundButton mTvDateStart;
28 | private CompoundButton mTvDateEnd;
29 | private int mLastStart;
30 | private int mLastEnd;
31 | private static final String DATA_FORMAT = "yyyy/MM/dd";
32 |
33 | private void init() {
34 | setContentView(R.layout.layout_condition_data_select);
35 | mTvTitle = (TextView) findViewById(R.id.tv_info_condition_tilte);
36 | mTvDateStart = (CompoundButton) findViewById(R.id.tv_title_condition_data_start);
37 | mTvDateEnd = (CompoundButton) findViewById(R.id.tv_info_condition_data_end);
38 |
39 |
40 | mTvDateEnd.setOnClickListener(new OnClickListener() {
41 |
42 | @Override
43 | public void onClick(View v) {
44 | mTvDateStart.setText("6546465465");
45 | mItem.end = 43434343;
46 | Toast.makeText(getContext(), "DateEnd", Toast.LENGTH_SHORT).show();
47 | ((GridContainer) getParent().getParent().getParent()).reSet();
48 | }
49 | });
50 | mTvDateStart.setOnClickListener(new OnClickListener() {
51 |
52 | @Override
53 | public void onClick(View v) {
54 | Toast.makeText(getContext(), "DateStart", Toast.LENGTH_SHORT).show();
55 | mTvDateEnd.setText("454545");
56 | mItem.start = 787834;
57 | ((GridContainer) getParent().getParent().getParent()).reSet();
58 | }
59 | });
60 |
61 |
62 | }
63 |
64 | public View setContentView(@LayoutRes int id) {
65 | return LayoutInflater.from(getContext()).inflate(id, this);
66 | }
67 |
68 | public void reSet() {
69 | mTvDateStart.setText("开始时间");
70 | mTvDateEnd.setText("结束时间");
71 | }
72 |
73 | private DateSelectConditionItem mItem;
74 |
75 | @Override
76 | public NewConditionItem getConditionItem() {
77 | return mItem;
78 | }
79 |
80 | @Override
81 | public void setConditionItem(NewConditionItem item) {
82 | mItem = (DateSelectConditionItem) item;
83 | mTvTitle.setText(mItem.name);
84 | mLastStart = mItem.start;
85 | mLastEnd = mItem.end;
86 | if (mLastStart == 0 && mLastEnd == 0) {
87 | reSet();
88 | return;
89 | }
90 | if (mLastStart == 0) {
91 | mTvDateStart.setText("开始时间");
92 | } else {
93 | mTvDateStart.setText("" + mLastStart);
94 | }
95 | if (mLastEnd == 0) {
96 | mTvDateEnd.setText("结束时间");
97 | } else {
98 | mTvDateEnd.setText("" + mLastEnd);
99 | }
100 | }
101 |
102 | @Override
103 | public NewConditionItem create(List itemList) {
104 | //todo create you ConditionItem, Usually not youself implement it!
105 | return null;
106 | }
107 |
108 | @Override
109 | public void addContentView(View view) {
110 | //todo add you childView to rootView , Usually not youself layout the View!
111 | addView(view);
112 | }
113 |
114 | static private int adjust(int base, int step, int value) {
115 | int steps = (value - base) / step;
116 | float r = (float) ((value - base) % step) / (float) step;
117 | return base + steps * step + Math.round(r) * step;
118 | }
119 |
120 | }
121 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/DateSelectConditionItem.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | /**
4 | * Created by Tamic on 2017-07-28.
5 | */
6 | public class DateSelectConditionItem extends NewConditionItem {
7 |
8 | public interface DateRangeInfo {
9 |
10 | String getInfo(DateSelectConditionItem item);
11 | }
12 |
13 | static public final DateRangeInfo DATE_INFO = new DateRangeInfo() {
14 |
15 | @Override
16 | public String getInfo(DateSelectConditionItem item) {
17 | if (item.start == 0 || item.end == 0) {
18 | return " ";
19 | }
20 | return item.start + ":" + item.end;
21 | }
22 | };
23 |
24 | public int start, end;
25 | public int from, to;
26 | public boolean isRefresh = true;
27 | public DateRangeInfo rangeInfo = DATE_INFO;
28 |
29 |
30 | public DateSelectConditionItem(int type) {
31 | super(type);
32 | }
33 |
34 | public DateSelectConditionItem(NewConditionItem parent, int id, String name,
35 | int start, int end) {
36 | super(parent, id, name, true, TYPE_DATA);
37 | this.start = start;
38 | this.end = end;
39 | /* if (this.parent != null) {
40 | this.parent.subItems.add(this);
41 | }*/
42 | }
43 |
44 |
45 | public NewConditionItem createConditionItem(int type) {
46 | return new DateSelectConditionItem(type);
47 | }
48 |
49 | @Override
50 | public void clear() {
51 | super.clear();
52 | if (isRefresh) {
53 | start = 0;
54 | end = 0;
55 | }
56 | isRefresh = false;
57 |
58 | }
59 |
60 | @Override
61 | public void reset() {
62 | super.reset();
63 | from = -1;
64 | to = -1;
65 | }
66 |
67 | public String getInfo() {
68 | if (rangeInfo == null) {
69 | return "";
70 | } else {
71 | return rangeInfo.getInfo(this);
72 | }
73 | }
74 |
75 | @Override
76 | public NewConditionItem clone() {
77 | DateSelectConditionItem cloned = new DateSelectConditionItem(type);
78 | cloned.id = this.id;
79 | cloned.name = this.name;
80 | cloned.selected = this.selected;
81 | cloned.canReset = this.canReset;
82 | cloned.type = this.type;
83 | cloned.start = this.start;
84 | cloned.end = this.end;
85 | cloned.processor = this.processor;
86 | cloned.isRefresh = this.isRefresh;
87 | for (NewConditionItem subItem : this.subItems) {
88 | NewConditionItem clonedSubItem = subItem.clone();
89 | clonedSubItem.parent = cloned;
90 | cloned.subItems.add(clonedSubItem);
91 | }
92 | cloned.start = this.start;
93 | cloned.end = this.end;
94 | cloned.from = this.from;
95 | cloned.to = this.to;
96 | cloned.rangeInfo = this.rangeInfo;
97 | return cloned;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/DateView.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.support.annotation.RequiresApi;
6 | import android.util.AttributeSet;
7 | import android.view.LayoutInflater;
8 | import android.widget.CompoundButton;
9 |
10 | import widget.tamic.com.filterviewsipmle.R;
11 |
12 | /**
13 | * Created by Tamic on 2017-08-02.
14 | */
15 |
16 | public class DateView extends CompoundButton {
17 |
18 | public DateView(Context context) {
19 | super(context);
20 | init();
21 | }
22 |
23 |
24 | public DateView(Context context, AttributeSet attrs) {
25 | super(context, attrs);
26 | init();
27 | }
28 |
29 | public DateView(Context context, AttributeSet attrs, int defStyleAttr) {
30 | super(context, attrs, defStyleAttr);
31 | init();
32 | }
33 |
34 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
35 | public DateView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
36 | super(context, attrs, defStyleAttr, defStyleRes);
37 | init();
38 | }
39 |
40 | private void init() {
41 | LayoutInflater.from(getContext())
42 | .inflate(R.layout.item_condition_grid, null);
43 | }
44 |
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/FilterBean.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 |
4 | import java.util.ArrayList;
5 |
6 | /**
7 | * FilterBean
8 | */
9 | public class FilterBean {
10 |
11 | private int id;
12 | private String name;
13 | private String sName;
14 | private ArrayList list;
15 |
16 | public FilterBean() {
17 | }
18 |
19 | public int getId() {
20 | return id;
21 | }
22 |
23 | public void setId(int id) {
24 | this.id = id;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 |
31 | public void setName(String name) {
32 | this.name = name;
33 | }
34 |
35 | public String getsName() {
36 | return sName;
37 | }
38 |
39 | public void setsName(String sName) {
40 | this.sName = sName;
41 | }
42 |
43 | public ArrayList getList() {
44 | return list;
45 | }
46 |
47 | public void setList(ArrayList list) {
48 | this.list = list;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/FilterContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.LinearLayout;
9 | import android.widget.RelativeLayout;
10 | import android.widget.TextView;
11 |
12 |
13 | import java.util.List;
14 |
15 | import widget.tamic.com.filterviewsipmle.R;
16 |
17 | /**
18 | * Created by SUNTAIYI on 2016-08-24.
19 | */
20 | public class FilterContainer extends ConditionContainer implements View.OnClickListener {
21 | public FilterContainer(Context context) {
22 | super(context);
23 | init();
24 | }
25 |
26 | public FilterContainer(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | init();
29 | }
30 |
31 | private LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
32 | ViewGroup.LayoutParams.MATCH_PARENT,
33 | ViewGroup.LayoutParams.WRAP_CONTENT
34 | );
35 |
36 | private LinearLayout mList;
37 | private TextView mTvReset;
38 | private TextView mTvConfirm;
39 |
40 | private void init() {
41 | LayoutInflater.from(getContext()).inflate(R.layout.layout_condition_filter, this);
42 | mList = (LinearLayout) findViewById(R.id.list_condition_filter);
43 | mTvReset = (TextView) findViewById(R.id.tv_reset_condition);
44 | mTvConfirm = (TextView) findViewById(R.id.tv_confirm_condition);
45 | mTvReset.setOnClickListener(this);
46 | mTvConfirm.setOnClickListener(this);
47 | findViewById(R.id.blank_condition).setOnClickListener(this);
48 | }
49 |
50 | private NewConditionItem mRoot;
51 |
52 | @Override
53 | public NewConditionItem getConditionItem() {
54 | return mRoot;
55 | }
56 |
57 | @Override
58 | public void setConditionItem(NewConditionItem item) {
59 | if (mRoot != item) {
60 | mRoot = item;
61 | mList.removeAllViews();
62 | if (item == null) {
63 | return;
64 | }
65 | LayoutInflater inflater = LayoutInflater.from(getContext());
66 | for (NewConditionItem subItem : item.subItems) {
67 |
68 | if (subItem.type == NewConditionItem.TYPE_GRID) {
69 | ConditionContainer container = new GridContainer(getContext());
70 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
71 | ViewGroup.LayoutParams.MATCH_PARENT,
72 | ViewGroup.LayoutParams.WRAP_CONTENT
73 | );
74 | container.setLayoutParams(lp);
75 | container.setTag(subItem);
76 | addContentView(container);
77 | container.setConditionItem(subItem);
78 |
79 | } /*else if (subItem.type == NewConditionItem.TYPE_GRID) {
80 | ConditionContainer container = null;
81 | container = new GridContainer(getContext());
82 | // RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
83 |
84 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
85 | ViewGroup.LayoutParams.WRAP_CONTENT,
86 | ViewGroup.LayoutParams.WRAP_CONTENT
87 | );
88 | container.setLayoutParams(lp);
89 | *//* if(subItem.type != NewConditionItem.TYPE_DATA) {
90 | for (NewConditionItem subItem2 : subItem.subItems) {
91 | if(subItem2.type == NewConditionItem.TYPE_DATA) {
92 | ConditionContainer container2 = new DataSelectContainer(getContext());
93 | LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
94 | ViewGroup.LayoutParams.MATCH_PARENT,
95 | ViewGroup.LayoutParams.WRAP_CONTENT
96 | );
97 | container2.setLayoutParams(lp2);
98 | container2.setTag(subItem2);
99 | container2.setConditionItem(subItem2);
100 |
101 | if (container != null) {
102 | container.addContentView(container2);
103 | }
104 |
105 | } else {
106 | container.setTag(subItem);
107 | container.setConditionItem(subItem);
108 | }
109 |
110 | container.setTag(subItem);
111 | // container.setConditionItem(subItem);
112 | }
113 | }*//*
114 |
115 | mList.addView(container);
116 | container.setConditionItem(subItem);
117 |
118 | } */else if (subItem.type == NewConditionItem.TYPE_RANGE) {
119 | ConditionContainer container = new RangeContainer(getContext());
120 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
121 | ViewGroup.LayoutParams.MATCH_PARENT,
122 | ViewGroup.LayoutParams.WRAP_CONTENT
123 | );
124 | container.setLayoutParams(lp);
125 | container.setTag(subItem);
126 | addContentView(container);
127 | container.setConditionItem(subItem);
128 |
129 | } else if (subItem.type == NewConditionItem.TYPE_DATA) {
130 | ConditionContainer container = new DataSelectContainer(getContext());
131 | container.setLayoutParams(lp);
132 | container.setTag(subItem);
133 | addContentView(container);
134 | container.setConditionItem(subItem);
135 | } else {
136 | continue;
137 | }
138 | if (subItem != item.subItems.get(item.subItems.size() - 1)) {
139 | inflater.inflate(R.layout.layout_condition_divider, mList);
140 | }
141 | }
142 | View bottomBlank = new View(getContext());
143 | LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
144 | ViewGroup.LayoutParams.MATCH_PARENT, UIUtil.dip2px(getContext(), 30));
145 | bottomBlank.setLayoutParams(lp);
146 | mList.addView(bottomBlank);
147 | } else if (mRoot != null) {
148 | for (int i = 0; i < mRoot.subItems.size(); ++i) {
149 | NewConditionItem subItem = mRoot.subItems.get(i);
150 | ConditionContainer container = (ConditionContainer) mList.findViewWithTag(subItem);
151 | container.setConditionItem(subItem);
152 | }
153 | }
154 | }
155 |
156 | @Override
157 | public NewConditionItem create(List itemList) {
158 | return null;
159 | }
160 |
161 | @Override
162 | public void addContentView(View v) {
163 | v.setLayoutParams(lp);
164 | mList.addView(v);
165 | }
166 |
167 |
168 | @Override
169 | public void onClick(View v) {
170 | int i = v.getId();
171 | if (i == R.id.tv_reset_condition) {
172 | if (mRoot != null) {
173 | mRoot.clear();
174 | mRoot.reset();
175 | setConditionItem(mRoot);
176 | }
177 | } else if (i == R.id.tv_confirm_condition) {
178 | mController.confirm(FilterContainer.this);
179 | } else if (i == R.id.blank_condition) {
180 | mController.cancel(FilterContainer.this);
181 | } else {
182 | }
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/FilterMode.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | /**
4 | * Created by tamic on 2017-08-03.
5 | */
6 | public enum FilterMode {
7 | ITEM,
8 | ENTER
9 | }
10 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/FliterResultItem.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 |
4 | import java.util.ArrayList;
5 |
6 | /**
7 | * Created by LIUYONGKUI726 on 2018-03-06.
8 | */
9 |
10 | public class FliterResultItem {
11 |
12 | public int id;
13 | public String name;
14 | private ArrayList subItems;
15 |
16 |
17 | public void setSubItems(ArrayList subItems) {
18 | this.subItems = subItems;
19 | }
20 |
21 | public boolean isEmpty() {
22 | return subItems == null || subItems.size() == 0;
23 | }
24 |
25 | public ArrayList subItems() {
26 | return subItems;
27 | }
28 |
29 | public FliterResultItem createResult(NewConditionItem item) {
30 | FliterResultItem fliterResultItem = null;
31 | if (item.selected) {
32 | fliterResultItem = new FliterResultItem();
33 | fliterResultItem.id = item.id;
34 | fliterResultItem.name = item.name;
35 | fliterResultItem.subItems = new ArrayList<>();
36 | for (NewConditionItem subItem : item.subItems) {
37 | if (!subItem.selected) {
38 | continue;
39 | }
40 | fliterResultItem.subItems.add(fliterResultItem.createResult(subItem));
41 | }
42 | }
43 | return fliterResultItem;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/GridContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.CompoundButton;
8 | import android.widget.GridLayout;
9 | import android.widget.LinearLayout;
10 | import android.widget.RelativeLayout;
11 | import android.widget.TextView;
12 |
13 |
14 | import java.util.List;
15 |
16 | import widget.tamic.com.filterviewsipmle.R;
17 |
18 | /**
19 | * Update by Tamic on 2017-07-27
20 | *
21 | * @link {https://github.com/Tamicer/FilterBar}
22 | */
23 | public class GridContainer extends ConditionContainer implements CompoundButton.OnCheckedChangeListener, View.OnLayoutChangeListener {
24 |
25 |
26 | public GridContainer(Context context) {
27 | super(context);
28 | init();
29 | }
30 |
31 | private TextView mTvTitle;
32 | private GridLayout mGrid;
33 | private LinearLayout mLayout;
34 | private CompoundButton btn;
35 | private int columnCount = 4;
36 | private View view;
37 | private TextView mTvDateStart;
38 | private TextView mTvDateEnd;
39 | private RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
40 | LayoutParams.MATCH_PARENT,
41 | LayoutParams.WRAP_CONTENT);
42 |
43 | private void init() {
44 | LayoutInflater.from(getContext()).inflate(R.layout.layout_condition_grid, this);
45 | mTvTitle = (TextView) findViewById(R.id.tv_title_condition_grid);
46 | mGrid = (GridLayout) findViewById(R.id.grid_condition_grid);
47 | mGrid.setColumnCount(columnCount);
48 | mLayout = (LinearLayout) findViewById(R.id.grid_condition_custom_view);
49 | mGrid.addOnLayoutChangeListener(this);
50 |
51 | }
52 |
53 |
54 | public void addFooterView(View view) {
55 | this.view = view;
56 | mLayout.removeAllViews();
57 | mLayout.addView(view);
58 | }
59 |
60 | public void addHeaderView(View view) {
61 | addView(view);
62 | }
63 |
64 | private NewConditionItem mRoot;
65 | private DateSelectConditionItem item;
66 |
67 | @Override
68 | public NewConditionItem getConditionItem() {
69 | return mRoot;
70 | }
71 |
72 | @Override
73 | public void setConditionItem(NewConditionItem item) {
74 | mRoot = item;
75 | mTvTitle.setText(item.name);
76 | mGrid.removeAllViews();
77 | for (NewConditionItem subItem : mRoot.subItems) {
78 | if (subItem.type != NewConditionItem.TYPE_LIST) {
79 | if (subItem.type == NewConditionItem.TYPE_DATA) {
80 | this.item = (DateSelectConditionItem) subItem;
81 | DataSelectContainer container2 = new DataSelectContainer(getContext());
82 | LinearLayout.LayoutParams lp2 = new LinearLayout.LayoutParams(
83 | ViewGroup.LayoutParams.MATCH_PARENT,
84 | ViewGroup.LayoutParams.WRAP_CONTENT
85 | );
86 | container2.setLayoutParams(lp2);
87 | container2.setTag(subItem);
88 | container2.setConditionItem(subItem);
89 | addFooterView(container2);
90 | }
91 | continue;
92 |
93 | }
94 | btn = (CompoundButton) LayoutInflater.from(getContext())
95 | .inflate(R.layout.item_condition_grid, mGrid, false);
96 | btn.setTag(subItem);
97 | btn.setText(subItem.name);
98 | btn.setChecked(subItem.selected);
99 | btn.setOnCheckedChangeListener(this);
100 | addToGrid(btn);
101 | }
102 | }
103 |
104 | @Override
105 | public NewConditionItem create(List itemList) {
106 | return null;
107 | }
108 |
109 | @Override
110 | public void addContentView(View view) {
111 | addFooterView(view);
112 | }
113 |
114 | private void addToGrid(View v) {
115 | if (mGrid.getWidth() > 0) {
116 | ViewGroup.LayoutParams lp = v.getLayoutParams();
117 | lp.width = mGrid.getWidth() / columnCount;
118 | v.setLayoutParams(lp);
119 | }
120 | mGrid.addView(v);
121 | }
122 |
123 | public void clear() {
124 | for (int i = 0; i < mGrid.getChildCount(); i++) {
125 | CompoundButton btn = (CompoundButton) mGrid.getChildAt(i);
126 | NewConditionItem item = (NewConditionItem) btn.getTag();
127 | item.reset();
128 | setConditionItem(item);
129 | }
130 | }
131 |
132 | public void reSet() {
133 | if (item != null) {
134 | item.isRefresh = false;
135 | }
136 | if (mRoot != null) {
137 | mRoot.clear();
138 | mRoot.reset();
139 | setConditionItem(mRoot);
140 | }
141 | }
142 |
143 | @Override
144 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
145 |
146 | NewConditionItem item = (NewConditionItem) buttonView.getTag();
147 | boolean refresh = item.parent.processSubItems(item, buttonView.isChecked());
148 | buttonView.setChecked(item.selected);
149 | if (refresh) {
150 | setConditionItem(item.parent);
151 | }
152 |
153 | }
154 |
155 | @Override
156 | public void onLayoutChange(View v, int left, int top, int right, int bottom,
157 | int oldLeft, int oldTop, int oldRight, int oldBottom) {
158 | if (right - left == oldRight - oldLeft) {
159 | return;
160 | }
161 | int cellWidth = mGrid.getWidth() / columnCount;
162 | for (int i = 0; i < mGrid.getChildCount(); ++i) {
163 | View cell = mGrid.getChildAt(i);
164 | GridLayout.LayoutParams lp = (GridLayout.LayoutParams) cell.getLayoutParams();
165 | lp.width = cellWidth;
166 | cell.setLayoutParams(lp);
167 | }
168 | }
169 |
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/GroupFilterItem.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 |
4 | import android.os.Parcel;
5 | import android.os.Parcelable;
6 |
7 | import java.util.ArrayList;
8 |
9 | /**
10 | * GroupFilterItem
11 | */
12 | public class GroupFilterItem extends BaseFilterItem implements Parcelable {
13 |
14 | private ArrayList children;
15 |
16 | public ArrayList getChildren() {
17 | return children;
18 | }
19 |
20 | public void setChildren(ArrayList children) {
21 | this.children = children;
22 | }
23 |
24 | @Override
25 | public void writeToParcel(Parcel dest, int flags) {
26 | super.writeToParcel(dest, flags);
27 | if (null == children || 0 == children.size()) {
28 | dest.writeInt(0);
29 | } else {
30 | dest.writeInt(children.size());
31 | for (BaseFilterItem item : children) {
32 | dest.writeParcelable(item, flags);
33 | }
34 | }
35 | }
36 |
37 | public static Creator CREATOR = new Creator() {
38 |
39 | @Override
40 | public GroupFilterItem createFromParcel(Parcel source) {
41 | GroupFilterItem item = new GroupFilterItem();
42 | item.setCode(source.readInt());
43 | item.setName(source.readString());
44 | int size = source.readInt();
45 | ArrayList items = new ArrayList<>();
46 | if (0 != size) {
47 | for (int i = 0; i < size; i++) {
48 | items.add((BaseFilterItem) source
49 | .readParcelable(BaseFilterItem.class
50 | .getClassLoader()));
51 | }
52 | }
53 | item.setChildren(items);
54 | return item;
55 | }
56 |
57 | @Override
58 | public GroupFilterItem[] newArray(int size) {
59 | return new GroupFilterItem[size];
60 | }
61 | };
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/ListFilterBean.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 |
4 | import java.util.ArrayList;
5 | import java.util.List;
6 |
7 | /**
8 | * Created by suntaiyi on 2016-09-21.
9 | */
10 | public class ListFilterBean {
11 |
12 | static public class Item {
13 |
14 | public int id;
15 | public String name;
16 | public String value;
17 | public List- children = new ArrayList<>();
18 | }
19 |
20 | static public class ItemList {
21 |
22 | public String name;
23 | public List
- list = new ArrayList<>();
24 | }
25 |
26 | static public class Range {
27 |
28 | public String name;
29 | public int min;
30 | public int max;
31 | public int step;
32 | public String unit;
33 | }
34 |
35 |
36 | public ItemList region;
37 | public ItemList layout;
38 | public ItemList sort;
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/NewConditionItem.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by SUNTAIYI on 2016-08-22.
8 | */
9 | public class NewConditionItem extends BaseBean {
10 |
11 | public interface SubItemsProcessor {
12 |
13 | boolean check(List items, NewConditionItem selectChanged);
14 |
15 | boolean uncheck(List items, NewConditionItem selectChanged);
16 | }
17 |
18 | static public final SubItemsProcessor DEFAULT = new SubItemsProcessor() {
19 |
20 | @Override
21 | public boolean check(List items, NewConditionItem selectChanged) {
22 | if (selectChanged.isSingled) { //当item的只能独立选中的
23 | for (NewConditionItem item : items) { //将其他选中的item都clear
24 | item.selected = false;
25 | item.clear();
26 | }
27 | } else {
28 | for (NewConditionItem item : items) {
29 | if (item.isSingled) {
30 | item.selected = false;
31 | item.clear();
32 | }
33 | }
34 | }
35 | selectChanged.selected = true;
36 | selectChanged.reset();
37 | return true;
38 | }
39 |
40 | @Override
41 | public boolean uncheck(List items, NewConditionItem selectChanged) {
42 | selectChanged.selected = false;
43 | selectChanged.clear();
44 | return true;
45 | }
46 | };
47 | static public final SubItemsProcessor RADIO_LIST = new SubItemsProcessor() {
48 |
49 | @Override
50 | public boolean check(List items, NewConditionItem selectChanged) {
51 | if (items.size() == 0) {
52 | return false;
53 | }
54 | if (selectChanged.selected) {
55 | return false;
56 | }
57 | for (NewConditionItem item : items) {
58 | item.selected = false;
59 | item.clear();
60 | }
61 | selectChanged.selected = true;
62 | selectChanged.reset();
63 | return true;
64 | }
65 |
66 | @Override
67 | public boolean uncheck(List items, NewConditionItem selectChanged) {
68 | return false;
69 | }
70 | };
71 | static public final SubItemsProcessor RADIO_LIST_NO_CLEAR = new SubItemsProcessor() {
72 |
73 | @Override
74 | public boolean check(List items, NewConditionItem selectChanged) {
75 | if (items.size() == 0) {
76 | return false;
77 | }
78 | if (selectChanged.selected) {
79 | return false;
80 | }
81 | for (NewConditionItem item : items) {
82 | item.selected = false;
83 | }
84 | selectChanged.selected = true;
85 | selectChanged.reset();
86 | return true;
87 | }
88 |
89 | @Override
90 | public boolean uncheck(List items, NewConditionItem selectChanged) {
91 | return false;
92 | }
93 | };
94 | static public final SubItemsProcessor RADIO_LIST_UNCHECKABLE = new SubItemsProcessor() {
95 |
96 | @Override
97 | public boolean check(List items, NewConditionItem selectChanged) {
98 | if (items.size() == 0) {
99 | return false;
100 | }
101 | if (selectChanged.selected) {
102 | return false;
103 | }
104 | for (NewConditionItem item : items) {
105 | item.selected = false;
106 | item.clear();
107 | }
108 | selectChanged.selected = true;
109 | selectChanged.reset();
110 | return true;
111 | }
112 |
113 | @Override
114 | public boolean uncheck(List items, NewConditionItem selectChanged) {
115 | selectChanged.selected = false;
116 | selectChanged.clear();
117 | return true;
118 | }
119 | };
120 | static public final SubItemsProcessor ALL_AT_ZERO = new SubItemsProcessor() {
121 |
122 | @Override
123 | public boolean check(List items, NewConditionItem selectChanged) {
124 | if (items.size() == 0) {
125 | return false;
126 | }
127 | if (items.get(0) == selectChanged) {
128 | for (NewConditionItem item : items) {
129 | item.selected = false;
130 | item.clear();
131 | }
132 | selectChanged.selected = true;
133 | selectChanged.reset();
134 | return true;
135 | } else {
136 | items.get(0).selected = false;
137 | items.get(0).clear();
138 | selectChanged.selected = true;
139 | selectChanged.reset();
140 | return true;
141 | }
142 | }
143 |
144 | @Override
145 | public boolean uncheck(List items, NewConditionItem selectChanged) {
146 | if (items.size() == 0) {
147 | return false;
148 | }
149 |
150 | if (items.get(0) != selectChanged) {
151 | selectChanged.selected = false;
152 | selectChanged.clear();
153 | boolean all = true;
154 | for (NewConditionItem item : items) {
155 | if (item != items.get(0)) {
156 | all = all && !item.selected;
157 | }
158 | }
159 | if (all) {
160 | items.get(0).selected = true;
161 | items.get(0).reset();
162 | }
163 | return true;
164 | }
165 | return false;
166 | }
167 | };
168 | static public final SubItemsProcessor CLEAR_UNCLE_ON_CHECK = new SubItemsProcessor() {
169 |
170 | @Override
171 | public boolean check(List items, NewConditionItem selectChanged) {
172 | selectChanged.selected = true;
173 | selectChanged.reset();
174 | NewConditionItem parent = selectChanged.parent;
175 | if (parent == null) {
176 | return true;
177 | }
178 | NewConditionItem grand = parent.parent;
179 | if (grand == null) {
180 | return true;
181 | }
182 | for (NewConditionItem uncle : grand.subItems) {
183 | if (uncle == parent) {
184 | continue;
185 | }
186 | uncle.clear();
187 | }
188 | return true;
189 | }
190 |
191 | @Override
192 | public boolean uncheck(List items, NewConditionItem selectChanged) {
193 | selectChanged.selected = false;
194 | selectChanged.clear();
195 | return true;
196 | }
197 | };
198 | static public final int TYPE_LIST = 0;
199 | static public final int TYPE_GRID = 1;
200 | static public final int TYPE_RANGE = 2;
201 | static public final int TYPE_DATA = 3;
202 | static public final int TYPE_DNA_GRID_STYLE1 = 10;
203 | static public final int TYPE_DNA_GRID_STYLE2 = 11;
204 | static public final int TYPE_DNA_GRID_STYLE3 = 12;
205 | static public final int TYPE_DNA_GRID_STYLE4 = 13;
206 | static public final int TYPE_DNA_TAB_GRID = 20;
207 | static public final int TYPE_DNA_MUTUAL_TAB_GRID = 21;
208 | static public final int TYPE_DNA_ONE_ROW = 22;
209 | static public final int TYPE_DNA_FAVOR_GRID = 23;
210 | static public final int TYPE_EMPTY = -1;
211 |
212 | public NewConditionItem parent;
213 | public int id;
214 | public String name;
215 | public boolean selected;
216 | public boolean canReset = true;
217 | public int type = TYPE_LIST;
218 | public final List subItems = new ArrayList<>();
219 | public SubItemsProcessor processor = DEFAULT;
220 | public boolean isSingled = false; //此时的item是否是独立选择
221 |
222 | public NewConditionItem() {
223 | type = TYPE_EMPTY;
224 | }
225 |
226 | public NewConditionItem(int type) {
227 | this.type = type;
228 | }
229 |
230 | public NewConditionItem createConditionItem(int type) {
231 | return new NewConditionItem(type);
232 | }
233 |
234 | public NewConditionItem(NewConditionItem parent, int id, String name) {
235 | this(parent, id, name, false);
236 | }
237 |
238 | public NewConditionItem(NewConditionItem parent, int id, String name, boolean selected) {
239 | this(parent, id, name, selected, TYPE_LIST);
240 | }
241 |
242 | public NewConditionItem(NewConditionItem parent, int id, String name, boolean selected, int type) {
243 | this.parent = parent;
244 | this.id = id;
245 | this.name = name;
246 | this.selected = selected;
247 | this.type = type;
248 | this.isSingled = (id == 0);
249 | if (this.parent != null) {
250 | this.parent.subItems.add(this);
251 | }
252 | }
253 |
254 | public NewConditionItem subItemById(int id) {
255 | if (this.type == TYPE_EMPTY) {
256 | return createConditionItem(TYPE_EMPTY);
257 | }
258 | for (NewConditionItem item : subItems) {
259 | if (item.id == id) {
260 | return item;
261 | }
262 | }
263 | return createConditionItem(TYPE_EMPTY);
264 | }
265 |
266 | public List selectedSubItems() {
267 | List list = new ArrayList<>();
268 | for (NewConditionItem item : subItems) {
269 | if (item.selected) {
270 | list.add(item);
271 | }
272 | }
273 | return list;
274 | }
275 |
276 | public List unselectedSubItems() {
277 | List list = new ArrayList<>();
278 | for (NewConditionItem item : subItems) {
279 | if (!item.selected) {
280 | list.add(item);
281 | }
282 | }
283 | return list;
284 | }
285 |
286 | public NewConditionItem firstSelectedSubItem() {
287 | for (NewConditionItem item : subItems) {
288 | if (item.selected) {
289 | return item;
290 | }
291 | }
292 | return null;
293 | }
294 |
295 | public NewConditionItem root() {
296 | NewConditionItem item = this;
297 | while (item.parent != null) {
298 | item = item.parent;
299 | }
300 | return item;
301 | }
302 |
303 | public void rootClear() {
304 | NewConditionItem root = this.root();
305 | for (NewConditionItem top : root.subItems) {
306 | if (!top.selected) {
307 | top.clear();
308 | }
309 | }
310 | }
311 |
312 | public boolean isEmpty() {
313 | return type == TYPE_EMPTY;
314 | }
315 |
316 | public boolean isLeaf() {
317 | return subItems.size() == 0;
318 | }
319 |
320 | public boolean processSubItems(NewConditionItem selectedChanged, boolean checked) {
321 | if (processor != null) {
322 | if (checked) {
323 | return processor.check(subItems, selectedChanged);
324 | } else {
325 | return processor.uncheck(subItems, selectedChanged);
326 | }
327 | } else {
328 | return false;
329 | }
330 | }
331 |
332 | public void clear() {
333 | for (NewConditionItem subItem : subItems) {
334 | subItem.selected = false;
335 | subItem.clear();
336 | }
337 | }
338 |
339 | public void reset() {
340 | NewConditionItem selected = this.firstSelectedSubItem();
341 | if (canReset && selected == null && subItems.size() > 0) {
342 |
343 | if (subItems.get(0).type != NewConditionItem.TYPE_DATA) {
344 | subItems.get(0).selected = true;
345 | } else {
346 |
347 | }
348 | //subItems.subItemById(0).reset();
349 | for (NewConditionItem subItem : subItems) {
350 | if (subItem.type == NewConditionItem.TYPE_DATA) {
351 | continue;
352 | }
353 | subItem.reset();
354 | }
355 | }
356 | }
357 |
358 | public NewConditionItem clone() {
359 | NewConditionItem cloned = createConditionItem(this.type);
360 | cloned.id = this.id;
361 | cloned.name = this.name;
362 | cloned.selected = this.selected;
363 | cloned.canReset = this.canReset;
364 | cloned.type = this.type;
365 | cloned.processor = this.processor;
366 | cloned.isSingled = this.isSingled;
367 | for (NewConditionItem subItem : this.subItems) {
368 | NewConditionItem clonedSubItem = subItem.clone();
369 | clonedSubItem.parent = cloned;
370 | cloned.subItems.add(clonedSubItem);
371 | }
372 | return cloned;
373 | }
374 | }
375 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/RangeConditionItem.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | /**
4 | * Created by SUNTAIYI on 2016-08-24.
5 | */
6 | public class RangeConditionItem extends NewConditionItem {
7 |
8 | public interface RangeInfo {
9 | String getInfo(RangeConditionItem item);
10 | }
11 |
12 | static public final RangeInfo PRICE_INFO = new RangeInfo() {
13 | @Override
14 | public String getInfo(RangeConditionItem item) {
15 | if (item.from == item.min && item.to == item.max) {
16 | return "不限";
17 | }
18 | if (item.from > item.min && item.to == item.max) {
19 | return String.format("高于%.1f 万元", (float)item.from/10);
20 | }
21 | if (item.from == item.min && item.to < item.max) {
22 | return String.format("低于%.1f 万元", (float)item.to/10);
23 | }
24 |
25 | return String.format("%.1f 万元 — %.1f 万元", (float)item.from/10, (float)item.to/10);
26 | }
27 | };
28 | static public final RangeInfo AREA_INFO = new RangeInfo() {
29 | @Override
30 | public String getInfo(RangeConditionItem item) {
31 | if (item.from == item.min && item.to == item.max) {
32 | return "不限";
33 | }
34 | if (item.from > item.min && item.to == item.max) {
35 | return String.format("大于%d㎡", item.from);
36 | }
37 | if (item.from == item.min && item.to < item.max) {
38 | return String.format("小于%d㎡", item.to);
39 | }
40 |
41 | return String.format("%d㎡ — %d㎡", item.from, item.to);
42 | }
43 | };
44 | static public final RangeInfo RENT_PRICE_INFO = new RangeInfo() {
45 | @Override
46 | public String getInfo(RangeConditionItem item) {
47 | if (item.from == item.min && item.to == item.max) {
48 | return "不限";
49 | }
50 | if (item.from > item.min && item.to == item.max) {
51 | return String.format("高于%.1f 元", (float)item.from/10);
52 | }
53 | if (item.from == item.min && item.to < item.max) {
54 | return String.format("低于%.1f 元", (float)item.to/10);
55 | }
56 |
57 | return String.format("%.1f 元 — %.1f 元", (float)item.from/10, (float)item.to/10);
58 | }
59 | };
60 |
61 | public int min, max, step;
62 | public int from, to;
63 | public RangeInfo rangeInfo = null;
64 |
65 | public RangeConditionItem() {
66 | super();
67 | }
68 |
69 | public RangeConditionItem(NewConditionItem parent, int id, String name,
70 | int min, int max, int step, int from, int to) {
71 | super(parent, id, name, true, TYPE_RANGE);
72 | this.min = min;
73 | this.max = max;
74 | this.step = step;
75 | this.from = from;
76 | this.to = to;
77 | }
78 |
79 | @Override
80 | public void clear() {
81 | super.clear();
82 | from = min;
83 | to = max;
84 | }
85 |
86 | public String getInfo() {
87 | if (rangeInfo == null) {
88 | return "";
89 | } else {
90 | return rangeInfo.getInfo(this);
91 | }
92 | }
93 |
94 | @Override
95 | public NewConditionItem clone() {
96 | RangeConditionItem cloned = new RangeConditionItem();
97 | cloned.id = this.id;
98 | cloned.name = this.name;
99 | cloned.selected = this.selected;
100 | cloned.canReset = this.canReset;
101 | cloned.type = this.type;
102 | cloned.processor = this.processor;
103 | for (NewConditionItem subItem : this.subItems) {
104 | NewConditionItem clonedSubItem = subItem.clone();
105 | clonedSubItem.parent = cloned;
106 | cloned.subItems.add(clonedSubItem);
107 | }
108 | cloned.min = this.min;
109 | cloned.max = this.max;
110 | cloned.step = this.step;
111 | cloned.from = this.from;
112 | cloned.to = this.to;
113 | cloned.rangeInfo = this.rangeInfo;
114 | return cloned;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/RangeContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.widget.TextView;
7 |
8 |
9 | import java.util.List;
10 |
11 | import widget.tamic.com.filterviewsipmle.R;
12 |
13 | /**
14 | * Update by Tamic on 2017-07-27
15 | * https://github.com/Tamicer/FilterBar
16 | */
17 | public class RangeContainer extends ConditionContainer implements RangeSeekBar.OnRangeSeekBarChangeListener {
18 |
19 | public RangeContainer(Context context) {
20 | super(context);
21 | init();
22 | }
23 |
24 | private TextView mTvTitle;
25 | private TextView mTvInfo;
26 | private RangeSeekBar mBar;
27 | private int mLastFrom;
28 | private int mLastTo;
29 |
30 | private void init() {
31 | LayoutInflater.from(getContext()).inflate(R.layout.layout_condition_range, this);
32 |
33 | mTvTitle = (TextView) findViewById(R.id.tv_title_condition_range);
34 | mTvInfo = (TextView) findViewById(R.id.tv_info_condition_range);
35 | mBar = (RangeSeekBar) findViewById(R.id.bar_range);
36 | mBar.setOnRangeSeekBarChangeListener(this);
37 | mBar.setNotifyWhileDragging(true);
38 |
39 | }
40 |
41 | private RangeConditionItem mItem;
42 |
43 | @Override
44 | public NewConditionItem getConditionItem() {
45 | return mItem;
46 | }
47 |
48 | @Override
49 | public void setConditionItem(NewConditionItem item) {
50 | mItem = (RangeConditionItem) item;
51 | mTvTitle.setText(mItem.name);
52 | mTvInfo.setText(mItem.getInfo());
53 | mBar.setRangeValues(mItem.min, mItem.max);
54 | mBar.setSelectedMinValue(mItem.from);
55 | mBar.setSelectedMaxValue(mItem.to);
56 | mLastFrom = mItem.from;
57 | mLastTo = mItem.to;
58 | }
59 |
60 | @Override
61 | public NewConditionItem create(List itemList) {
62 | return null;
63 | }
64 |
65 | @Override
66 | public void addContentView(View view) {
67 | addView(view);
68 | }
69 |
70 | @Override
71 | public void onRangeSeekBarValuesChanged(RangeSeekBar> bar, Integer minValue, Integer maxValue) {
72 | int adjustMin = adjust(mItem.min, mItem.step, minValue);
73 | int adjustMax = adjust(mItem.min, mItem.step, maxValue);
74 | if (adjustMin == adjustMax) {
75 | if (mLastFrom == adjustMin) {
76 | adjustMax += mItem.step;
77 | } else if (mLastTo == adjustMax) {
78 | adjustMin -= mItem.step;
79 | }
80 | }
81 | mItem.from = adjustMin;
82 | mItem.to = adjustMax;
83 | mTvInfo.setText(mItem.getInfo());
84 | mBar.setSelectedMinValue(mItem.from);
85 | mBar.setSelectedMaxValue(mItem.to);
86 | mLastFrom = mItem.from;
87 | mLastTo = mItem.to;
88 | }
89 |
90 | static private int adjust(int base, int step, int value) {
91 | int steps = (value - base) / step;
92 | float r = (float) ((value - base) % step) / (float) step;
93 | return base + steps * step + Math.round(r) * step;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/RangeSeekBar.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2014 Stephan Tittel and Yahoo Inc.
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.tamic.widget.filter;
18 |
19 | import android.content.Context;
20 | import android.content.res.TypedArray;
21 | import android.graphics.Bitmap;
22 | import android.graphics.BitmapFactory;
23 | import android.graphics.Canvas;
24 | import android.graphics.Color;
25 | import android.graphics.Paint;
26 | import android.graphics.Paint.Style;
27 | import android.graphics.RectF;
28 | import android.os.Bundle;
29 | import android.os.Parcelable;
30 | import android.util.AttributeSet;
31 | import android.util.DisplayMetrics;
32 | import android.util.TypedValue;
33 | import android.view.MotionEvent;
34 | import android.view.ViewConfiguration;
35 | import android.widget.ImageView;
36 |
37 | import java.math.BigDecimal;
38 |
39 | import widget.tamic.com.filterviewsipmle.R;
40 |
41 | /**
42 | * Widget that lets users select a minimum and maximum value on a given numerical range.
43 | * The range value types can be one of Long, Double, Integer, Float, Short, Byte or BigDecimal.
44 | *
45 | * Improved {@link MotionEvent} handling for smoother use, anti-aliased painting for improved aesthetics.
46 | *
47 | * @param The Number type of the range values. One of Long, Double, Integer, Float, Short, Byte or BigDecimal.
48 | * @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
49 | * @author Peter Sinnott (psinnott@gmail.com)
50 | * @author Thomas Barrasso (tbarrasso@sevenplusandroid.org)
51 | * @author Alex Florescu (florescu@yahoo-inc.com)
52 | * @author Michael Keppler (bananeweizen@gmx.de)
53 | */
54 | public class RangeSeekBar extends ImageView {
55 |
56 | public static final Integer DEFAULT_MINIMUM = 0;
57 | public static final Integer DEFAULT_MAXIMUM = 100;
58 | public static final int HEIGHT_IN_DP = 10;
59 | public static final int TEXT_LATERAL_PADDING_IN_DP = 3;
60 | private static final int INITIAL_PADDING_IN_DP = 8;
61 | private static final int COLOR_OUTSIDE_RANGE = 0xffcccccc;
62 | private static final int COLOR_INSIDE_RANGE = 0xffff8447;
63 |
64 | private final int LINE_HEIGHT_IN_DP = 3;
65 | private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
66 | private final Bitmap thumbImage = BitmapFactory.decodeResource(
67 | getResources(), R.drawable.range_seek_bar_thumb);
68 | /*private final Bitmap thumbPressedImage = BitmapFactory.decodeResource(getResources(),
69 | R.drawable.seek_thumb_pressed);
70 | private final Bitmap thumbDisabledImage = BitmapFactory.decodeResource(getResources(),
71 | R.drawable.seek_thumb_disabled);*/
72 | private final float thumbWidth = thumbImage.getWidth();
73 | private final float thumbHalfWidth = 0.5f * thumbWidth;
74 | private final float thumbHalfHeight = 0.5f * thumbImage.getHeight();
75 | private float INITIAL_PADDING;
76 | private T absoluteMinValue, absoluteMaxValue;
77 | private NumberType numberType;
78 | private double absoluteMinValuePrim, absoluteMaxValuePrim;
79 | private double normalizedMinValue = 0d;
80 | private double normalizedMaxValue = 1d;
81 | private Thumb pressedThumb = null;
82 | private boolean notifyWhileDragging = false;
83 | private OnRangeSeekBarChangeListener listener;
84 | /**
85 | * Default color of a {@link RangeSeekBar}, #FF33B5E5. This is also known as "Ice Cream Sandwich" blue.
86 | */
87 | public static final int DEFAULT_COLOR = Color.argb(0xFF, 0x33, 0xB5, 0xE5);
88 | /**
89 | * An invalid pointer id.
90 | */
91 | public static final int INVALID_POINTER_ID = 255;
92 |
93 | // Localized constants from MotionEvent for compatibility
94 | // with API < 8 "Froyo".
95 | public static final int ACTION_POINTER_UP = 0x6, ACTION_POINTER_INDEX_MASK = 0x0000ff00, ACTION_POINTER_INDEX_SHIFT = 8;
96 |
97 | private float mDownMotionX;
98 |
99 | private int mActivePointerId = INVALID_POINTER_ID;
100 |
101 | private int mScaledTouchSlop;
102 |
103 | private boolean mIsDragging;
104 |
105 | //private int mTextOffset;
106 | private int mTextSize;
107 | private int mDistanceToTop;
108 | private RectF mRect;
109 |
110 | private static final int DEFAULT_TEXT_SIZE_IN_DP = 14;
111 | private static final int DEFAULT_TEXT_DISTANCE_TO_BUTTON_IN_DP = 8;
112 | private static final int DEFAULT_TEXT_DISTANCE_TO_TOP_IN_DP = 8;
113 | private boolean mSingleThumb;
114 |
115 | public RangeSeekBar(Context context) {
116 | super(context);
117 | init(context, null);
118 | }
119 |
120 | public RangeSeekBar(Context context, AttributeSet attrs) {
121 | super(context, attrs);
122 | init(context, attrs);
123 | }
124 |
125 | public RangeSeekBar(Context context, AttributeSet attrs, int defStyle) {
126 | super(context, attrs, defStyle);
127 | init(context, attrs);
128 | }
129 |
130 | private T extractNumericValueFromAttributes(TypedArray a, int attribute, int defaultValue) {
131 | TypedValue tv = a.peekValue(attribute);
132 | if (tv == null) {
133 | return (T) Integer.valueOf(defaultValue);
134 | }
135 |
136 | int type = tv.type;
137 | if (type == TypedValue.TYPE_FLOAT) {
138 | return (T) Float.valueOf(a.getFloat(attribute, defaultValue));
139 | } else {
140 | return (T) Integer.valueOf(a.getInteger(attribute, defaultValue));
141 | }
142 | }
143 |
144 | private void init(Context context, AttributeSet attrs) {
145 | if (attrs == null) {
146 | setRangeToDefaultValues();
147 | } else {
148 | TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RangeSeekBar, 0, 0);
149 | setRangeValues(
150 | extractNumericValueFromAttributes(a, R.styleable.RangeSeekBar_absoluteMinValue, DEFAULT_MINIMUM),
151 | extractNumericValueFromAttributes(a, R.styleable.RangeSeekBar_absoluteMaxValue, DEFAULT_MAXIMUM));
152 | mSingleThumb = a.getBoolean(R.styleable.RangeSeekBar_singleThumb, false);
153 | a.recycle();
154 | }
155 |
156 | setValuePrimAndNumberType();
157 |
158 | INITIAL_PADDING = PixelUtil.dpToPx(context, INITIAL_PADDING_IN_DP);
159 |
160 | mTextSize = PixelUtil.dpToPx(context, DEFAULT_TEXT_SIZE_IN_DP);
161 | mDistanceToTop = PixelUtil.dpToPx(context, DEFAULT_TEXT_DISTANCE_TO_TOP_IN_DP);
162 | /* mTextOffset = this.mTextSize +
163 | PixelUtil.dpToPx(context,DEFAULT_TEXT_DISTANCE_TO_BUTTON_IN_DP) +
164 | this.mDistanceToTop;*/
165 |
166 | float lineHeight = PixelUtil.dpToPx(context, LINE_HEIGHT_IN_DP);
167 | /*mRect = new RectF(getPaddingLeft(),
168 | mTextOffset + thumbHalfHeight - lineHeight / 2,
169 | getWidth() - getPaddingRight(),
170 | mTextOffset + thumbHalfHeight + lineHeight / 2);*/
171 | mRect = new RectF(getPaddingLeft(),
172 | thumbHalfHeight - lineHeight / 2,
173 | getWidth() - getPaddingRight(),
174 | thumbHalfHeight + lineHeight / 2);
175 |
176 | // make RangeSeekBar focusable. This solves focus handling issues in case EditText widgets are being used along with the RangeSeekBar within ScollViews.
177 | setFocusable(true);
178 | setFocusableInTouchMode(true);
179 | mScaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
180 | }
181 |
182 | public void setRangeValues(T minValue, T maxValue) {
183 | this.absoluteMinValue = minValue;
184 | this.absoluteMaxValue = maxValue;
185 | setValuePrimAndNumberType();
186 | }
187 |
188 | @SuppressWarnings("unchecked")
189 | // only used to set default values when initialised from XML without any values specified
190 | private void setRangeToDefaultValues() {
191 | this.absoluteMinValue = (T) DEFAULT_MINIMUM;
192 | this.absoluteMaxValue = (T) DEFAULT_MAXIMUM;
193 | setValuePrimAndNumberType();
194 | }
195 |
196 | private void setValuePrimAndNumberType() {
197 | absoluteMinValuePrim = absoluteMinValue.doubleValue();
198 | absoluteMaxValuePrim = absoluteMaxValue.doubleValue();
199 | numberType = NumberType.fromNumber(absoluteMinValue);
200 | }
201 |
202 | public void resetSelectedValues() {
203 | setSelectedMinValue(absoluteMinValue);
204 | setSelectedMaxValue(absoluteMaxValue);
205 | }
206 |
207 | public boolean isNotifyWhileDragging() {
208 | return notifyWhileDragging;
209 | }
210 |
211 | /**
212 | * Should the widget notify the listener callback while the user is still dragging a thumb? Default is false.
213 | *
214 | * @param flag
215 | */
216 | public void setNotifyWhileDragging(boolean flag) {
217 | this.notifyWhileDragging = flag;
218 | }
219 |
220 | /**
221 | * Returns the absolute minimum value of the range that has been set at construction time.
222 | *
223 | * @return The absolute minimum value of the range.
224 | */
225 | public T getAbsoluteMinValue() {
226 | return absoluteMinValue;
227 | }
228 |
229 | /**
230 | * Returns the absolute maximum value of the range that has been set at construction time.
231 | *
232 | * @return The absolute maximum value of the range.
233 | */
234 | public T getAbsoluteMaxValue() {
235 | return absoluteMaxValue;
236 | }
237 |
238 | /**
239 | * Returns the currently selected min value.
240 | *
241 | * @return The currently selected min value.
242 | */
243 | public T getSelectedMinValue() {
244 | return normalizedToValue(normalizedMinValue);
245 | }
246 |
247 | /**
248 | * Sets the currently selected minimum value. The widget will be invalidated and redrawn.
249 | *
250 | * @param value The Number value to set the minimum value to. Will be clamped to given absolute minimum/maximum range.
251 | */
252 | public void setSelectedMinValue(T value) {
253 | // in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
254 | if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) {
255 | setNormalizedMinValue(0d);
256 | } else {
257 | setNormalizedMinValue(valueToNormalized(value));
258 | }
259 | }
260 |
261 | /**
262 | * Returns the currently selected max value.
263 | *
264 | * @return The currently selected max value.
265 | */
266 | public T getSelectedMaxValue() {
267 | return normalizedToValue(normalizedMaxValue);
268 | }
269 |
270 | /**
271 | * Sets the currently selected maximum value. The widget will be invalidated and redrawn.
272 | *
273 | * @param value The Number value to set the maximum value to. Will be clamped to given absolute minimum/maximum range.
274 | */
275 | public void setSelectedMaxValue(T value) {
276 | // in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
277 | if (0 == (absoluteMaxValuePrim - absoluteMinValuePrim)) {
278 | setNormalizedMaxValue(1d);
279 | } else {
280 | setNormalizedMaxValue(valueToNormalized(value));
281 | }
282 | }
283 |
284 | /**
285 | * Registers given listener callback to notify about changed selected values.
286 | *
287 | * @param listener The listener to notify about changed selected values.
288 | */
289 | public void setOnRangeSeekBarChangeListener(OnRangeSeekBarChangeListener listener) {
290 | this.listener = listener;
291 | }
292 |
293 | /**
294 | * Handles thumb selection and movement. Notifies listener callback on certain events.
295 | */
296 | @Override
297 | public boolean onTouchEvent(MotionEvent event) {
298 |
299 | if (!isEnabled()) {
300 | return false;
301 | }
302 |
303 | int pointerIndex;
304 |
305 | final int action = event.getAction();
306 | switch (action & MotionEvent.ACTION_MASK) {
307 |
308 | case MotionEvent.ACTION_DOWN:
309 | // Remember where the motion event started
310 | mActivePointerId = event.getPointerId(event.getPointerCount() - 1);
311 | pointerIndex = event.findPointerIndex(mActivePointerId);
312 | mDownMotionX = event.getX(pointerIndex);
313 |
314 | pressedThumb = evalPressedThumb(mDownMotionX);
315 |
316 | // Only handle thumb presses.
317 | if (pressedThumb == null) {
318 | return super.onTouchEvent(event);
319 | }
320 |
321 | setPressed(true);
322 | invalidate();
323 | onStartTrackingTouch();
324 | trackTouchEvent(event);
325 | attemptClaimDrag();
326 |
327 | break;
328 | case MotionEvent.ACTION_MOVE:
329 | if (pressedThumb != null) {
330 |
331 | if (mIsDragging) {
332 | trackTouchEvent(event);
333 | } else {
334 | // Scroll to follow the motion event
335 | pointerIndex = event.findPointerIndex(mActivePointerId);
336 | final float x = event.getX(pointerIndex);
337 |
338 | if (Math.abs(x - mDownMotionX) > mScaledTouchSlop) {
339 | setPressed(true);
340 | invalidate();
341 | onStartTrackingTouch();
342 | trackTouchEvent(event);
343 | attemptClaimDrag();
344 | }
345 | }
346 |
347 | if (notifyWhileDragging && listener != null) {
348 | listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue());
349 | }
350 | }
351 | break;
352 | case MotionEvent.ACTION_UP:
353 | if (mIsDragging) {
354 | trackTouchEvent(event);
355 | onStopTrackingTouch();
356 | setPressed(false);
357 | } else {
358 | // Touch up when we never crossed the touch slop threshold
359 | // should be interpreted as a tap-seek to that location.
360 | onStartTrackingTouch();
361 | trackTouchEvent(event);
362 | onStopTrackingTouch();
363 | }
364 |
365 | pressedThumb = null;
366 | invalidate();
367 | if (listener != null) {
368 | listener.onRangeSeekBarValuesChanged(this, getSelectedMinValue(), getSelectedMaxValue());
369 | }
370 | break;
371 | case MotionEvent.ACTION_POINTER_DOWN: {
372 | final int index = event.getPointerCount() - 1;
373 | // final int index = ev.getActionIndex();
374 | mDownMotionX = event.getX(index);
375 | mActivePointerId = event.getPointerId(index);
376 | invalidate();
377 | break;
378 | }
379 | case MotionEvent.ACTION_POINTER_UP:
380 | onSecondaryPointerUp(event);
381 | invalidate();
382 | break;
383 | case MotionEvent.ACTION_CANCEL:
384 | if (mIsDragging) {
385 | onStopTrackingTouch();
386 | setPressed(false);
387 | }
388 | invalidate(); // see above explanation
389 | break;
390 | }
391 | return true;
392 | }
393 |
394 | private final void onSecondaryPointerUp(MotionEvent ev) {
395 | final int pointerIndex = (ev.getAction() & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT;
396 |
397 | final int pointerId = ev.getPointerId(pointerIndex);
398 | if (pointerId == mActivePointerId) {
399 | // This was our active pointer going up. Choose
400 | // a new active pointer and adjust accordingly.
401 | // TODO: Make this decision more intelligent.
402 | final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
403 | mDownMotionX = ev.getX(newPointerIndex);
404 | mActivePointerId = ev.getPointerId(newPointerIndex);
405 | }
406 | }
407 |
408 | private final void trackTouchEvent(MotionEvent event) {
409 | final int pointerIndex = event.findPointerIndex(mActivePointerId);
410 | final float x = event.getX(pointerIndex);
411 |
412 | if (Thumb.MIN.equals(pressedThumb) && !mSingleThumb) {
413 | setNormalizedMinValue(screenToNormalized(x));
414 | } else if (Thumb.MAX.equals(pressedThumb)) {
415 | setNormalizedMaxValue(screenToNormalized(x));
416 | }
417 | }
418 |
419 | /**
420 | * Tries to claim the user's drag motion, and requests disallowing any ancestors from stealing events in the drag.
421 | */
422 | private void attemptClaimDrag() {
423 | if (getParent() != null) {
424 | getParent().requestDisallowInterceptTouchEvent(true);
425 | }
426 | }
427 |
428 | /**
429 | * This is called when the user has started touching this widget.
430 | */
431 | void onStartTrackingTouch() {
432 | mIsDragging = true;
433 | }
434 |
435 | /**
436 | * This is called when the user either releases his touch or the touch is canceled.
437 | */
438 | void onStopTrackingTouch() {
439 | mIsDragging = false;
440 | }
441 |
442 | /**
443 | * Ensures correct size of the widget.
444 | */
445 | @Override
446 | protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
447 | int width = 200;
448 | if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(widthMeasureSpec)) {
449 | width = MeasureSpec.getSize(widthMeasureSpec);
450 | }
451 | //width -= getPaddingLeft() + getPaddingRight();
452 |
453 | int height = thumbImage.getHeight() + PixelUtil.dpToPx(getContext(), HEIGHT_IN_DP);
454 | if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(heightMeasureSpec)) {
455 | height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
456 | }
457 | height += getPaddingBottom() + getPaddingTop();
458 | setMeasuredDimension(width, height);
459 | }
460 |
461 | /**
462 | * Draws the widget on the given canvas.
463 | */
464 | @Override
465 | protected synchronized void onDraw(Canvas canvas) {
466 | super.onDraw(canvas);
467 |
468 | paint.setTextSize(mTextSize);
469 | paint.setStyle(Style.FILL);
470 | //paint.setColor(Color.GRAY);
471 | paint.setColor(COLOR_OUTSIDE_RANGE);
472 | paint.setAntiAlias(true);
473 |
474 | // draw min and max labels
475 | /*String minLabel = getContext().getString(R.string.demo_min_label);
476 | String maxLabel = getContext().getString(R.string.demo_max_label);
477 | float minMaxLabelSize = Math.max(paint.measureText(minLabel), paint.measureText(maxLabel));
478 | float minMaxHeight = mTextOffset + thumbHalfHeight + mTextSize / 3;
479 | canvas.drawText(minLabel, 0, minMaxHeight, paint);
480 | canvas.drawText(maxLabel, getWidth() - minMaxLabelSize, minMaxHeight, paint);
481 | padding = INITIAL_PADDING + minMaxLabelSize + thumbHalfWidth;*/
482 |
483 | // draw seek bar background line
484 | mRect.left = getPaddingLeft();
485 | mRect.right = getWidth() - getPaddingRight();
486 | canvas.drawRect(mRect, paint);
487 |
488 | boolean selectedValuesAreDefault = (getSelectedMinValue().equals(getAbsoluteMinValue()) &&
489 | getSelectedMaxValue().equals(getAbsoluteMaxValue()));
490 |
491 | /*int colorToUseForButtonsAndHighlightedLine = selectedValuesAreDefault ?
492 | Color.GRAY : // default values
493 | DEFAULT_COLOR; //non default, filter is active*/
494 |
495 | // draw seek bar active range line
496 | mRect.left = normalizedToScreen(normalizedMinValue);
497 | mRect.right = normalizedToScreen(normalizedMaxValue);
498 |
499 | paint.setColor(getResources().getColor(R.color.material_blue_grey_800));
500 | canvas.drawRect(mRect, paint);
501 |
502 | // draw minimum thumb if not a single thumb control
503 | if (!mSingleThumb) {
504 | drawThumb(normalizedToScreen(normalizedMinValue), Thumb.MIN.equals(pressedThumb), canvas,
505 | selectedValuesAreDefault);
506 | }
507 |
508 | // draw maximum thumb
509 | drawThumb(normalizedToScreen(normalizedMaxValue), Thumb.MAX.equals(pressedThumb), canvas,
510 | selectedValuesAreDefault);
511 |
512 | // draw the text if sliders have moved from default edges
513 | if (!selectedValuesAreDefault) {
514 | paint.setTextSize(mTextSize);
515 | paint.setColor(Color.WHITE);
516 | // give text a bit more space here so it doesn't subItemById cut off
517 | int offset = PixelUtil.dpToPx(getContext(), TEXT_LATERAL_PADDING_IN_DP);
518 |
519 | String minText = String.valueOf(getSelectedMinValue());
520 | String maxText = String.valueOf(getSelectedMaxValue());
521 | float minTextWidth = paint.measureText(minText) + offset;
522 | float maxTextWidth = paint.measureText(maxText) + offset;
523 |
524 | /*if (!mSingleThumb) {
525 | canvas.drawText(minText,
526 | normalizedToScreen(normalizedMinValue) - minTextWidth * 0.5f,
527 | mDistanceToTop + mTextSize,
528 | paint);
529 |
530 | }
531 |
532 | canvas.drawText(maxText,
533 | normalizedToScreen(normalizedMaxValue) - maxTextWidth * 0.5f,
534 | mDistanceToTop + mTextSize,
535 | paint);*/
536 | }
537 |
538 | }
539 |
540 | /**
541 | * Overridden to save instance state when device orientation changes. This method is called automatically if you assign an id to the RangeSeekBar widget using the {@link #setId(int)} method. Other members of this class than the normalized min and max values don't need to be saved.
542 | */
543 | @Override
544 | protected Parcelable onSaveInstanceState() {
545 | final Bundle bundle = new Bundle();
546 | bundle.putParcelable("SUPER", super.onSaveInstanceState());
547 | bundle.putDouble("MIN", normalizedMinValue);
548 | bundle.putDouble("MAX", normalizedMaxValue);
549 | return bundle;
550 | }
551 |
552 | /**
553 | * Overridden to restore instance state when device orientation changes. This method is called automatically if you assign an id to the RangeSeekBar widget using the {@link #setId(int)} method.
554 | */
555 | @Override
556 | protected void onRestoreInstanceState(Parcelable parcel) {
557 | final Bundle bundle = (Bundle) parcel;
558 | super.onRestoreInstanceState(bundle.getParcelable("SUPER"));
559 | normalizedMinValue = bundle.getDouble("MIN");
560 | normalizedMaxValue = bundle.getDouble("MAX");
561 | }
562 |
563 | /**
564 | * Draws the "normal" resp. "pressed" thumb image on specified x-coordinate.
565 | *
566 | * @param screenCoord The x-coordinate in screen space where to draw the image.
567 | * @param pressed Is the thumb currently in "pressed" state?
568 | * @param canvas The canvas to draw upon.
569 | */
570 | private void drawThumb(float screenCoord, boolean pressed, Canvas canvas, boolean areSelectedValuesDefault) {
571 | Bitmap buttonToDraw;
572 | /*if (areSelectedValuesDefault) {
573 | buttonToDraw = thumbDisabledImage;
574 | } else {
575 | buttonToDraw = pressed ? thumbPressedImage : thumbImage;
576 | }*/
577 | buttonToDraw = thumbImage;
578 |
579 | canvas.drawBitmap(buttonToDraw, screenCoord - thumbHalfWidth,
580 | 0,
581 | paint);
582 | }
583 |
584 | /**
585 | * Decides which (if any) thumb is touched by the given x-coordinate.
586 | *
587 | * @param touchX The x-coordinate of a touch event in screen space.
588 | * @return The pressed thumb or null if none has been touched.
589 | */
590 | private Thumb evalPressedThumb(float touchX) {
591 | Thumb result = null;
592 | boolean minThumbPressed = isInThumbRange(touchX, normalizedMinValue);
593 | boolean maxThumbPressed = isInThumbRange(touchX, normalizedMaxValue);
594 | if (minThumbPressed && maxThumbPressed) {
595 | // if both thumbs are pressed (they lie on top of each other), choose the one with more room to drag. this avoids "stalling" the thumbs in a corner, not being able to drag them apart anymore.
596 | result = (touchX / getWidth() > 0.5f) ? Thumb.MIN : Thumb.MAX;
597 | } else if (minThumbPressed) {
598 | result = Thumb.MIN;
599 | } else if (maxThumbPressed) {
600 | result = Thumb.MAX;
601 | }
602 | return result;
603 | }
604 |
605 | /**
606 | * Decides if given x-coordinate in screen space needs to be interpreted as "within" the normalized thumb x-coordinate.
607 | *
608 | * @param touchX The x-coordinate in screen space to check.
609 | * @param normalizedThumbValue The normalized x-coordinate of the thumb to check.
610 | * @return true if x-coordinate is in thumb range, false otherwise.
611 | */
612 | private boolean isInThumbRange(float touchX, double normalizedThumbValue) {
613 | return Math.abs(touchX - normalizedToScreen(normalizedThumbValue)) <= thumbHalfWidth;
614 | }
615 |
616 | /**
617 | * Sets normalized min value to value so that 0 <= value <= normalized max value <= 1. The View will subItemById invalidated when calling this method.
618 | *
619 | * @param value The new normalized min value to set.
620 | */
621 | private void setNormalizedMinValue(double value) {
622 | normalizedMinValue = Math.max(0d, Math.min(1d, Math.min(value, normalizedMaxValue)));
623 | invalidate();
624 | }
625 |
626 | /**
627 | * Sets normalized max value to value so that 0 <= normalized min value <= value <= 1. The View will subItemById invalidated when calling this method.
628 | *
629 | * @param value The new normalized max value to set.
630 | */
631 | private void setNormalizedMaxValue(double value) {
632 | normalizedMaxValue = Math.max(0d, Math.min(1d, Math.max(value, normalizedMinValue)));
633 | invalidate();
634 | }
635 |
636 | /**
637 | * Converts a normalized value to a Number object in the value space between absolute minimum and maximum.
638 | *
639 | * @param normalized
640 | * @return
641 | */
642 | @SuppressWarnings("unchecked")
643 | private T normalizedToValue(double normalized) {
644 | double v = absoluteMinValuePrim + normalized * (absoluteMaxValuePrim - absoluteMinValuePrim);
645 | // TODO parameterize this rounding to allow variable decimal points
646 | return (T) numberType.toNumber(Math.round(v * 100) / 100d);
647 | }
648 |
649 | /**
650 | * Converts the given Number value to a normalized double.
651 | *
652 | * @param value The Number value to normalize.
653 | * @return The normalized double.
654 | */
655 | private double valueToNormalized(T value) {
656 | if (0 == absoluteMaxValuePrim - absoluteMinValuePrim) {
657 | // prevent division by zero, simply return 0.
658 | return 0d;
659 | }
660 | return (value.doubleValue() - absoluteMinValuePrim) / (absoluteMaxValuePrim - absoluteMinValuePrim);
661 | }
662 |
663 | /**
664 | * Converts a normalized value into screen space.
665 | *
666 | * @param normalizedCoord The normalized value to convert.
667 | * @return The converted value in screen space.
668 | */
669 | private float normalizedToScreen(double normalizedCoord) {
670 | return (float) (getPaddingLeft() + normalizedCoord * (getWidth() - getPaddingLeft() - getPaddingRight()));
671 | }
672 |
673 | /**
674 | * Converts screen space x-coordinates into normalized values.
675 | *
676 | * @param screenCoord The x-coordinate in screen space to convert.
677 | * @return The normalized value.
678 | */
679 | private double screenToNormalized(float screenCoord) {
680 | int padding = getPaddingLeft() + getPaddingRight();
681 | int width = getWidth();
682 | if (width <= 2 * padding) {
683 | // prevent division by zero, simply return 0.
684 | return 0d;
685 | } else {
686 | double result = (screenCoord - padding) / (width - 2 * padding);
687 | return Math.min(1d, Math.max(0d, result));
688 | }
689 | }
690 |
691 | /**
692 | * Callback listener interface to notify about changed range values.
693 | *
694 | * @param The Number type the RangeSeekBar has been declared with.
695 | * @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
696 | */
697 | public interface OnRangeSeekBarChangeListener {
698 |
699 | public void onRangeSeekBarValuesChanged(RangeSeekBar> bar, T minValue, T maxValue);
700 | }
701 |
702 | /**
703 | * Thumb constants (min and max).
704 | */
705 | private static enum Thumb {
706 | MIN, MAX
707 | }
708 |
709 | ;
710 |
711 | /**
712 | * Utility enumeration used to convert between Numbers and doubles.
713 | *
714 | * @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
715 | */
716 | private static enum NumberType {
717 | LONG, DOUBLE, INTEGER, FLOAT, SHORT, BYTE, BIG_DECIMAL;
718 |
719 | public static NumberType fromNumber(E value) throws IllegalArgumentException {
720 | if (value instanceof Long) {
721 | return LONG;
722 | }
723 | if (value instanceof Double) {
724 | return DOUBLE;
725 | }
726 | if (value instanceof Integer) {
727 | return INTEGER;
728 | }
729 | if (value instanceof Float) {
730 | return FLOAT;
731 | }
732 | if (value instanceof Short) {
733 | return SHORT;
734 | }
735 | if (value instanceof Byte) {
736 | return BYTE;
737 | }
738 | if (value instanceof BigDecimal) {
739 | return BIG_DECIMAL;
740 | }
741 | throw new IllegalArgumentException("Number class '" + value.getClass().getName() + "' is not supported");
742 | }
743 |
744 | public Number toNumber(double value) {
745 | switch (this) {
746 | case LONG:
747 | return Long.valueOf((long) value);
748 | case DOUBLE:
749 | return value;
750 | case INTEGER:
751 | return Integer.valueOf((int) value);
752 | case FLOAT:
753 | return Float.valueOf((float)value);
754 | case SHORT:
755 | return Short.valueOf((short) value);
756 | case BYTE:
757 | return Byte.valueOf((byte) value);
758 | case BIG_DECIMAL:
759 | return BigDecimal.valueOf(value);
760 | }
761 | throw new InstantiationError("can't convert " + this + " to a Number object");
762 | }
763 | }
764 |
765 | /**
766 | * Util class for converting between dp, px and other magical pixel units
767 | */
768 | public static class PixelUtil {
769 |
770 | private PixelUtil() {
771 | }
772 |
773 | public static int dpToPx(Context context, int dp) {
774 | int px = Math.round(dp * getPixelScaleFactor(context));
775 | return px;
776 | }
777 |
778 | public static int pxToDp(Context context, int px) {
779 | int dp = Math.round(px / getPixelScaleFactor(context));
780 | return dp;
781 | }
782 |
783 | private static float getPixelScaleFactor(Context context) {
784 | DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
785 | return (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT);
786 | }
787 |
788 | }
789 | }
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/RegionContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.animation.Animator;
4 | import android.animation.ValueAnimator;
5 | import android.content.Context;
6 | import android.graphics.Canvas;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.v4.content.ContextCompat;
9 | import android.support.v7.widget.LinearLayoutManager;
10 | import android.support.v7.widget.RecyclerView;
11 | import android.util.AttributeSet;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.widget.CompoundButton;
16 | import android.widget.LinearLayout;
17 | import android.widget.TextView;
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import widget.tamic.com.filterviewsipmle.R;
22 |
23 | /**
24 | *
25 | * Created by Tamic on 2017-07-27
26 | */
27 | public class RegionContainer extends ConditionContainer implements View.OnClickListener {
28 |
29 | private FilterMode mFilterMode;
30 |
31 | public static int TYPE_NORMAL = 1000;
32 | public static int TYPE_EDIT = 1001;
33 | public static int TYPE_ALL = 1002;
34 |
35 |
36 | public RegionContainer(Context context, FilterMode filterMode) {
37 | super(context);
38 | mFilterMode = filterMode;
39 | init();
40 | }
41 |
42 | public RegionContainer(Context context, AttributeSet attrs) {
43 | super(context, attrs);
44 | init();
45 | }
46 |
47 | private void init() {
48 | View inflate = LayoutInflater.from(getContext()).inflate(R.layout.layout_condition_region, this);
49 | mTabGroup = (LinearLayout) findViewById(R.id.tab_layout_condition_region);
50 | mPrimaryList = (RecyclerView) findViewById(R.id.list_primary_layout_condition_region);
51 | mSecondaryList = (RecyclerView) findViewById(R.id.list_secondary_layout_condition_region);
52 | mConfirmPannel = (LinearLayout) findViewById(R.id.bottom_layout_condition_region);
53 |
54 | if (checkConfimPannelVisibility()) {
55 | mConfirmPannel.setVisibility(View.VISIBLE);
56 | this.invalidate();
57 | }
58 |
59 | mDecoration = new DividerItemDecoration(getContext(), R.drawable.shape_list_divider);
60 | mPrimaryList.addItemDecoration(mDecoration);
61 |
62 | mPrimaryList.setLayoutManager(new LinearLayoutManager(getContext()));
63 | mSecondaryList.setLayoutManager(new LinearLayoutManager(getContext()));
64 | mPrimaryAdapter = new ConditionItemAdapter(R.layout.item_condition_2, mLevelTwoClickListener);
65 | mSecondaryAdapter = new ConditionItem2Adapter(R.layout.item_condition_2, R.layout.item_condition_3, mLevelThreeClickListener);
66 | mSecondaryAdapter.setOnItemClickListener(mLevelThreeItemListener);
67 | mPrimaryList.setAdapter(mPrimaryAdapter);
68 | mSecondaryList.setAdapter(mSecondaryAdapter);
69 |
70 | mTvReset = (TextView) findViewById(R.id.tv_reset_condition);
71 | mTvConfirm = (TextView) findViewById(R.id.tv_confirm_condition);
72 | mTvReset.setOnClickListener(this);
73 | mTvConfirm.setOnClickListener(this);
74 | findViewById(R.id.blank_condition).setOnClickListener(this);
75 | }
76 |
77 | private LinearLayout mTabGroup;
78 | private LinearLayout mConfirmPannel;
79 | private RecyclerView mPrimaryList;
80 | private RecyclerView mSecondaryList;
81 | private TextView mTvReset;
82 | private TextView mTvConfirm;
83 | private ConditionItemAdapter mPrimaryAdapter;
84 | private ConditionItem2Adapter mSecondaryAdapter;
85 | private DividerItemDecoration mDecoration;
86 | private NewConditionItem mRoot;
87 | private boolean mSetting = false;
88 |
89 | private OnClickListener mLevelOneClickListener = new OnClickListener() {
90 | @Override
91 | public void onClick(View v) {
92 | CompoundButton cb = (CompoundButton) v;
93 | NewConditionItem item = (NewConditionItem) cb.getTag();
94 | boolean refresh = item.parent.processSubItems(item, cb.isChecked());
95 | cb.setChecked(item.selected);
96 | if (refresh) {
97 | setLv0Item(item.parent);
98 | }
99 | }
100 | };
101 | private OnClickListener mLevelTwoClickListener = new OnClickListener() {
102 | @Override
103 | public void onClick(View v) {
104 | CompoundButton cb = (CompoundButton) v;
105 | NewConditionItem item = (NewConditionItem) cb.getTag();
106 | boolean refresh = item.parent.processSubItems(item, cb.isChecked());
107 | cb.setChecked(item.selected);
108 | if (refresh) {
109 | item.rootClear();
110 | setLv1Item(item.parent);
111 | }
112 |
113 | }
114 | };
115 |
116 | private OnClickListener mLevelThreeClickListener = new OnClickListener() {
117 | @Override
118 | public void onClick(View v) {
119 | CompoundButton cb = (CompoundButton) v;
120 | NewConditionItem item = (NewConditionItem) cb.getTag();
121 | boolean refresh = item.parent.processSubItems(item, cb.isChecked());
122 | cb.setChecked(item.selected);
123 | if (refresh) {
124 | item.rootClear();
125 | setLv2Item(item.parent);
126 | }
127 |
128 | if (!checkConfimPannelVisibility()) {
129 | refreshDrawableState();
130 | v.postDelayed(new Runnable() {
131 | @Override
132 | public void run() {
133 | mController.confirm(RegionContainer.this);
134 | }
135 | }, 20);
136 | }
137 |
138 |
139 | }
140 | };
141 |
142 | private OnItemClickListener mLevelThreeItemListener = new OnItemClickListener() {
143 |
144 | @Override
145 | public void onEditClick(View v, int viewType) {
146 | mController.onItemClick(RegionContainer.this, viewType);
147 | }
148 | };
149 |
150 | @Override
151 | public NewConditionItem getConditionItem() {
152 | return mRoot;
153 | }
154 |
155 | @Override
156 | public void setConditionItem(NewConditionItem item) {
157 | mRoot = item;
158 | if (item == null) {
159 | mTabGroup.removeAllViews();
160 | return;
161 | }
162 | if (this.isLayoutRequested()) {
163 | this.addOnLayoutChangeListener(new OnLayoutChangeListener() {
164 | @Override
165 | public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
166 | v.removeOnLayoutChangeListener(this);
167 | mSetting = true;
168 | setLv0Item(mRoot);
169 | mSetting = false;
170 | }
171 | });
172 | } else {
173 | mSetting = true;
174 | setLv0Item(mRoot);
175 | mSetting = false;
176 | }
177 | }
178 |
179 | @Override
180 | public NewConditionItem create(List itemList) {
181 | return null;
182 | }
183 |
184 | @Override
185 | public void addContentView(View view) {
186 | addView(view);
187 | }
188 |
189 | @Override
190 | public void onItemClick(ConditionContainer container) {
191 | super.onItemClick(container);
192 | mController.confirm(container);
193 | }
194 |
195 | private void setLv0Item(NewConditionItem item) {
196 | mTabGroup.removeAllViews();
197 | for (NewConditionItem subItem : item.subItems) {
198 | CompoundButton btn = (CompoundButton) LayoutInflater.from(getContext()).inflate(
199 | R.layout.item_condition_1, mTabGroup, false);
200 | btn.setText(subItem.name);
201 | btn.setChecked(subItem.selected);
202 | btn.setTag(subItem);
203 | btn.setOnClickListener(mLevelOneClickListener);
204 | mTabGroup.addView(btn);
205 | }
206 | for (NewConditionItem subItem : item.subItems) {
207 | if (subItem.selected) {
208 | setLv1Item(subItem);
209 | return;
210 | }
211 | }
212 | setLv1Item(null);
213 | }
214 |
215 | private void setLv1Item(NewConditionItem item) {
216 | if (item == null) {
217 | mPrimaryList.setVisibility(View.GONE);
218 | setLv2Item(null);
219 | return;
220 | }
221 | if (mPrimaryList.getVisibility() != View.VISIBLE) {
222 | mPrimaryList.setVisibility(View.VISIBLE);
223 | }
224 | mPrimaryAdapter.setList(item.subItems);
225 | mPrimaryAdapter.notifyDataSetChanged();
226 |
227 | for (int i = 0; i < item.subItems.size(); ++i) {
228 | NewConditionItem subItem = item.subItems.get(i);
229 | if (subItem.selected) {
230 | setLv2Item(subItem);
231 | if (mSetting) {
232 | checkSelectedItemVisibility(mPrimaryList, i);
233 | }
234 | return;
235 | }
236 | }
237 | setLv2Item(null);
238 | }
239 |
240 | private void setLv2Item(NewConditionItem item) {
241 | if (item == null || item.isLeaf()) {
242 | closeSecondaryList();
243 | return;
244 | }
245 | mSecondaryAdapter.setList(item.subItems);
246 | mSecondaryAdapter.notifyDataSetChanged();
247 | for (int i = 0; i < item.subItems.size(); ++i) {
248 | NewConditionItem subItem = item.subItems.get(i);
249 | if (subItem.selected) {
250 | if (mSetting) {
251 | checkSelectedItemVisibility(mSecondaryList, i);
252 | }
253 | }
254 | }
255 | openSecondaryList();
256 | }
257 |
258 | private boolean mIsAnimating;
259 | private void closeSecondaryList() {
260 | final int w = getWidth();
261 | if (mSetting) {
262 | ViewGroup.LayoutParams lp;
263 | lp = mPrimaryList.getLayoutParams();
264 | lp.width = w;
265 | mPrimaryList.setLayoutParams(lp);
266 | lp = mSecondaryList.getLayoutParams();
267 | lp.width = 0;
268 | mSecondaryList.setLayoutParams(lp);
269 | } else {
270 | if (!mIsAnimating && mSecondaryList.getWidth() != 0) {
271 | ValueAnimator anime = ValueAnimator.ofInt(w / 2, w);
272 | anime.setDuration(500);
273 | anime.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
274 | @Override
275 | public void onAnimationUpdate(ValueAnimator animation) {
276 | Integer value = (Integer) animation.getAnimatedValue();
277 | mPrimaryList.layout(
278 | mPrimaryList.getLeft(),
279 | mPrimaryList.getTop(),
280 | value,
281 | mPrimaryList.getBottom()
282 | );
283 | mSecondaryList.layout(
284 | value,
285 | mSecondaryList.getTop(),
286 | value + w / 2,
287 | mSecondaryList.getBottom()
288 | );
289 | }
290 | });
291 | anime.addListener(new Animator.AnimatorListener() {
292 | @Override
293 | public void onAnimationStart(Animator animation) {
294 | mIsAnimating = true;
295 | }
296 |
297 | @Override
298 | public void onAnimationEnd(Animator animation) {
299 | ViewGroup.LayoutParams lp;
300 | lp = mPrimaryList.getLayoutParams();
301 | lp.width = w;
302 | mPrimaryList.setLayoutParams(lp);
303 | lp = mSecondaryList.getLayoutParams();
304 | lp.width = 0;
305 | mSecondaryList.setLayoutParams(lp);
306 | mIsAnimating = false;
307 | }
308 |
309 | @Override
310 | public void onAnimationCancel(Animator animation) {
311 |
312 | }
313 |
314 | @Override
315 | public void onAnimationRepeat(Animator animation) {
316 |
317 | }
318 | });
319 | anime.start();
320 | }
321 | }
322 | }
323 | private void openSecondaryList() {
324 | final int w = getWidth();
325 | if (mSetting) {
326 | ViewGroup.LayoutParams lp;
327 | lp = mPrimaryList.getLayoutParams();
328 | lp.width = w / 2;
329 | mPrimaryList.setLayoutParams(lp);
330 | lp = mSecondaryList.getLayoutParams();
331 | lp.width = w / 2;
332 | mSecondaryList.setLayoutParams(lp);
333 | } else {
334 | if (!mIsAnimating && mSecondaryList.getWidth() == 0) {
335 | ValueAnimator anime = ValueAnimator.ofInt(w, w / 2);
336 | anime.setDuration(500);
337 | anime.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
338 | @Override
339 | public void onAnimationUpdate(ValueAnimator animation) {
340 | Integer value = (Integer) animation.getAnimatedValue();
341 | mPrimaryList.layout(
342 | mPrimaryList.getLeft(),
343 | mPrimaryList.getTop(),
344 | value,
345 | mPrimaryList.getBottom()
346 | );
347 | mSecondaryList.layout(
348 | value,
349 | mSecondaryList.getTop(),
350 | value + w / 2,
351 | mSecondaryList.getBottom()
352 | );
353 | }
354 | });
355 | anime.addListener(new Animator.AnimatorListener() {
356 | @Override
357 | public void onAnimationStart(Animator animation) {
358 | mIsAnimating = true;
359 | }
360 |
361 | @Override
362 | public void onAnimationEnd(Animator animation) {
363 | ViewGroup.LayoutParams lp;
364 | lp = mPrimaryList.getLayoutParams();
365 | lp.width = w / 2;
366 | mPrimaryList.setLayoutParams(lp);
367 | lp = mSecondaryList.getLayoutParams();
368 | lp.width = w / 2;
369 | mSecondaryList.setLayoutParams(lp);
370 | mIsAnimating = false;
371 | }
372 |
373 | @Override
374 | public void onAnimationCancel(Animator animation) {
375 |
376 | }
377 |
378 | @Override
379 | public void onAnimationRepeat(Animator animation) {
380 |
381 | }
382 | });
383 | anime.start();
384 | }
385 | }
386 | }
387 |
388 | private void checkSelectedItemVisibility(RecyclerView listView, int position) {
389 | listView.scrollToPosition(position);
390 | }
391 |
392 | private boolean checkConfimPannelVisibility() {
393 | /* if (mCallback == null) {
394 | retur;
395 | }*/
396 | // return FilterMode.ENTER.ordinal() == mCallback.geFiterMode().ordinal();
397 | return FilterMode.ENTER.ordinal() == mFilterMode.ordinal();
398 | }
399 |
400 | @Override
401 | public void onClick(View v) {
402 | int i = v.getId();
403 | if (i == R.id.tv_reset_condition) {
404 | if (mRoot != null) {
405 | mRoot.clear();
406 | mRoot.reset();
407 | setConditionItem(mRoot);
408 | }
409 | } else if (i == R.id.tv_confirm_condition) {
410 | mController.confirm(RegionContainer.this);
411 | } else if (i == R.id.blank_condition) {
412 | mController.cancel(RegionContainer.this);
413 | } else {
414 | }
415 | }
416 |
417 | private static class ConditionItemAdapter extends RecyclerView.Adapter {
418 |
419 | static final List EMPTY_LIST = new ArrayList<>();
420 | private List mList = EMPTY_LIST;
421 | private int mItemLayoutID;
422 | private OnClickListener mOnClickListener;
423 |
424 | public ConditionItemAdapter(int itemLayoutID, OnClickListener listener) {
425 | mItemLayoutID = itemLayoutID;
426 | mOnClickListener = listener;
427 | }
428 |
429 | public void setList(List list) {
430 | if (list == null) {
431 | list = EMPTY_LIST;
432 | }
433 | mList = list;
434 | }
435 |
436 | @Override
437 | public VH onCreateViewHolder(ViewGroup parent, int viewType) {
438 | return new VH(LayoutInflater.from(parent.getContext()).inflate(
439 | mItemLayoutID, parent, false));
440 | }
441 |
442 | @Override
443 | public void onBindViewHolder(VH holder, int position) {
444 | NewConditionItem item = mList.get(position);
445 | holder.tb.setText(item.name);
446 | holder.tb.setChecked(item.selected);
447 | holder.tb.setTag(item);
448 | holder.tb.setOnClickListener(mOnClickListener);
449 | }
450 |
451 | @Override
452 | public int getItemCount() {
453 | return mList.size();
454 | }
455 |
456 | }
457 |
458 |
459 | private static class ConditionItem2Adapter extends RecyclerView.Adapter {
460 |
461 | static final List EMPTY_LIST = new ArrayList<>();
462 | private final int mItemSpecLayoutID;
463 | private List mList = EMPTY_LIST;
464 | private int mItemLayoutID;
465 | private OnClickListener mOnClickListener;
466 | private OnItemClickListener mOnItemClickListener;
467 |
468 | public ConditionItem2Adapter(int itemLayoutID,int itemSpecLayoutID ,OnClickListener listener) {
469 | mItemLayoutID = itemLayoutID;
470 | mItemSpecLayoutID = itemSpecLayoutID;
471 | mOnClickListener = listener;
472 | }
473 |
474 | public OnItemClickListener getOnItemClickListener() {
475 | return mOnItemClickListener;
476 | }
477 |
478 | public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
479 | this.mOnItemClickListener = mOnItemClickListener;
480 | }
481 |
482 | public void setList(List list) {
483 | if (list == null) {
484 | list = EMPTY_LIST;
485 | }
486 | mList = list;
487 | }
488 |
489 | @Override
490 | public RegionContainer.VH onCreateViewHolder(ViewGroup parent, int viewType) {
491 |
492 | if (viewType == TYPE_NORMAL) {
493 | return new RegionContainer.VH(LayoutInflater.from(parent.getContext()).inflate(
494 | mItemLayoutID, parent, false));
495 | } else if (viewType == TYPE_EDIT) {
496 | return new RegionContainer.VH(LayoutInflater.from(parent.getContext()).inflate(
497 | mItemSpecLayoutID, parent, false));
498 | }
499 |
500 | return new RegionContainer.VH(LayoutInflater.from(parent.getContext()).inflate(
501 | mItemLayoutID, parent, false));
502 | }
503 |
504 | @Override
505 | public void onBindViewHolder(RegionContainer.VH holder, final int position) {
506 | final NewConditionItem item = mList.get(position);
507 | if (holder.getItemViewType() == TYPE_EDIT) {
508 | CompoundButton btnEdit = holder.tb;
509 | btnEdit.setText(item.name);
510 | btnEdit.setChecked(item.selected);
511 | btnEdit.setTag(item);
512 | btnEdit.setId(holder.getItemViewType());
513 | btnEdit.setOnClickListener(mOnClickListener);
514 | final View finalView = btnEdit;
515 | final NewConditionItem finalitem =item;
516 | btnEdit.setOnClickListener(new OnClickListener() {
517 | @Override
518 | public void onClick(View v) {
519 | if (mOnItemClickListener!= null) {
520 | mOnItemClickListener.onEditClick(finalView, item.id);
521 | }
522 | }
523 | });
524 |
525 | } else {
526 | CompoundButton btn = holder.tb;
527 | btn.setText(item.name);
528 | btn.setChecked(item.selected);
529 | btn.setTag(item);
530 | btn.setId(holder.getItemViewType());
531 | btn.setOnClickListener(mOnClickListener);
532 | }
533 |
534 | }
535 |
536 | @Override
537 | public int getItemViewType(int position) {
538 | if (mList!=null && !mList.isEmpty()) {
539 | NewConditionItem item = mList.get(position);
540 | if (item.id == TYPE_EDIT) {
541 | return TYPE_EDIT;
542 | }
543 | }
544 | return super.getItemViewType(position);
545 | }
546 |
547 |
548 | @Override
549 | public int getItemCount() {
550 | return mList.size();
551 | }
552 |
553 | @Override
554 | public void onViewRecycled(RegionContainer.VH holder) {
555 | super.onViewRecycled(holder);
556 | CompoundButton btn = (CompoundButton) holder.tb;
557 |
558 | }
559 | }
560 |
561 | public interface OnItemClickListener {
562 | void onEditClick(View v, int viewType);
563 | }
564 |
565 | private static class VH extends RecyclerView.ViewHolder {
566 | CompoundButton tb;
567 | public VH(View itemView) {
568 | super(itemView);
569 | tb = (CompoundButton) itemView.findViewById(R.id.tb);
570 | }
571 | }
572 |
573 | private static class DividerItemDecoration extends RecyclerView.ItemDecoration {
574 |
575 | private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
576 |
577 | private Drawable mDivider;
578 |
579 | /**
580 | * Custom divider will be used
581 | */
582 | public DividerItemDecoration(Context context, int resId) {
583 | mDivider = ContextCompat.getDrawable(context, resId);
584 | }
585 |
586 | @Override
587 | public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
588 | int left = parent.getPaddingLeft();
589 | int right = parent.getWidth() - parent.getPaddingRight();
590 |
591 | int childCount = parent.getChildCount();
592 | for (int i = 0; i < childCount; i++) {
593 | View child = parent.getChildAt(i);
594 |
595 | RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
596 |
597 | int top = child.getBottom() + params.bottomMargin;
598 | int bottom = top + mDivider.getIntrinsicHeight();
599 |
600 | mDivider.setBounds(left, top, right, bottom);
601 | mDivider.draw(c);
602 | }
603 | }
604 | }
605 | }
606 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/SorterContainer.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.widget.CompoundButton;
8 | import android.widget.LinearLayout;
9 |
10 | import java.util.List;
11 |
12 | import widget.tamic.com.filterviewsipmle.R;
13 |
14 | /**
15 | * Created by tamic on 2017-08-03.
16 | *
17 | * @link {https://github.com/Tamicer/FilterBar}
18 | */
19 | public class SorterContainer extends ConditionContainer implements View.OnClickListener {
20 |
21 | public SorterContainer(Context context) {
22 | super(context);
23 | init();
24 | }
25 |
26 | public SorterContainer(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | init();
29 | }
30 |
31 | private void init() {
32 | LayoutInflater.from(getContext()).inflate(R.layout.layout_condition_sorter, this);
33 | mList = (LinearLayout) findViewById(R.id.list_condition_sorter);
34 | findViewById(R.id.blank_condition).setOnClickListener(new OnClickListener() {
35 |
36 | @Override
37 | public void onClick(View v) {
38 | mController.cancel(SorterContainer.this);
39 | }
40 | });
41 | }
42 |
43 | private NewConditionItem mRoot;
44 | private LinearLayout mList;
45 |
46 | @Override
47 | public NewConditionItem getConditionItem() {
48 | return mRoot;
49 | }
50 |
51 | @Override
52 | public NewConditionItem create(List sorterBean) {
53 |
54 | NewConditionItem sorterRoot = new NewConditionItem(null, 0, CategoryBar.SORTER_ROOT, true);
55 | sorterRoot.processor = NewConditionItem.RADIO_LIST;
56 | if (sorterBean != null) {
57 | for (BaseFilterItem item : sorterBean) {
58 | new NewConditionItem(sorterRoot, item.getId(), item.getValue());
59 | }
60 | }
61 | sorterRoot.reset();
62 | return sorterRoot;
63 | }
64 |
65 | @Override
66 | public void addContentView(View view) {
67 | addView(view);
68 | }
69 |
70 | @Override
71 | public void setConditionItem(NewConditionItem item) {
72 | mRoot = item;
73 | mList.removeAllViews();
74 | LayoutInflater inflater = LayoutInflater.from(getContext());
75 | for (NewConditionItem subItem : mRoot.subItems) {
76 | CompoundButton cb = (CompoundButton) inflater.inflate(
77 | R.layout.item_condition_1, mList, false);
78 | cb.setTag(subItem);
79 | cb.setText(subItem.name);
80 | cb.setChecked(subItem.selected);
81 | cb.setOnClickListener(this);
82 | mList.addView(cb);
83 |
84 | if (subItem != mRoot.subItems.get(mRoot.subItems.size() - 1)) {
85 | inflater.inflate(R.layout.layout_condition_divider, mList);
86 | }
87 | }
88 | }
89 |
90 | @Override
91 | public void onClick(View v) {
92 | CompoundButton cb = (CompoundButton) v;
93 | NewConditionItem item = (NewConditionItem) cb.getTag();
94 | boolean refresh = item.parent.processSubItems(item, cb.isChecked());
95 | cb.setChecked(item.selected);
96 | if (refresh) {
97 | setConditionItem(mRoot);
98 | this.postDelayed(new Runnable() {
99 |
100 | @Override
101 | public void run() {
102 | mController.confirm(SorterContainer.this);
103 | }
104 | }, 20);
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filter/UIUtil.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filter;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.ListAdapter;
9 | import android.widget.ListView;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * @link {https://github.com/Tamicer/FilterBar}
16 | */
17 | public class UIUtil {
18 |
19 | public UIUtil() {
20 | }
21 |
22 | public static int px2dip(Context context, float pxValue) {
23 | float scale = context.getResources().getDisplayMetrics().density;
24 | return (int) (pxValue / scale + 0.5F);
25 | }
26 |
27 | public static int dip2px(Context context, float dipValue) {
28 | float scale = context.getResources().getDisplayMetrics().density;
29 | return (int) (dipValue * scale + 0.5F);
30 | }
31 |
32 | public static void measureView(View child) {
33 | ViewGroup.LayoutParams p = child.getLayoutParams();
34 | if (p == null) {
35 | p = new ViewGroup.LayoutParams(-1, -2);
36 | }
37 |
38 | int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);
39 | int lpHeight = p.height;
40 | int childHeightSpec;
41 | if (lpHeight > 0) {
42 | childHeightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, 1073741824);
43 | } else {
44 | childHeightSpec = View.MeasureSpec.makeMeasureSpec(0, 0);
45 | }
46 |
47 | child.measure(childWidthSpec, childHeightSpec);
48 | }
49 |
50 | public static List getViewGroupAllLeafs(ViewGroup root) {
51 | ArrayList ret = new ArrayList();
52 | if (root.getChildCount() != 0) {
53 | for (int i = 0; i < root.getChildCount(); ++i) {
54 | try {
55 | ViewGroup e = (ViewGroup) root.getChildAt(i);
56 | ret.addAll(getViewGroupAllLeafs(e));
57 | } catch (Exception var4) {
58 | ret.add(root.getChildAt(i));
59 | }
60 | }
61 | }
62 |
63 | return ret;
64 | }
65 |
66 | public static List getViewGroupAll(ViewGroup root) {
67 | ArrayList ret = new ArrayList();
68 | if (root.getChildCount() != 0) {
69 | for (int i = 0; i < root.getChildCount(); ++i) {
70 | try {
71 | ret.add(root.getChildAt(i));
72 | ViewGroup e = (ViewGroup) root.getChildAt(i);
73 | ret.addAll(getViewGroupAll(e));
74 | } catch (Exception var4) {
75 | ret.add(root.getChildAt(i));
76 | }
77 | }
78 | }
79 |
80 | return ret;
81 | }
82 |
83 | public static Bitmap convertViewToBitmap(View view) {
84 | if (view.getLayoutParams() == null) {
85 | view.setLayoutParams(new ViewGroup.LayoutParams(-2, -2));
86 | }
87 |
88 | measureView(view);
89 | view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
90 | view.destroyDrawingCache();
91 | view.buildDrawingCache();
92 | return view.getDrawingCache();
93 | }
94 |
95 | public static int getWindowHeight(Context context) {
96 | return context.getResources().getDisplayMetrics().heightPixels;
97 | }
98 |
99 | public static int getWindowWidth(Context context) {
100 | return context.getResources().getDisplayMetrics().widthPixels;
101 | }
102 |
103 | public static float getWindowDensity(Context context) {
104 | return context.getResources().getDisplayMetrics().density;
105 | }
106 |
107 | public static int getListViewMesureHeight(ListView lv) {
108 | int height = 0;
109 |
110 | try {
111 | ListAdapter la = lv.getAdapter();
112 | int count = la.getCount();
113 |
114 | for (int i = 0; i < count; ++i) {
115 | View listItem = la.getView(i, (View) null, lv);
116 | listItem.measure(View.MeasureSpec.makeMeasureSpec(0, 0), View.MeasureSpec.makeMeasureSpec(0, 0));
117 | height += listItem.getMeasuredHeight();
118 | }
119 |
120 | height += lv.getDividerHeight() * (count - 1);
121 | } catch (Exception var6) {
122 | ;
123 | }
124 |
125 | return height;
126 | }
127 |
128 | public static float px2sp(Context context, float px) {
129 | float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
130 | return px / scaledDensity;
131 | }
132 |
133 | public static float sp2px(Context context, float sp) {
134 | float scaledDensity = context.getResources().getDisplayMetrics().scaledDensity;
135 | return sp * scaledDensity;
136 | }
137 |
138 | public static View getFirstChildView(Activity activity) {
139 | return ((ViewGroup) ((ViewGroup) activity.getWindow().getDecorView().findViewById(16908290)).getChildAt(0)).getChildAt(0);
140 | }
141 | }
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filterviewsipmle/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filterviewsipmle;
2 |
3 | import android.content.Context;
4 | import android.net.Uri;
5 | import android.os.Bundle;
6 | import android.support.design.widget.FloatingActionButton;
7 | import android.support.design.widget.Snackbar;
8 | import android.support.v7.app.AppCompatActivity;
9 | import android.support.v7.widget.Toolbar;
10 | import android.util.Log;
11 | import android.view.View;
12 | import android.widget.Toast;
13 |
14 | import com.alibaba.fastjson.JSON;
15 | import com.alibaba.fastjson.TypeReference;
16 | import com.google.gson.Gson;
17 | import com.google.gson.reflect.TypeToken;
18 | import com.tamic.widget.filter.BaseFilterItem;
19 | import com.tamic.widget.filter.CategoryBar;
20 | import com.tamic.widget.filter.ConditionContainer;
21 | import com.tamic.widget.filter.DateSelectConditionItem;
22 | import com.tamic.widget.filter.FilterContainer;
23 | import com.tamic.widget.filter.FliterResultItem;
24 | import com.tamic.widget.filter.GroupFilterItem;
25 | import com.tamic.widget.filter.ListFilterBean;
26 | import com.tamic.widget.filter.NewConditionItem;
27 | import com.tamic.widget.filter.RegionContainer;
28 | import com.tamic.widget.filter.SorterContainer;
29 |
30 | import java.io.BufferedReader;
31 | import java.io.IOException;
32 | import java.io.InputStream;
33 | import java.io.InputStreamReader;
34 | import java.util.ArrayList;
35 | import java.util.List;
36 | import java.util.Map;
37 |
38 | import widget.tamic.com.filterviewsipmle.R;
39 |
40 |
41 | /**
42 | * Created by TAMIC on 2017-07-27
43 | */
44 | public class MainActivity extends AppCompatActivity {
45 |
46 | private CategoryBar mfilterView;
47 | protected NewConditionItem mRegionRoot;
48 | protected NewConditionItem mFilterRoot;
49 | protected NewConditionItem mSortRoot;
50 |
51 | @Override
52 | protected void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | setContentView(R.layout.activity_main);
55 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
56 | setSupportActionBar(toolbar);
57 | mfilterView = (CategoryBar) findViewById(R.id.ablwf_filter_cfv);
58 | initFilterView();
59 | setFilterData();
60 | }
61 |
62 |
63 | public void initFilterView() {
64 | mfilterView.setFristTabText("地区");
65 | // mfilterView.addFristContainer(new SorterContainer(MainActivity.this));
66 | mfilterView.setSorterShow(true);
67 | mfilterView.setThreeTabText("默认排序");
68 | mfilterView.setOnConfirmListener(new CategoryBar.ControllerListener() {
69 |
70 | @Override
71 | public void onConfirm(ConditionContainer container) {
72 |
73 | if (container == mfilterView.getRegionContainer()) {
74 | mRegionRoot = container.getConditionItem();
75 | } else if (container == mfilterView.getFilterContainer()) {
76 | mFilterRoot = container.getConditionItem();
77 | }
78 |
79 | onFilterHandleResult(container);
80 | }
81 |
82 | @Override
83 | public void onOpen(ConditionContainer container) {
84 |
85 | if (container == mfilterView.getRegionContainer()) {
86 | if (mRegionRoot == null) {
87 | return;
88 | }
89 | container.setConditionItem(mRegionRoot.clone());
90 | } else if (container == mfilterView.getFilterContainer()) {
91 | if (mFilterRoot == null) {
92 | return;
93 | }
94 | container.setConditionItem(mFilterRoot.clone());
95 | }
96 | }
97 |
98 | @Override
99 | public void onCancel(ConditionContainer container) {
100 |
101 | }
102 |
103 | @Override
104 | public void onSpecial(ConditionContainer container, int id) {
105 |
106 |
107 | }
108 | });
109 | }
110 |
111 | private void onFilterHandleResult(ConditionContainer container) {
112 |
113 | FliterResultItem item = new FliterResultItem();
114 |
115 | if (container instanceof SorterContainer) {
116 | mSortRoot = container.getConditionItem();
117 | NewConditionItem lv0 = mSortRoot.firstSelectedSubItem();
118 | if (lv0.isEmpty()) {
119 | return;
120 | }
121 | onResult(item.createResult(lv0));
122 | }
123 |
124 | if (container instanceof FilterContainer) {
125 | mFilterRoot = container.getConditionItem();
126 |
127 | List lv0 = mFilterRoot.selectedSubItems();
128 | if (lv0.isEmpty()) {
129 | return;
130 | }
131 | onResult(item.createResult(mFilterRoot));
132 | }
133 |
134 | if (container instanceof RegionContainer) {
135 | mRegionRoot = container.getConditionItem();
136 | if (mRegionRoot.selected) {
137 | onResult(item.createResult(mRegionRoot));
138 | }
139 | }
140 | }
141 |
142 |
143 |
144 | protected void onFilterResult(ConditionContainer container) {
145 |
146 | NewConditionItem mRegionRoot;
147 | NewConditionItem mFilterRoot;
148 | NewConditionItem mSortRoot;
149 | if (container == mfilterView.getRegionContainer()) {
150 | mRegionRoot = container.getConditionItem();
151 | NewConditionItem lv0 = mRegionRoot.firstSelectedSubItem();
152 | if (lv0.isEmpty()) {
153 | return;
154 | }
155 |
156 | return;
157 |
158 | } else if (container == mfilterView.getSorterContainer()) {
159 | mSortRoot = container.getConditionItem();
160 | NewConditionItem lv0 = mSortRoot.firstSelectedSubItem();
161 | if (lv0.isEmpty()) {
162 | return;
163 | }
164 |
165 | return;
166 | } else if (container == mfilterView.getFilterContainer()) {
167 | mFilterRoot = container.getConditionItem();
168 | NewConditionItem lv0 = mFilterRoot.subItemById(0);
169 | NewConditionItem selectprice = lv0.firstSelectedSubItem();
170 | if (!lv0.isEmpty()) {
171 | if (selectprice != null) {
172 |
173 | } else {
174 |
175 | }
176 | }
177 |
178 | NewConditionItem lv1 = mFilterRoot.subItemById(1);
179 | List select1 = lv1.selectedSubItems();
180 | if (!lv1.isEmpty()) {
181 | if (select1 != null) {
182 | for (NewConditionItem child : select1) {
183 |
184 | }
185 |
186 | } else {
187 |
188 | }
189 | }
190 |
191 | NewConditionItem lv2 = mFilterRoot.subItemById(2);
192 | NewConditionItem select2 = lv2.firstSelectedSubItem();
193 | /* if (!lv2.isEmpty()) {
194 |
195 | DateSelectConditionItem dataitem = (DateSelectConditionItem) lv2.subItemById(555);
196 | dataitem.rangeInfo.getInfo(dataitem);
197 |
198 | Toast.makeText(MainActivity.this, dataitem.getInfo(), Toast.LENGTH_SHORT).show();
199 | }*/
200 | if (select2 != null) {
201 | for (NewConditionItem child : select1) {
202 | Toast.makeText(MainActivity.this, String.valueOf(child.id), Toast.LENGTH_SHORT).show();
203 | }
204 | } else {
205 | Toast.makeText(MainActivity.this, "被重置了!", Toast.LENGTH_SHORT).show();
206 |
207 | }
208 | return;
209 | }
210 |
211 | }
212 |
213 |
214 |
215 | /**
216 | * 设置筛选数据
217 | */
218 | public void setFilterData() {
219 | //模擬數據
220 | ListFilterBean listFilterBean = new ListFilterBean();
221 |
222 | listFilterBean.region = new ListFilterBean.ItemList();
223 | listFilterBean.region.name = "地铁";
224 | listFilterBean.region.list = new ArrayList<>();
225 | listFilterBean.sort = new ListFilterBean.ItemList();
226 |
227 | listFilterBean.sort.name = "其他";
228 | listFilterBean.sort.list = new ArrayList<>();
229 | listFilterBean.layout = new ListFilterBean.ItemList();
230 | listFilterBean.layout.name = "tab2";
231 | listFilterBean.layout.list = new ArrayList<>();
232 | for (int i = 1; i < 6; i++) {
233 | ListFilterBean.Item item = new ListFilterBean.Item();
234 | item.id = i;
235 | item.name = "item" + i;
236 | listFilterBean.sort.list.add(item);
237 | }
238 |
239 | for (int i = 0; i < 8; i++) {
240 | ListFilterBean.Item item = new ListFilterBean.Item();
241 | item.children = new ArrayList<>();
242 | item.id = i;
243 | item.name = "我的" + i;
244 | for (int j = 0; j < 4; j++) {
245 | ListFilterBean.Item childitem = new ListFilterBean.Item();
246 | if (j == 0) {
247 | childitem.name = "不限";
248 | childitem.id = i * j;
249 | } else {
250 | childitem.name = "tag" + i + "-" + j;
251 | childitem.id = i * j;
252 | }
253 |
254 | item.children.add(childitem);
255 | }
256 | listFilterBean.layout.list.add(item);
257 | }
258 |
259 |
260 | for (int i = 0; i < 10; i++) {
261 | ListFilterBean.Item item = new ListFilterBean.Item();
262 | item.children = new ArrayList<>();
263 | item.id = i;
264 | item.name = "地铁" + i + "号线";
265 | for (int j = 0; j < 20; j++) {
266 | ListFilterBean.Item childitem = new ListFilterBean.Item();
267 | childitem.name = "tamic" + i + "-" + j;
268 | childitem.id = i * j;
269 | item.children.add(childitem);
270 | }
271 | listFilterBean.region.list.add(item);
272 | }
273 | ListFilterBean.Item item = new ListFilterBean.Item();
274 | item.children = new ArrayList<>();
275 | item.id = 5000;
276 | item.name = "不限";
277 | listFilterBean.region.list.add(0, item);
278 |
279 |
280 | //設置
281 | mSortRoot = getSorterRoot(listFilterBean);
282 | mfilterView.getSorterContainer().setConditionItem(mSortRoot);
283 |
284 | //区域
285 | mRegionRoot = getRegionRoot(listFilterBean);
286 | mfilterView.getRegionContainer().setConditionItem(mSortRoot);
287 |
288 | //筛选
289 | mFilterRoot = getFilterRoot(listFilterBean);
290 | mfilterView.getFilterContainer().setConditionItem(mFilterRoot);
291 |
292 | }
293 |
294 |
295 | public NewConditionItem getSorterRoot(ListFilterBean filterBean) {
296 | NewConditionItem sorterRoot = new NewConditionItem(null, 0, CategoryBar.SORTER_ROOT, true);
297 | sorterRoot.processor = NewConditionItem.RADIO_LIST;
298 | if (filterBean.sort != null) {
299 | mfilterView.setThreeTabText(filterBean.sort.name);
300 | for (ListFilterBean.Item item : filterBean.sort.list) {
301 | new NewConditionItem(sorterRoot, item.id, item.name);
302 | }
303 | }
304 | sorterRoot.reset();
305 | return sorterRoot;
306 | }
307 |
308 | public NewConditionItem getFilterRoot(ListFilterBean filterBean) {
309 | NewConditionItem filterRoot = new NewConditionItem(null, 0, CategoryBar.FILTER_ROOT, true);
310 |
311 |
312 | if (filterBean != null && filterBean.layout != null) {
313 |
314 | /* new NewConditionItem(filterRoot, 1111, "选择区间", true,
315 | NewConditionItem.TYPE_RANGE);*/
316 |
317 | for (ListFilterBean.Item item : filterBean.layout.list) {
318 | NewConditionItem createTimeItem = new NewConditionItem(filterRoot, item.id, item.name, true,
319 | NewConditionItem.TYPE_GRID);
320 | createTimeItem.canReset = false;
321 | createTimeItem.processor = NewConditionItem.DEFAULT;
322 | for (ListFilterBean.Item item1 : item.children) {
323 | new NewConditionItem(createTimeItem, item1.id, item1.name);
324 | }
325 | }
326 |
327 |
328 | }
329 | return filterRoot;
330 | }
331 |
332 | public NewConditionItem getRegionRoot(ListFilterBean filterBean) {
333 |
334 | NewConditionItem regionRoot = new NewConditionItem(null, 0, "regionRoot", true);
335 | regionRoot.processor = NewConditionItem.RADIO_LIST_NO_CLEAR;
336 | if (filterBean.region != null) {
337 | NewConditionItem lv0 = new NewConditionItem(regionRoot, 0, filterBean.region.name);
338 | lv0.processor = NewConditionItem.RADIO_LIST;
339 | for (ListFilterBean.Item item : filterBean.region.list) {
340 | NewConditionItem lv1 = new NewConditionItem(lv0, item.id, item.name);
341 | if (item.children == null || item.children.size() == 0) {
342 | continue;
343 | }
344 | lv1.processor = NewConditionItem.DEFAULT;
345 | for (ListFilterBean.Item subItem : item.children) {
346 | new NewConditionItem(lv1, subItem.id, subItem.name);
347 | }
348 | }
349 | }
350 |
351 | if (filterBean != null && filterBean.layout != null) {
352 | NewConditionItem lv0 = new NewConditionItem(regionRoot, 1, filterBean.layout.name);
353 | lv0.processor = NewConditionItem.RADIO_LIST;
354 | for (ListFilterBean.Item item : filterBean.layout.list) {
355 | NewConditionItem lv1 = new NewConditionItem(lv0, item.id, item.name);
356 | if (item.children == null || item.children.size() == 0) {
357 | continue;
358 | }
359 | lv1.processor = NewConditionItem.DEFAULT;
360 | for (ListFilterBean.Item subItem : item.children) {
361 | new NewConditionItem(lv1, subItem.id, subItem.name);
362 | }
363 | }
364 | }
365 | regionRoot.reset();
366 | return regionRoot;
367 | }
368 |
369 | public static String getFromAssets(Context context, String fileName) {
370 | BufferedReader reader = null;
371 |
372 | try {
373 | InputStream e = context.getResources().getAssets().open(fileName);
374 | reader = new BufferedReader(new InputStreamReader(e));
375 | char[] buf = new char[1024];
376 | boolean count = false;
377 | StringBuffer sb = new StringBuffer(e.available());
378 |
379 | String readData;
380 | int count1;
381 | while ((count1 = reader.read(buf)) != -1) {
382 | readData = String.valueOf(buf, 0, count1);
383 | sb.append(readData);
384 | }
385 |
386 | readData = sb.toString();
387 | return readData;
388 | } catch (Exception var11) {
389 | var11.printStackTrace();
390 | } finally {
391 | try {
392 | reader.close();
393 | } catch (IOException e) {
394 | e.printStackTrace();
395 | }
396 | }
397 |
398 | return "";
399 | }
400 |
401 | protected void onResult(FliterResultItem resultItem) {
402 |
403 | if (resultItem == null) {
404 | }
405 |
406 | if (resultItem.isEmpty()) {
407 | Log.d("Tag", "lv0: "+ resultItem.name);
408 | Toast.makeText(MainActivity.this, String.valueOf(resultItem.id), Toast.LENGTH_SHORT).show();
409 |
410 | return;
411 | }
412 |
413 | for (FliterResultItem item : resultItem.subItems()) {
414 |
415 | if (item.isEmpty()) {
416 | continue;
417 | }
418 | for (FliterResultItem item1 : item.subItems()) {
419 | Log.d("Tag", "lv1: "+ item.name);
420 | Log.d("Tag", "lv1: "+ item1.name);
421 | Toast.makeText(MainActivity.this, String.valueOf(item.id), Toast.LENGTH_SHORT).show();
422 | for (FliterResultItem item2 : item1.subItems()) {
423 | Log.d("Tag", "lv2: "+ item2.name);
424 | Toast.makeText(MainActivity.this, String.valueOf(item.id), Toast.LENGTH_SHORT).show();
425 | }
426 | }
427 | }
428 | }
429 |
430 | }
431 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/java/com/tamic/widget/filterviewsipmle/Test.java:
--------------------------------------------------------------------------------
1 | package com.tamic.widget.filterviewsipmle;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * Created by LIUYONGKUI726 on 2017-08-10.
8 | */
9 |
10 | public class Test {
11 |
12 |
13 | /**
14 | * keyName : 支付条件
15 | * value : hjjjj
16 | */
17 |
18 | private String keyName;
19 | private String value;
20 |
21 | public String getKeyName() {
22 | return keyName;
23 | }
24 |
25 | public void setKeyName(String keyName) {
26 | this.keyName = keyName;
27 | }
28 |
29 | public String getValue() {
30 | return value;
31 | }
32 |
33 | public void setValue(String value) {
34 | this.value = value;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/less.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/drawable/less.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/more_unfold.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/drawable/more_unfold.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/range_seek_bar_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/drawable/range_seek_bar_thumb.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/selector_item_condition_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
5 |
6 | -
7 |
8 |
9 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/selector_item_condition_grid_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | -
7 |
8 |
-
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | -
23 |
24 |
-
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/selector_item_condition_grid_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/selector_item_condition_text2_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/selector_item_condition_text_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/shape_btn_standard_3b4263_rectangle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/drawable/shape_list_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
26 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/content_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
19 |
20 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/item_condition_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/item_condition_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/item_condition_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/item_condition_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
12 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_category_bar_mode_brand_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
24 |
25 |
30 |
31 |
35 |
36 |
41 |
42 |
43 |
44 |
45 |
49 |
50 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_category_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_category_button_new.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_data_select.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
18 |
28 |
29 |
36 |
37 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_divider.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_filter.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
17 |
18 |
24 |
25 |
35 |
36 |
46 |
47 |
48 |
53 |
54 |
59 |
60 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_grid.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
16 |
17 |
24 |
25 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_range.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
24 |
25 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_region.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
17 |
18 |
24 |
25 |
30 |
31 |
35 |
36 |
37 |
43 |
44 |
53 |
54 |
63 |
64 |
65 |
71 |
72 |
77 |
78 |
84 |
85 |
86 |
87 |
88 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/layout/layout_condition_sorter.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
18 |
19 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values/attrs-rangeseekbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 | #f98e39
7 | #FFFFFF
8 | #BBBBBB
9 | #666666
10 |
11 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | FilterViewSipmle
3 | Settings
4 |
5 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/FilterViewSipmle/app/src/test/java/widget/tamic/com/filterviewsipmle/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package widget.tamic.com.filterviewsipmle;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/FilterViewSipmle/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.2.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/FilterViewSipmle/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Mon Jul 31 09:58:09 CST 2017
16 | systemProp.http.proxyHost=10.59.72.13
17 | org.gradle.jvmargs=-Xmx1536m
18 | systemProp.http.proxyPort=3128
19 |
--------------------------------------------------------------------------------
/FilterViewSipmle/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Tamicer/FilterBar/88d7dae23d4e029dcfc3cf64d2879e2a33e331df/FilterViewSipmle/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/FilterViewSipmle/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
7 |
--------------------------------------------------------------------------------
/FilterViewSipmle/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/FilterViewSipmle/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/FilterViewSipmle/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Tamic (码小白)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FilterBar
2 | 筛选框
3 |
--------------------------------------------------------------------------------