singleMovieList = new ArrayList<>();
12 | singleMovieList.add(
13 | new SingleMovie(
14 | "Smurfs: The Lost Village",
15 | "https://yts.ag/movie/smurfs-the-lost-village-2017",
16 | "https://yts.ag/assets/images/movies/smurfs_the_lost_village_2017/medium-cover.jpg",
17 | "Adventure",
18 | "720p",
19 | 2017,
20 | 5.8f));
21 | singleMovieList.add(
22 | new SingleMovie(
23 | "House of Strangers",
24 | "https://yts.ag/movie/house-of-strangers-1949",
25 | "https://yts.ag/assets/images/movies/house_of_strangers_1949/medium-cover.jpg",
26 | "Crime",
27 | "1080p",
28 | 1949,
29 | 7.4f));
30 | singleMovieList.add(
31 | new SingleMovie(
32 | "Bonjour Tristesse",
33 | "https://yts.ag/movie/bonjour-tristesse-1958",
34 | "https://yts.ag/assets/images/movies/bonjour_tristesse_1958/medium-cover.jpg",
35 | "Drama",
36 | "3D",
37 | 1958,
38 | 7.0f));
39 | singleMovieList.add(
40 | new SingleMovie(
41 | "Dragonwyck",
42 | "https://yts.ag/movie/dragonwyck-1946",
43 | "https://yts.ag/assets/images/movies/dragonwyck_1946/medium-cover.jpg",
44 | "Drama",
45 | "720p",
46 | 1946,
47 | 7.0f));
48 | singleMovieList.add(
49 | new SingleMovie(
50 | "Barabbas",
51 | "https://yts.ag/movie/barabbas-1961",
52 | "https://yts.ag/assets/images/movies/barabbas_1961/medium-cover.jpg",
53 | "Adventure",
54 | "1080p",
55 | 1961,
56 | 7.0f));
57 | singleMovieList.add(
58 | new SingleMovie(
59 | "Ghost in the Shell Arise: Border 4 - Ghost Stands Alone",
60 | "https://yts.ag/movie/ghost-in-the-shell-arise-border-4-ghost-stands-alone-2014",
61 | "https://yts.ag/assets/images/movies/ghost_in_the_shell_arise_border_4_ghost_stands_alone_2014/medium-cover.jpg",
62 | "Action",
63 | "3D",
64 | 2014,
65 | 7.4f));
66 | singleMovieList.add(
67 | new SingleMovie(
68 | "Ghost in the Shell Arise: Border 3 - Ghost Tears",
69 | "https://yts.ag/movie/ghost-in-the-shell-arise-border-3-ghost-tears-2014",
70 | "https://yts.ag/assets/images/movies/ghost_in_the_shell_arise_border_3_ghost_tears_2014/medium-cover.jpg",
71 | "Action",
72 | "720p",
73 | 2014,
74 | 7.3f));
75 | singleMovieList.add(
76 | new SingleMovie(
77 | "Extortion",
78 | "https://yts.ag/movie/extortion-2017",
79 | "https://yts.ag/assets/images/movies/extortion_2017/medium-cover.jpg",
80 | "Action",
81 | "1080p",
82 | 2017,
83 | 6.2f));
84 | singleMovieList.add(
85 | new SingleMovie(
86 | "Is Genesis History?",
87 | "https://yts.ag/movie/is-genesis-history-2017",
88 | "https://yts.ag/assets/images/movies/is_genesis_history_2017/medium-cover.jpg",
89 | "Documentary",
90 | "3D",
91 | 2017,
92 | 4.6f));
93 | singleMovieList.add(
94 | new SingleMovie(
95 | "Whoever Slew Auntie Roo?",
96 | "https://yts.ag/movie/whoever-slew-auntie-roo-1972",
97 | "https://yts.ag/assets/images/movies/whoever_slew_auntie_roo_1972/medium-cover.jpg",
98 | "Horror",
99 | "720p",
100 | 1972,
101 | 6.2f));
102 | singleMovieList.add(
103 | new SingleMovie(
104 | "Moontrap: Target Earth",
105 | "https://yts.ag/movie/moontrap-target-earth-2017",
106 | "https://yts.ag/assets/images/movies/moontrap_target_earth_2017/medium-cover.jpg",
107 | "Action",
108 | "1080p",
109 | 2017,
110 | 2.8f));
111 | singleMovieList.add(
112 | new SingleMovie(
113 | "Kong: Skull Island",
114 | "https://yts.ag/movie/kong-skull-island-2017",
115 | "https://yts.ag/assets/images/movies/kong_skull_island_2017/medium-cover.jpg",
116 | "Action",
117 | "3D",
118 | 2017,
119 | 6.9f));
120 | singleMovieList.add(
121 | new SingleMovie(
122 | "Trail of the Pink Panther",
123 | "https://yts.ag/movie/trail-of-the-pink-panther-1982",
124 | "https://yts.ag/assets/images/movies/trail_of_the_pink_panther_1982/medium-cover.jpg",
125 | "Comedy",
126 | "720p",
127 | 1982,
128 | 4.9f));
129 | singleMovieList.add(
130 | new SingleMovie(
131 | "The Babymoon",
132 | "https://yts.ag/movie/the-babymoon-2017",
133 | "https://yts.ag/assets/images/movies/the_babymoon_2017/medium-cover.jpg",
134 | "Action",
135 | "1080p",
136 | 2017,
137 | 4.9f));
138 | singleMovieList.add(
139 | new SingleMovie(
140 | "Rabbit Hole",
141 | "https://yts.ag/movie/rabbit-hole-2010",
142 | "https://yts.ag/assets/images/movies/rabbit_hole_2010/medium-cover.jpg",
143 | "Drama",
144 | "3D",
145 | 2010,
146 | 7.0f));
147 | singleMovieList.add(
148 | new SingleMovie(
149 | "Who'll Stop the Rain",
150 | "https://yts.ag/movie/wholl-stop-the-rain-1978",
151 | "https://yts.ag/assets/images/movies/wholl_stop_the_rain_1978/medium-cover.jpg",
152 | "Action",
153 | "720p",
154 | 1978,
155 | 6.8f));
156 | singleMovieList.add(
157 | new SingleMovie(
158 | "Revenge of the Pink Panther",
159 | "https://yts.ag/movie/revenge-of-the-pink-panther-1978",
160 | "https://yts.ag/assets/images/movies/revenge_of_the_pink_panther_1978/medium-cover.jpg",
161 | "Comedy",
162 | "1080p",
163 | 1978,
164 | 6.7f));
165 | singleMovieList.add(
166 | new SingleMovie(
167 | "Apprentice",
168 | "https://yts.ag/movie/apprentice-2016",
169 | "https://yts.ag/assets/images/movies/apprentice_2016/medium-cover.jpg",
170 | "Drama",
171 | "3D",
172 | 2016,
173 | 6.7f));
174 | singleMovieList.add(
175 | new SingleMovie(
176 | "The Food Guide to Love",
177 | "https://yts.ag/movie/the-food-guide-to-love-2013",
178 | "https://yts.ag/assets/images/movies/the_food_guide_to_love_2013/medium-cover.jpg",
179 | "Comedy",
180 | "720p",
181 | 2013,
182 | 5.8f));
183 | singleMovieList.add(
184 | new SingleMovie(
185 | "Youth in Revolt",
186 | "https://yts.ag/movie/youth-in-revolt-2009",
187 | "https://yts.ag/assets/images/movies/youth_in_revolt_2009/medium-cover.jpg",
188 | "Comedy",
189 | "1080p",
190 | 2009,
191 | 6.5f));
192 | singleMovieList.add(
193 | new SingleMovie(
194 | "Gods and Generals",
195 | "https://yts.ag/movie/gods-and-generals-2003",
196 | "https://yts.ag/assets/images/movies/gods_and_generals_2003/medium-cover.jpg",
197 | "Drama",
198 | "3D",
199 | 2003,
200 | 6.3f));
201 | singleMovieList.add(
202 | new SingleMovie(
203 | "D3: The Mighty Ducks",
204 | "https://yts.ag/movie/d3-the-mighty-ducks-1996",
205 | "https://yts.ag/assets/images/movies/d3_the_mighty_ducks_1996/medium-cover.jpg",
206 | "Action",
207 | "720p",
208 | 1996,
209 | 5.3f));
210 | singleMovieList.add(
211 | new SingleMovie(
212 | "Airport",
213 | "https://yts.ag/movie/airport-1970",
214 | "https://yts.ag/assets/images/movies/airport_1970/medium-cover.jpg",
215 | "Action",
216 | "1080p",
217 | 1970,
218 | 6.6f));
219 | singleMovieList.add(
220 | new SingleMovie(
221 | "The Zookeeper's Wife",
222 | "https://yts.ag/movie/the-zookeepers-wife-2017",
223 | "https://yts.ag/assets/images/movies/the_zookeepers_wife_2017/medium-cover.jpg",
224 | "Biography",
225 | "3D",
226 | 2017,
227 | 7.0f));
228 | singleMovieList.add(
229 | new SingleMovie(
230 | "Evil Ed",
231 | "https://yts.ag/movie/evil-ed-1995",
232 | "https://yts.ag/assets/images/movies/evil_ed_1995/medium-cover.jpg",
233 | "Comedy",
234 | "720p",
235 | 1995,
236 | 5.5f));
237 | singleMovieList.add(
238 | new SingleMovie(
239 | "Needful Things",
240 | "https://yts.ag/movie/needful-things-1993",
241 | "https://yts.ag/assets/images/movies/needful_things_1993/medium-cover.jpg",
242 | "Crime",
243 | "1080p",
244 | 1993,
245 | 6.2f));
246 | singleMovieList.add(
247 | new SingleMovie(
248 | "Red Dog: True Blue",
249 | "https://yts.ag/movie/red-dog-true-blue-2016",
250 | "https://yts.ag/assets/images/movies/red_dog_true_blue_2016/medium-cover.jpg",
251 | "Comedy",
252 | "3D",
253 | 2016,
254 | 6.6f));
255 | singleMovieList.add(
256 | new SingleMovie(
257 | "Jawbreaker",
258 | "https://yts.ag/movie/jawbreaker-1999",
259 | "https://yts.ag/assets/images/movies/jawbreaker_1999/medium-cover.jpg",
260 | "Action",
261 | "720p",
262 | 1999,
263 | 5.5f));
264 | singleMovieList.add(
265 | new SingleMovie(
266 | "Alone in Berlin",
267 | "https://yts.ag/movie/alone-in-berlin-2016",
268 | "https://yts.ag/assets/images/movies/alone_in_berlin_2016/medium-cover.jpg",
269 | "Action",
270 | "1080p",
271 | 2016,
272 | 0.0f));
273 | singleMovieList.add(
274 | new SingleMovie(
275 | "Song to Song",
276 | "https://yts.ag/movie/song-to-song-2017",
277 | "https://yts.ag/assets/images/movies/song_to_song_2017/medium-cover.jpg",
278 | "Drama",
279 | "3D",
280 | 2017,
281 | 6.2f));
282 | singleMovieList.add(
283 | new SingleMovie(
284 | "Power Rangers",
285 | "https://yts.ag/movie/power-rangers-2017",
286 | "https://yts.ag/assets/images/movies/power_rangers_2017/medium-cover.jpg",
287 | "Action",
288 | "720p",
289 | 2017,
290 | 0.0f));
291 | singleMovieList.add(
292 | new SingleMovie(
293 | "Immortal Beloved",
294 | "https://yts.ag/movie/immortal-beloved-1994",
295 | "https://yts.ag/assets/images/movies/immortal_beloved_1994/medium-cover.jpg",
296 | "Biography",
297 | "1080p",
298 | 1994,
299 | 7.5f));
300 | singleMovieList.add(
301 | new SingleMovie(
302 | "The Eagle Huntress",
303 | "https://yts.ag/movie/the-eagle-huntress-2016",
304 | "https://yts.ag/assets/images/movies/the_eagle_huntress_2016/medium-cover.jpg",
305 | "Adventure",
306 | "3D",
307 | 2016,
308 | 7.5f));
309 | singleMovieList.add(
310 | new SingleMovie(
311 | "CHIPS",
312 | "https://yts.ag/movie/chips-2017",
313 | "https://yts.ag/assets/images/movies/chips_2017/medium-cover.jpg",
314 | "Action",
315 | "720p",
316 | 2017,
317 | 5.8f));
318 | singleMovieList.add(
319 | new SingleMovie(
320 | "Jawbone",
321 | "https://yts.ag/movie/jawbone-2017",
322 | "https://yts.ag/assets/images/movies/jawbone_2017/medium-cover.jpg",
323 | "Action",
324 | "1080p",
325 | 2017,
326 | 6.5f));
327 | singleMovieList.add(
328 | new SingleMovie(
329 | "Dragonheart: Battle for the Heartfire",
330 | "https://yts.ag/movie/dragonheart-battle-for-the-heartfire-2017",
331 | "https://yts.ag/assets/images/movies/dragonheart_battle_for_the_heartfire_2017/medium-cover.jpg",
332 | "Fantasy",
333 | "3D",
334 | 2017,
335 | 5.2f));
336 | singleMovieList.add(
337 | new SingleMovie(
338 | "Das Boot",
339 | "https://yts.ag/movie/das-boot-1981",
340 | "https://yts.ag/assets/images/movies/das_boot_1981/medium-cover.jpg",
341 | "Adventure",
342 | "720p",
343 | 1981,
344 | 8.4f));
345 | singleMovieList.add(
346 | new SingleMovie(
347 | "The Belko Experiment",
348 | "https://yts.ag/movie/the-belko-experiment-2016",
349 | "https://yts.ag/assets/images/movies/the_belko_experiment_2016/medium-cover.jpg",
350 | "Action",
351 | "1080p",
352 | 2016,
353 | 6.1f));
354 | singleMovieList.add(
355 | new SingleMovie(
356 | "Life",
357 | "https://yts.ag/movie/life-2017",
358 | "https://yts.ag/assets/images/movies/life_2017/medium-cover.jpg",
359 | "Horror",
360 | "3D",
361 | 2017,
362 | 6.7f));
363 | singleMovieList.add(
364 | new SingleMovie(
365 | "The Carer",
366 | "https://yts.ag/movie/the-carer-2016",
367 | "https://yts.ag/assets/images/movies/the_carer_2016/medium-cover.jpg",
368 | "Comedy",
369 | "720p",
370 | 2016,
371 | 6.5f));
372 | singleMovieList.add(
373 | new SingleMovie(
374 | "Altitude",
375 | "https://yts.ag/movie/altitude-2017",
376 | "https://yts.ag/assets/images/movies/altitude_2017/medium-cover.jpg",
377 | "Action",
378 | "1080p",
379 | 2017,
380 | 5.0f));
381 | singleMovieList.add(
382 | new SingleMovie(
383 | "Wilson",
384 | "https://yts.ag/movie/wilson-2017",
385 | "https://yts.ag/assets/images/movies/wilson_2017/medium-cover.jpg",
386 | "Comedy",
387 | "3D",
388 | 2017,
389 | 5.8f));
390 | singleMovieList.add(
391 | new SingleMovie(
392 | "On the Double",
393 | "https://yts.ag/movie/on-the-double-1961",
394 | "https://yts.ag/assets/images/movies/on_the_double_1961/medium-cover.jpg",
395 | "Adventure",
396 | "720p",
397 | 1961,
398 | 6.5f));
399 | singleMovieList.add(
400 | new SingleMovie(
401 | "A Date with Miss Fortune",
402 | "https://yts.ag/movie/a-date-with-miss-fortune-2015",
403 | "https://yts.ag/assets/images/movies/a_date_with_miss_fortune_2015/medium-cover.jpg",
404 | "Comedy",
405 | "1080p",
406 | 2015,
407 | 5.5f));
408 | singleMovieList.add(
409 | new SingleMovie(
410 | "Prevenge",
411 | "https://yts.ag/movie/prevenge-2016",
412 | "https://yts.ag/assets/images/movies/prevenge_2016/medium-cover.jpg",
413 | "Comedy",
414 | "3D",
415 | 2016,
416 | 6.0f));
417 | singleMovieList.add(
418 | new SingleMovie(
419 | "We Go On",
420 | "https://yts.ag/movie/we-go-on-2016",
421 | "https://yts.ag/assets/images/movies/we_go_on_2016/medium-cover.jpg",
422 | "Action",
423 | "720p",
424 | 2016,
425 | 0.0f));
426 | singleMovieList.add(
427 | new SingleMovie(
428 | "The Legend of Ben Hall",
429 | "https://yts.ag/movie/the-legend-of-ben-hall-2016",
430 | "https://yts.ag/assets/images/movies/the_legend_of_ben_hall_2016/medium-cover.jpg",
431 | "Action",
432 | "1080p",
433 | 2016,
434 | 6.0f));
435 | singleMovieList.add(
436 | new SingleMovie(
437 | "Sniper",
438 | "https://yts.ag/movie/sniper-1993",
439 | "https://yts.ag/assets/images/movies/sniper_1993/medium-cover.jpg",
440 | "Action",
441 | "3D",
442 | 1993,
443 | 0.0f));
444 | singleMovieList.add(
445 | new SingleMovie(
446 | "The Last Flight of Noah's Ark",
447 | "https://yts.ag/movie/the-last-flight-of-noahs-ark-1980",
448 | "https://yts.ag/assets/images/movies/the_last_flight_of_noahs_ark_1980/medium-cover.jpg",
449 | "Adventure",
450 | "720p",
451 | 1980,
452 | 5.8f));
453 | singleMovieList.add(
454 | new SingleMovie(
455 | "I Tawt I Taw a Puddy Tat",
456 | "https://yts.ag/movie/i-tawt-i-taw-a-puddy-tat-2011",
457 | "https://yts.ag/assets/images/movies/i_tawt_i_taw_a_puddy_tat_2011/medium-cover.jpg",
458 | "na",
459 | "1080p",
460 | 2011,
461 | 6.5f));
462 | singleMovieList.add(
463 | new SingleMovie(
464 | "I Tawt I Taw a Puddy Tat",
465 | "https://yts.ag/movie/i-tawt-i-taw-a-puddy-tat-2011",
466 | "https://yts.ag/assets/images/movies/i_tawt_i_taw_a_puddy_tat_2011/medium-cover.jpg",
467 | "Action",
468 | "1080p",
469 | 2011,
470 | 6.5f));
471 |
472 | singleMovieList.add(
473 | new SingleMovie(
474 | "Tell Me How I Die",
475 | "https://yts.ag/movie/tell-me-how-i-die-2016",
476 | "https://yts.ag/assets/images/movies/tell_me_how_i_die_2016/medium-cover.jpg",
477 | "na",
478 | "720p",
479 | 2016,
480 | 5.0f));
481 | singleMovieList.add(
482 | new SingleMovie(
483 | "12 Rounds",
484 | "https://yts.ag/movie/12-rounds-2009",
485 | "https://yts.ag/assets/images/movies/12_rounds_2009/medium-cover.jpg",
486 | "na",
487 | "1080p",
488 | 2009,
489 | 5.6f));
490 | singleMovieList.add(
491 | new SingleMovie(
492 | "I Am Heath Ledger",
493 | "https://yts.ag/movie/i-am-heath-ledger-2017",
494 | "https://yts.ag/assets/images/movies/i_am_heath_ledger_2017/medium-cover.jpg",
495 | "na",
496 | "3D",
497 | 2017,
498 | 7.4f));
499 | singleMovieList.add(
500 | new SingleMovie(
501 | "Table 19",
502 | "https://yts.ag/movie/table-19-2017",
503 | "https://yts.ag/assets/images/movies/table_19_2017/medium-cover.jpg",
504 | "na",
505 | "720p",
506 | 2017,
507 | 5.8f));
508 | singleMovieList.add(
509 | new SingleMovie(
510 | "The LEGO Batman Movie",
511 | "https://yts.ag/movie/the-lego-batman-movie-2017",
512 | "https://yts.ag/assets/images/movies/the_lego_batman_movie_2017/medium-cover.jpg",
513 | "na",
514 | "1080p",
515 | 2017,
516 | 7.4f));
517 | singleMovieList.add(
518 | new SingleMovie(
519 | "John Wick: Chapter 2",
520 | "https://yts.ag/movie/john-wick-chapter-2-2017",
521 | "https://yts.ag/assets/images/movies/john_wick_chapter_2_2017/medium-cover.jpg",
522 | "na",
523 | "3D",
524 | 2017,
525 | 7.8f));
526 | singleMovieList.add(
527 | new SingleMovie(
528 | "The Sea Shall Not Have Them",
529 | "https://yts.ag/movie/the-sea-shall-not-have-them-1954",
530 | "https://yts.ag/assets/images/movies/the_sea_shall_not_have_them_1954/medium-cover.jpg",
531 | "na",
532 | "720p",
533 | 1954,
534 | 6.5f));
535 | singleMovieList.add(
536 | new SingleMovie(
537 | "How to Murder Your Wife",
538 | "https://yts.ag/movie/how-to-murder-your-wife-1965",
539 | "https://yts.ag/assets/images/movies/how_to_murder_your_wife_1965/medium-cover.jpg",
540 | "na",
541 | "1080p",
542 | 1965,
543 | 0.0f));
544 | singleMovieList.add(
545 | new SingleMovie(
546 | "Alvarez Kelly",
547 | "https://yts.ag/movie/alvarez-kelly-1966",
548 | "https://yts.ag/assets/images/movies/alvarez_kelly_1966/medium-cover.jpg",
549 | "na",
550 | "3D",
551 | 1966,
552 | 6.4f));
553 | singleMovieList.add(
554 | new SingleMovie(
555 | "The Vagrant",
556 | "https://yts.ag/movie/the-vagrant-1992",
557 | "https://yts.ag/assets/images/movies/the_vagrant_1992/medium-cover.jpg",
558 | "na",
559 | "720p",
560 | 1992,
561 | 5.8f));
562 | singleMovieList.add(
563 | new SingleMovie(
564 | "Queen Rock Montreal & Live Aid",
565 | "https://yts.ag/movie/queen-rock-montreal-live-aid-2007",
566 | "https://yts.ag/assets/images/movies/queen_rock_montreal_live_aid_2007/medium-cover.jpg",
567 | "na",
568 | "1080p",
569 | 2007,
570 | 0.0f));
571 | singleMovieList.add(
572 | new SingleMovie(
573 | "Overboard",
574 | "https://yts.ag/movie/overboard-1987",
575 | "https://yts.ag/assets/images/movies/overboard_1987/medium-cover.jpg",
576 | "na",
577 | "3D",
578 | 1987,
579 | 6.8f));
580 | singleMovieList.add(
581 | new SingleMovie(
582 | "Peaceful Warrior",
583 | "https://yts.ag/movie/peaceful-warrior-2006",
584 | "https://yts.ag/assets/images/movies/peaceful_warrior_2006/medium-cover.jpg",
585 | "na",
586 | "720p",
587 | 2006,
588 | 7.3f));
589 | singleMovieList.add(
590 | new SingleMovie(
591 | "The Axe Murders of Villisca",
592 | "https://yts.ag/movie/the-axe-murders-of-villisca-2016",
593 | "https://yts.ag/assets/images/movies/the_axe_murders_of_villisca_2016/medium-cover.jpg",
594 | "na",
595 | "1080p",
596 | 2016,
597 | 4.3f));
598 | singleMovieList.add(
599 | new SingleMovie(
600 | "Viking Legacy",
601 | "https://yts.ag/movie/viking-legacy-2016",
602 | "https://yts.ag/assets/images/movies/viking_legacy_2016/medium-cover.jpg",
603 | "na",
604 | "3D",
605 | 2016,
606 | 2.6f));
607 | singleMovieList.add(
608 | new SingleMovie(
609 | "Child of Satan",
610 | "https://yts.ag/movie/child-of-satan-2017",
611 | "https://yts.ag/assets/images/movies/child_of_satan_2017/medium-cover.jpg",
612 | "na",
613 | "720p",
614 | 2017,
615 | 2.1f));
616 | singleMovieList.add(
617 | new SingleMovie(
618 | "Voice from the Stone",
619 | "https://yts.ag/movie/voice-from-the-stone-2017",
620 | "https://yts.ag/assets/images/movies/voice_from_the_stone_2017/medium-cover.jpg",
621 | "na",
622 | "1080p",
623 | 2017,
624 | 5.3f));
625 | singleMovieList.add(
626 | new SingleMovie(
627 | "The Last Word",
628 | "https://yts.ag/movie/the-last-word-2017",
629 | "https://yts.ag/assets/images/movies/the_last_word_2017/medium-cover.jpg",
630 | "na",
631 | "3D",
632 | 2017,
633 | 6.5f));
634 | singleMovieList.add(
635 | new SingleMovie(
636 | "Swallows and Amazons",
637 | "https://yts.ag/movie/swallows-and-amazons-2016",
638 | "https://yts.ag/assets/images/movies/swallows_and_amazons_2016/medium-cover.jpg",
639 | "na",
640 | "720p",
641 | 2016,
642 | 6.2f));
643 | singleMovieList.add(
644 | new SingleMovie(
645 | "A Cure for Wellness",
646 | "https://yts.ag/movie/a-cure-for-wellness-2016",
647 | "https://yts.ag/assets/images/movies/a_cure_for_wellness_2016/medium-cover.jpg",
648 | "na",
649 | "1080p",
650 | 2016,
651 | 6.5f));
652 | singleMovieList.add(
653 | new SingleMovie(
654 | "McLaren",
655 | "https://yts.ag/movie/mclaren-2017",
656 | "https://yts.ag/assets/images/movies/mclaren_2016/medium-cover.jpg",
657 | "na",
658 | "3D",
659 | 2017,
660 | 0.0f));
661 | singleMovieList.add(
662 | new SingleMovie(
663 | "The Ticket",
664 | "https://yts.ag/movie/the-ticket-2016",
665 | "https://yts.ag/assets/images/movies/the_ticket_2016/medium-cover.jpg",
666 | "na",
667 | "720p",
668 | 2016,
669 | 5.3f));
670 | singleMovieList.add(
671 | new SingleMovie(
672 | "Limelight",
673 | "https://yts.ag/movie/limelight-1952",
674 | "https://yts.ag/assets/images/movies/limelight_1952/medium-cover.jpg",
675 | "na",
676 | "1080p",
677 | 1952,
678 | 8.1f));
679 | singleMovieList.add(
680 | new SingleMovie(
681 | "Bonded by Blood 2",
682 | "https://yts.ag/movie/bonded-by-blood-2-2017",
683 | "https://yts.ag/assets/images/movies/bonded_by_blood_2_2017/medium-cover.jpg",
684 | "na",
685 | "3D",
686 | 2017,
687 | 7.4f));
688 | singleMovieList.add(
689 | new SingleMovie(
690 | "T2 Trainspotting",
691 | "https://yts.ag/movie/t2-trainspotting-2017",
692 | "https://yts.ag/assets/images/movies/t2_trainspotting_2017/medium-cover.jpg",
693 | "na",
694 | "720p",
695 | 2017,
696 | 7.4f));
697 | singleMovieList.add(
698 | new SingleMovie(
699 | "The Last Face",
700 | "https://yts.ag/movie/the-last-face-2016",
701 | "https://yts.ag/assets/images/movies/the_last_face_2016/medium-cover.jpg",
702 | "na",
703 | "1080p",
704 | 2016,
705 | 3.9f));
706 | singleMovieList.add(
707 | new SingleMovie(
708 | "The Assignment",
709 | "https://yts.ag/movie/the-assignment-2016",
710 | "https://yts.ag/assets/images/movies/the_assignment_2016/medium-cover.jpg",
711 | "na",
712 | "3D",
713 | 2016,
714 | 4.5f));
715 | singleMovieList.add(
716 | new SingleMovie(
717 | "Aftermath",
718 | "https://yts.ag/movie/aftermath-2017",
719 | "https://yts.ag/assets/images/movies/aftermath_2017/medium-cover.jpg",
720 | "na",
721 | "720p",
722 | 2017,
723 | 5.7f));
724 | singleMovieList.add(
725 | new SingleMovie(
726 | "Night of Something Strange",
727 | "https://yts.ag/movie/night-of-something-strange-2016",
728 | "https://yts.ag/assets/images/movies/night_of_something_strange_2016/medium-cover.jpg",
729 | "na",
730 | "1080p",
731 | 2016,
732 | 4.8f));
733 | singleMovieList.add(
734 | new SingleMovie(
735 | "Molot",
736 | "https://yts.ag/movie/molot-2016",
737 | "https://yts.ag/assets/images/movies/molot_2016/medium-cover.jpg",
738 | "na",
739 | "3D",
740 | 2016,
741 | 4.7f));
742 | singleMovieList.add(
743 | new SingleMovie(
744 | "The Devil's Candy",
745 | "https://yts.ag/movie/the-devils-candy-2015",
746 | "https://yts.ag/assets/images/movies/the_devils_candy_2015/medium-cover.jpg",
747 | "na",
748 | "720p",
749 | 2015,
750 | 6.5f));
751 | singleMovieList.add(
752 | new SingleMovie(
753 | "Teen Witch",
754 | "https://yts.ag/movie/teen-witch-1989",
755 | "https://yts.ag/assets/images/movies/teen_witch_1989/medium-cover.jpg",
756 | "na",
757 | "1080p",
758 | 1989,
759 | 6.2f));
760 | singleMovieList.add(
761 | new SingleMovie(
762 | "Off Piste",
763 | "https://yts.ag/movie/off-piste-2016",
764 | "https://yts.ag/assets/images/movies/off_piste_2016/medium-cover.jpg",
765 | "na",
766 | "3D",
767 | 2016,
768 | 4.4f));
769 | singleMovieList.add(
770 | new SingleMovie(
771 | "Ana-ta-han",
772 | "https://yts.ag/movie/ana-ta-han-1953",
773 | "https://yts.ag/assets/images/movies/ana_ta_han_1953/medium-cover.jpg",
774 | "na",
775 | "720p",
776 | 1953,
777 | 7.5f));
778 | singleMovieList.add(
779 | new SingleMovie(
780 | "Bang Bang Baby",
781 | "https://yts.ag/movie/bang-bang-baby-2014",
782 | "https://yts.ag/assets/images/movies/bang_bang_baby_2014/medium-cover.jpg",
783 | "na",
784 | "1080p",
785 | 2014,
786 | 5.0f));
787 | singleMovieList.add(
788 | new SingleMovie(
789 | "Logan",
790 | "https://yts.ag/movie/logan-2017",
791 | "https://yts.ag/assets/images/movies/logan_2017/medium-cover.jpg",
792 | "na",
793 | "3D",
794 | 2017,
795 | 8.3f));
796 | singleMovieList.add(
797 | new SingleMovie(
798 | "Rita, Sue and Bob Too",
799 | "https://yts.ag/movie/rita-sue-and-bob-too-1987",
800 | "https://yts.ag/assets/images/movies/rita_sue_and_bob_too_1987/medium-cover.jpg",
801 | "na",
802 | "720p",
803 | 1987,
804 | 6.5f));
805 | singleMovieList.add(
806 | new SingleMovie(
807 | "MacArthur",
808 | "https://yts.ag/movie/macarthur-1977",
809 | "https://yts.ag/assets/images/movies/macarthur_1977/medium-cover.jpg",
810 | "na",
811 | "1080p",
812 | 1977,
813 | 6.6f));
814 | singleMovieList.add(
815 | new SingleMovie(
816 | "King Arthur and the Knights of the Round Table",
817 | "https://yts.ag/movie/king-arthur-and-the-knights-of-the-round-table-2017",
818 | "https://yts.ag/assets/images/movies/king_arthur_and_the_knights_of_the_round_table_2017/medium-cover.jpg",
819 | "na",
820 | "3D",
821 | 2017,
822 | 2.5f));
823 | singleMovieList.add(
824 | new SingleMovie(
825 | "Albion: The Enchanted Stallion",
826 | "https://yts.ag/movie/albion-the-enchanted-stallion-2016",
827 | "https://yts.ag/assets/images/movies/albion_the_enchanted_stallion_2016/medium-cover.jpg",
828 | "na",
829 | "720p",
830 | 2016,
831 | 4.8f));
832 | singleMovieList.add(
833 | new SingleMovie(
834 | "The Comedian",
835 | "https://yts.ag/movie/the-comedian-2016",
836 | "https://yts.ag/assets/images/movies/the_comedian_2016/medium-cover.jpg",
837 | "na",
838 | "1080p",
839 | 2016,
840 | 0.0f));
841 | singleMovieList.add(
842 | new SingleMovie(
843 | "Kill'em All",
844 | "https://yts.ag/movie/killem-all-2017",
845 | "https://yts.ag/assets/images/movies/killem_all_2017/medium-cover.jpg",
846 | "na",
847 | "3D",
848 | 2017,
849 | 4.2f));
850 | singleMovieList.add(
851 | new SingleMovie(
852 | "M.S. Dhoni: The Untold Story",
853 | "https://yts.ag/movie/m-s-dhoni-the-untold-story-2016",
854 | "https://yts.ag/assets/images/movies/m_s_dhoni_the_untold_story_2016/medium-cover.jpg",
855 | "na",
856 | "720p",
857 | 2016,
858 | 7.8f));
859 | singleMovieList.add(
860 | new SingleMovie(
861 | "Knucklebones",
862 | "https://yts.ag/movie/knucklebones-2016",
863 | "https://yts.ag/assets/images/movies/knucklebones_2016/medium-cover.jpg",
864 | "na",
865 | "1080p",
866 | 2016,
867 | 3.8f));
868 | singleMovieList.add(
869 | new SingleMovie(
870 | "Beauty and the Beast",
871 | "https://yts.ag/movie/beauty-and-the-beast-2017",
872 | "https://yts.ag/assets/images/movies/beauty_and_the_beast_2017/medium-cover.jpg",
873 | "na",
874 | "3D",
875 | 2017,
876 | 7.5f));
877 | singleMovieList.add(
878 | new SingleMovie(
879 | "The Mephisto Waltz",
880 | "https://yts.ag/movie/the-mephisto-waltz-1971",
881 | "https://yts.ag/assets/images/movies/the_mephisto_waltz_1971/medium-cover.jpg",
882 | "na",
883 | "720p",
884 | 1971,
885 | 6.0f));
886 | singleMovieList.add(
887 | new SingleMovie(
888 | "The Goose Steps Out",
889 | "https://yts.ag/movie/the-goose-steps-out-1942",
890 | "https://yts.ag/assets/images/movies/the_goose_steps_out_1942/medium-cover.jpg",
891 | "na",
892 | "1080p",
893 | 1942,
894 | 7.0f));
895 | singleMovieList.add(
896 | new SingleMovie(
897 | "The California Kid",
898 | "https://yts.ag/movie/the-california-kid-1974",
899 | "https://yts.ag/assets/images/movies/the_california_kid_1974/medium-cover.jpg",
900 | "na",
901 | "3D",
902 | 1974,
903 | 6.6f));
904 | singleMovieList.add(
905 | new SingleMovie(
906 | "My Cousin Vinny",
907 | "https://yts.ag/movie/my-cousin-vinny-1992",
908 | "https://yts.ag/assets/images/movies/my_cousin_vinny_1992/medium-cover.jpg",
909 | "na",
910 | "720p",
911 | 1992,
912 | 7.5f));
913 | singleMovieList.add(
914 | new SingleMovie(
915 | "Mean Dreams",
916 | "https://yts.ag/movie/mean-dreams-2016",
917 | "https://yts.ag/assets/images/movies/mean_dreams_2016/medium-cover.jpg",
918 | "na",
919 | "1080p",
920 | 2016,
921 | 6.3f));
922 |
923 | return new MovieData(singleMovieList);
924 | }
925 | }
926 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/chip_selected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/chip_unselected.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/done.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_filter.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/refresh.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/states_fab_button.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_fragment_example.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
21 |
22 |
23 |
24 |
29 |
41 |
42 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main_sample.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
21 |
22 |
29 |
30 |
36 |
37 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/filter_sample_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
24 |
25 |
34 |
35 |
44 |
45 |
46 |
54 |
55 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/filter_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
34 |
35 |
43 |
44 |
45 |
46 |
53 |
54 |
62 |
63 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_example.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
18 |
19 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/single_chip.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/single_movie.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
20 |
21 |
25 |
26 |
32 |
33 |
39 |
40 |
51 |
52 |
57 |
62 |
71 |
81 |
82 |
87 |
96 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/view_filters_sorters.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #000
4 | #000
5 | #000
6 | #f5f5f5
7 | #464756
8 |
9 | #3f51b5
10 | #303f9f
11 | #ff4081
12 | #c2185b
13 | #b3e5fc
14 |
15 | #ff5722
16 | #795548
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 12dp
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | FabulousFilterSample
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/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 | google()
6 | mavenCentral()
7 | maven { url "https://maven.google.com" }
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:7.2.1'
11 | // NOTE: Do not place your application dependencies here; they belong
12 | // in the individual module build.gradle files
13 | }
14 | }
15 |
16 | plugins {
17 | id("io.github.gradle-nexus.publish-plugin") version "1.0.0"
18 | }
19 |
20 | group = "io.github.krupen"
21 |
22 | allprojects {
23 | repositories {
24 | google()
25 | mavenCentral()
26 | maven { url "https://maven.google.com" }
27 | }
28 | }
29 |
30 | nexusPublishing {
31 | repositories {
32 | sonatype {
33 | username = ossrhUsername
34 | password = ossrhPassword
35 | nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
36 | snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
37 | }
38 | }
39 | }
40 |
41 | task clean(type: Delete) {
42 | delete rootProject.buildDir
43 | }
44 |
--------------------------------------------------------------------------------
/concept.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/concept.gif
--------------------------------------------------------------------------------
/fabulousfilter/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/fabulousfilter/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | ext {
4 | PUBLISH_GROUP_ID = 'io.github.krupen'
5 | PUBLISH_VERSION = '0.0.6'
6 | PUBLISH_ARTIFACT_ID = 'fabulousfilter'
7 | PUBLISH_DESCRIPTION = 'FabulousFilter Android SDK'
8 | PUBLISH_URL = 'https://github.com/krupen/FabulousFilter'
9 | PUBLISH_LICENSE_NAME = 'Apache License'
10 | PUBLISH_LICENSE_URL =
11 | 'https://github.com/Krupen/FabulousFilter#license'
12 | PUBLISH_DEVELOPER_ID = 'krupen'
13 | PUBLISH_DEVELOPER_NAME = 'Krupen Ghetiya'
14 | PUBLISH_DEVELOPER_EMAIL = 'krupen.ghetiya@gmail.com'
15 | PUBLISH_SCM_CONNECTION =
16 | 'scm:git:github.com/krupen/FabulousFilter.git'
17 | PUBLISH_SCM_DEVELOPER_CONNECTION =
18 | 'scm:git:ssh://github.com/krupen/FabulousFilter.git'
19 | PUBLISH_SCM_URL =
20 | 'https://github.com/krupen/FabulousFilter/tree/master'
21 | }
22 |
23 | apply from: "${rootProject.projectDir}/scripts/publish-module.gradle"
24 |
25 | android {
26 | compileSdkVersion 33
27 |
28 | defaultConfig {
29 | minSdkVersion 15
30 | targetSdkVersion 33
31 |
32 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
33 |
34 | }
35 | buildTypes {
36 | release {
37 | minifyEnabled false
38 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
39 | }
40 | }
41 | }
42 |
43 | dependencies {
44 | implementation 'androidx.appcompat:appcompat:1.4.2'
45 | implementation 'com.google.android.material:material:1.6.1'
46 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
47 | }
48 |
49 |
50 |
--------------------------------------------------------------------------------
/fabulousfilter/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 /Users/krupenghetiya/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/AAH_ArcTranslateAnimation.java:
--------------------------------------------------------------------------------
1 | package com.allattentionhere.fabulousfilter;
2 |
3 | import android.graphics.PointF;
4 | import android.view.animation.Animation;
5 | import android.view.animation.Transformation;
6 |
7 | /** Created by krupenghetiya on 19/06/17. */
8 | public class AAH_ArcTranslateAnimation extends Animation {
9 | private final int fromXType;
10 | private final int toXType;
11 |
12 | private final int fromYType;
13 | private final int toYType;
14 |
15 | private final float fromXValue;
16 | private final float toXValue;
17 |
18 | private final float fromYValue;
19 | private final float toYValue;
20 |
21 | private PointF start;
22 | private PointF control;
23 | private PointF end;
24 |
25 | /**
26 | * Constructor to use when building a ArcTranslateAnimation from code
27 | *
28 | * @param fromXDelta Change in X coordinate to apply at the start of the animation
29 | * @param toXDelta Change in X coordinate to apply at the end of the animation
30 | * @param fromYDelta Change in Y coordinate to apply at the start of the animation
31 | * @param toYDelta Change in Y coordinate to apply at the end of the animation
32 | */
33 | public AAH_ArcTranslateAnimation(
34 | float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) {
35 | fromXValue = fromXDelta;
36 | toXValue = toXDelta;
37 | fromYValue = fromYDelta;
38 | toYValue = toYDelta;
39 |
40 | fromXType = ABSOLUTE;
41 | toXType = ABSOLUTE;
42 | fromYType = ABSOLUTE;
43 | toYType = ABSOLUTE;
44 | }
45 |
46 | /**
47 | * Constructor to use when building a ArcTranslateAnimation from code
48 | *
49 | * @param fromXType Specifies how fromXValue should be interpreted. One of Animation.ABSOLUTE,
50 | * Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
51 | * @param fromXValue Change in X coordinate to apply at the start of the animation. This value can
52 | * either be an absolute number if fromXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
53 | * otherwise.
54 | * @param toXType Specifies how toXValue should be interpreted. One of Animation.ABSOLUTE,
55 | * Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
56 | * @param toXValue Change in X coordinate to apply at the end of the animation. This value can
57 | * either be an absolute number if toXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
58 | * otherwise.
59 | * @param fromYType Specifies how fromYValue should be interpreted. One of Animation.ABSOLUTE,
60 | * Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
61 | * @param fromYValue Change in Y coordinate to apply at the start of the animation. This value can
62 | * either be an absolute number if fromYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
63 | * otherwise.
64 | * @param toYType Specifies how toYValue should be interpreted. One of Animation.ABSOLUTE,
65 | * Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT.
66 | * @param toYValue Change in Y coordinate to apply at the end of the animation. This value can
67 | * either be an absolute number if toYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
68 | * otherwise.
69 | */
70 | public AAH_ArcTranslateAnimation(
71 | int fromXType,
72 | float fromXValue,
73 | int toXType,
74 | float toXValue,
75 | int fromYType,
76 | float fromYValue,
77 | int toYType,
78 | float toYValue) {
79 |
80 | this.fromXValue = fromXValue;
81 | this.toXValue = toXValue;
82 | this.fromYValue = fromYValue;
83 | this.toYValue = toYValue;
84 |
85 | this.fromXType = fromXType;
86 | this.toXType = toXType;
87 | this.fromYType = fromYType;
88 | this.toYType = toYType;
89 | }
90 |
91 | @Override
92 | protected void applyTransformation(float interpolatedTime, Transformation t) {
93 | float dx = calcBezier(interpolatedTime, start.x, control.x, end.x);
94 | float dy = calcBezier(interpolatedTime, start.y, control.y, end.y);
95 |
96 | t.getMatrix().setTranslate(dx, dy);
97 | }
98 |
99 | @Override
100 | public void initialize(int width, int height, int parentWidth, int parentHeight) {
101 | super.initialize(width, height, parentWidth, parentHeight);
102 | float fromXDelta = resolveSize(fromXType, fromXValue, width, parentWidth);
103 | float toXDelta = resolveSize(toXType, toXValue, width, parentWidth);
104 | float fromYDelta = resolveSize(fromYType, fromYValue, height, parentHeight);
105 | float toYDelta = resolveSize(toYType, toYValue, height, parentHeight);
106 |
107 | start = new PointF(fromXDelta, fromYDelta);
108 | end = new PointF(toXDelta, toYDelta);
109 | control = new PointF(fromXDelta, toYDelta); // How to choose the
110 | // Control point(we can use the cross of the two tangents from p0,p1)
111 | }
112 |
113 | /**
114 | * Calculate the position on a quadratic bezier curve by given three points and the percentage of
115 | * time passed.
116 | *
117 | * from http://en.wikipedia.org/wiki/B%C3%A9zier_curve
118 | *
119 | * @param interpolatedTime the fraction of the duration that has passed where 0 <= time <= 1
120 | * @param p0 a single dimension of the starting point
121 | * @param p1 a single dimension of the control point
122 | * @param p2 a single dimension of the ending point
123 | */
124 | private long calcBezier(float interpolatedTime, float p0, float p1, float p2) {
125 | return Math.round(
126 | (Math.pow((1 - interpolatedTime), 2) * p0)
127 | + (2 * (1 - interpolatedTime) * interpolatedTime * p1)
128 | + (Math.pow(interpolatedTime, 2) * p2));
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/AAH_FabulousFragment.java:
--------------------------------------------------------------------------------
1 | package com.allattentionhere.fabulousfilter;
2 |
3 | import android.animation.Animator;
4 | import android.animation.AnimatorListenerAdapter;
5 | import android.annotation.SuppressLint;
6 | import android.app.Dialog;
7 | import android.content.Context;
8 | import android.content.res.ColorStateList;
9 | import android.content.res.Configuration;
10 | import android.content.res.Resources;
11 | import android.graphics.Color;
12 | import android.graphics.Point;
13 | import android.graphics.drawable.Drawable;
14 | import android.os.Build;
15 | import android.os.Bundle;
16 | import android.os.Handler;
17 |
18 | import androidx.annotation.NonNull;
19 | import androidx.coordinatorlayout.widget.CoordinatorLayout;
20 |
21 | import com.google.android.material.floatingactionbutton.FloatingActionButton;
22 |
23 | import androidx.viewpager.widget.ViewPager;
24 |
25 | import android.util.DisplayMetrics;
26 | import android.view.Display;
27 | import android.view.Gravity;
28 | import android.view.View;
29 | import android.view.ViewGroup;
30 | import android.view.WindowManager;
31 | import android.view.animation.Animation;
32 | import android.view.animation.Interpolator;
33 | import android.widget.FrameLayout;
34 |
35 | import com.allattentionhere.fabulousfilter.viewpagerbottomsheet.BottomSheetUtils;
36 | import com.allattentionhere.fabulousfilter.viewpagerbottomsheet.ViewPagerBottomSheetBehavior;
37 | import com.allattentionhere.fabulousfilter.viewpagerbottomsheet.ViewPagerBottomSheetDialog;
38 | import com.allattentionhere.fabulousfilter.viewpagerbottomsheet.ViewPagerBottomSheetDialogFragment;
39 |
40 | /** Created by krupenghetiya on 05/10/16. */
41 | public class AAH_FabulousFragment extends ViewPagerBottomSheetDialogFragment {
42 |
43 | private int fabSize = 56, fabPosY, fabPosX, fabOutsidePeekHeightBuffer;
44 | private float scaleBy = 12f;
45 | private float fabOutsideYOffset = 0f;
46 | private boolean isFabOutsidePeekHeight;
47 | private FloatingActionButton parentFab;
48 | @NonNull private DisplayMetrics metrics;
49 | private FrameLayout bottomSheet;
50 | private ViewPagerBottomSheetBehavior bottomSheetBehavior;
51 |
52 | // user params
53 | private int screenHeight, screenHeightExcludingTopBar, screenHeightExcludingTopBottomBar;
54 | private int peekHeight = 400;
55 | private int animDuration = 500;
56 | private Interpolator interpolator;
57 | private FloatingActionButton fabulousFab;
58 | private FrameLayout fabContainer;
59 | private View viewMain;
60 | private View viewGroupStatic;
61 | private Drawable fabIconResource;
62 | private View contentView;
63 | private Callbacks callbacks;
64 | private AnimationListener animationListener;
65 | private ViewPager viewPager;
66 |
67 | private final ViewPagerBottomSheetBehavior.BottomSheetCallback bottomSheetBehaviorCallback =
68 | new ViewPagerBottomSheetBehavior.BottomSheetCallback() {
69 |
70 | @Override
71 | public void onStateChanged(View bottomSheet, int newState) {
72 | switch (newState) {
73 | case ViewPagerBottomSheetBehavior.STATE_HIDDEN:
74 | if (callbacks != null) {
75 | callbacks.onResult("swiped_down");
76 | }
77 | dismiss();
78 | break;
79 | case ViewPagerBottomSheetBehavior.STATE_COLLAPSED:
80 | case ViewPagerBottomSheetBehavior.STATE_EXPANDED:
81 | ViewGroup.LayoutParams params = viewMain.getLayoutParams();
82 | params.height = ViewGroup.LayoutParams.MATCH_PARENT;
83 | viewMain.setLayoutParams(params);
84 | break;
85 | }
86 | }
87 |
88 | @Override
89 | public void onSlide(View bottomSheet, float slideOffset) {
90 | if (viewGroupStatic != null) {
91 | int range = (int) (screenHeight - (metrics.density * peekHeight));
92 | if (slideOffset > 0) {
93 | viewGroupStatic.setTranslationY((range * slideOffset) - range);
94 | } else {
95 | int peekHeightDp = (int) ((metrics.density * peekHeight));
96 | viewGroupStatic.setTranslationY((peekHeightDp * slideOffset) - range);
97 | }
98 | }
99 | }
100 | };
101 |
102 | @Override
103 | public void onStart() {
104 | super.onStart();
105 | if (getDialog() != null) {
106 | getDialog().getWindow().setWindowAnimations(R.style.dialog_animation_fade);
107 | }
108 | }
109 |
110 | @Override
111 | public void onCreate(Bundle savedInstanceState) {
112 | super.onCreate(savedInstanceState);
113 | metrics = this.getResources().getDisplayMetrics();
114 | screenHeight = getScreenHeightTopBottomBar(true, true);
115 | screenHeightExcludingTopBar = getScreenHeightTopBottomBar(false, true);
116 | screenHeightExcludingTopBottomBar = getScreenHeightTopBottomBar(false, false);
117 | }
118 |
119 | @SuppressLint("DiscouragedApi")
120 | private int getScreenHeightTopBottomBar(boolean excludeTopBar, boolean excludeBottomBar) {
121 | Context context = getContext();
122 | if (context == null) {
123 | return metrics.heightPixels;
124 | }
125 | WindowManager wm = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE));
126 | Display display = wm.getDefaultDisplay();
127 | Point screenSize = new Point();
128 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
129 | display.getRealSize(screenSize);
130 | } else {
131 | display.getSize(screenSize);
132 | }
133 | int total = screenSize.y;
134 | final Resources resources = context.getResources();
135 | if (excludeBottomBar) {
136 | int navBarResourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
137 | int bottomBarHeight = 0;
138 | if (navBarResourceId > 0) {
139 | bottomBarHeight = resources.getDimensionPixelSize(navBarResourceId);
140 | }
141 | total -= bottomBarHeight;
142 | }
143 | if (excludeTopBar) {
144 | int topBarHeight;
145 | final int statusBarResourceId =
146 | resources.getIdentifier("status_bar_height", "dimen", "android");
147 | if (statusBarResourceId > 0) {
148 | topBarHeight = resources.getDimensionPixelSize(statusBarResourceId);
149 | } else {
150 | topBarHeight =
151 | (int)
152 | Math.ceil(
153 | (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? 24 : 25) * metrics.density);
154 | }
155 | total -= topBarHeight;
156 | }
157 |
158 | return total;
159 | }
160 |
161 | @SuppressLint("RestrictedApi")
162 | @Override
163 | public void setupDialog(@NonNull Dialog dialog, int style) {
164 | super.setupDialog(dialog, style);
165 | if (viewPager != null) {
166 | BottomSheetUtils.setupViewPager(viewPager);
167 | }
168 |
169 | dialog.setContentView(contentView);
170 |
171 | int[] location = new int[2];
172 | parentFab.getLocationInWindow(location);
173 | int x = location[0];
174 | int y = location[1];
175 |
176 | fabSize = parentFab.getHeight();
177 | fabOutsidePeekHeightBuffer = (int) (4 * metrics.density);
178 | fabPosY = y;
179 | fabPosX = x;
180 | fabIconResource = parentFab.getDrawable();
181 | ColorStateList fabBackgroundColorResource = parentFab.getBackgroundTintList();
182 |
183 | ((View) contentView.getParent())
184 | .setBackgroundColor(getResources().getColor(android.R.color.transparent));
185 |
186 | bottomSheetBehavior = ViewPagerBottomSheetBehavior.from(((View) contentView.getParent()));
187 | bottomSheetBehavior.setBottomSheetCallback(bottomSheetBehaviorCallback);
188 | if ((fabPosY - (metrics.heightPixels - (metrics.density * peekHeight))) <= 0) {
189 | isFabOutsidePeekHeight = true;
190 | bottomSheetBehavior.setPeekHeight(
191 | metrics.heightPixels - fabPosY + fabSize / 2 + fabOutsidePeekHeightBuffer);
192 | fabOutsideYOffset =
193 | metrics.heightPixels
194 | - fabPosY
195 | + (float) fabSize / 2
196 | + fabOutsidePeekHeightBuffer
197 | - (metrics.density * peekHeight);
198 | } else {
199 | bottomSheetBehavior.setPeekHeight((int) (metrics.density * peekHeight));
200 | }
201 | contentView.requestLayout();
202 | dialog.setOnShowListener(
203 | dialog1 -> {
204 | ViewPagerBottomSheetDialog viewPagerBottomSheetDialog =
205 | (ViewPagerBottomSheetDialog) dialog1;
206 | bottomSheet =
207 | viewPagerBottomSheetDialog.findViewById(
208 | com.google.android.material.R.id.design_bottom_sheet);
209 | if (bottomSheet != null) {
210 | ViewPagerBottomSheetBehavior.from(bottomSheet)
211 | .setState(ViewPagerBottomSheetBehavior.STATE_COLLAPSED);
212 | }
213 | if (viewGroupStatic != null) {
214 | int range = (int) (screenHeight - (metrics.density * peekHeight));
215 |
216 | viewGroupStatic.setTranslationY(-range);
217 | }
218 | int screenHeightToUse =
219 | getContext() != null && isSystemBarOnBottom(getContext(), metrics)
220 | ? screenHeightExcludingTopBar
221 | : screenHeightExcludingTopBottomBar;
222 | int fabRangeY = (int) (fabPosY - (screenHeightToUse - (metrics.density * peekHeight)));
223 | fabulousFab.setY(fabRangeY + fabOutsideYOffset);
224 | fabulousFab.setX(fabPosX);
225 | viewMain.setVisibility(View.INVISIBLE);
226 | fabAnim();
227 | });
228 |
229 | CoordinatorLayout.LayoutParams params =
230 | (CoordinatorLayout.LayoutParams) ((View) contentView.getParent()).getLayoutParams();
231 | CoordinatorLayout.Behavior behavior = params.getBehavior();
232 |
233 | if (behavior instanceof ViewPagerBottomSheetBehavior) {
234 | ((ViewPagerBottomSheetBehavior) behavior).setBottomSheetCallback(bottomSheetBehaviorCallback);
235 | }
236 |
237 | scaleBy = (float) (peekHeight * 1.6 / fabSize) * metrics.density;
238 | fabulousFab = contentView.findViewWithTag("aah_fab");
239 | fabContainer = contentView.findViewWithTag("aah_fl");
240 | int newfabsize = fabSize;
241 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
242 | int elevation = (int) Math.floor(parentFab.getCompatElevation() / 2);
243 | newfabsize = (int) (fabSize - (metrics.density * (18 + (6 * elevation))));
244 | scaleBy = (float) (peekHeight * 2 / newfabsize) * metrics.density;
245 | }
246 |
247 | final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(newfabsize, newfabsize);
248 | lp.gravity = Gravity.CENTER;
249 | fabulousFab.setLayoutParams(lp);
250 | fabulousFab.setImageDrawable(fabIconResource);
251 | fabulousFab.setBackgroundTintList(fabBackgroundColorResource);
252 | }
253 |
254 | private static boolean isSystemBarOnBottom(Context context, DisplayMetrics metrics) {
255 | Configuration configuration = context.getResources().getConfiguration();
256 | boolean canMove =
257 | (metrics.widthPixels != metrics.heightPixels && configuration.smallestScreenWidthDp < 600);
258 | return (!canMove || metrics.widthPixels < metrics.heightPixels);
259 | }
260 |
261 | private void fabAnim() {
262 | if (animationListener != null) {
263 | animationListener.onOpenAnimationStart();
264 | }
265 | AAH_ArcTranslateAnimation anim =
266 | new AAH_ArcTranslateAnimation(
267 | 0,
268 | (float) metrics.widthPixels / 2 - fabPosX - (float) (fabSize / 2),
269 | 0,
270 | -(metrics.density
271 | * ((float) (peekHeight / 2)
272 | - ((((metrics.heightPixels - fabPosY) - fabSize) / metrics.density)))));
273 | if (interpolator != null) {
274 | anim.setInterpolator(interpolator);
275 | }
276 | anim.setDuration(animDuration);
277 | anim.setAnimationListener(
278 | new Animation.AnimationListener() {
279 | @Override
280 | public void onAnimationStart(Animation animation) {
281 | if (getActivity() != null && !getActivity().isFinishing()) {
282 | parentFab.setVisibility(View.GONE);
283 | }
284 | }
285 |
286 | @Override
287 | public void onAnimationEnd(Animation animation) {
288 | fabulousFab.setImageResource(android.R.color.transparent);
289 | fabulousFab.animate().setListener(null);
290 | fabulousFab.setVisibility(View.INVISIBLE);
291 | // Do something after 100ms
292 | final Handler handler = new Handler();
293 | handler.postDelayed(
294 | new Runnable() {
295 | @Override
296 | public void run() {
297 | bottomSheetBehavior.setPeekHeight((int) (metrics.density * peekHeight));
298 | ViewPagerBottomSheetBehavior.from(bottomSheet)
299 | .setState(ViewPagerBottomSheetBehavior.STATE_COLLAPSED);
300 | if (isFabOutsidePeekHeight) {
301 | bottomSheet.requestLayout();
302 | }
303 | fabulousFab.setVisibility(View.VISIBLE);
304 | fabulousFab.setTranslationX(0f);
305 | float offsetY =
306 | -(metrics.density
307 | * ((float) (peekHeight / 2)
308 | - ((((metrics.heightPixels - fabPosY) - fabSize)
309 | / metrics.density))))
310 | - fabOutsideYOffset;
311 | fabulousFab.setTranslationY(fabulousFab.getTranslationY() + offsetY);
312 | fabulousFab.animate().setListener(null);
313 | fabulousFab
314 | .animate()
315 | .scaleXBy(scaleBy)
316 | .scaleYBy(scaleBy)
317 | .setDuration(animDuration)
318 | .setListener(
319 | new AnimatorListenerAdapter() {
320 | @Override
321 | public void onAnimationEnd(Animator animation) {
322 | super.onAnimationEnd(animation);
323 | fabulousFab.animate().setListener(null);
324 | fabulousFab.setVisibility(View.GONE);
325 | viewMain.setVisibility(View.VISIBLE);
326 | if (animationListener != null)
327 | animationListener.onOpenAnimationEnd();
328 | }
329 | });
330 | }
331 | },
332 | 100);
333 | }
334 |
335 | @Override
336 | public void onAnimationRepeat(Animation animation) {}
337 | });
338 | fabContainer.startAnimation(anim);
339 | }
340 |
341 | public void closeFilter(final Object object) {
342 | if (animationListener != null) {
343 | animationListener.onCloseAnimationStart();
344 | }
345 | if (ViewPagerBottomSheetBehavior.from(bottomSheet).getState()
346 | == ViewPagerBottomSheetBehavior.STATE_EXPANDED) {
347 | ViewPagerBottomSheetBehavior.from(bottomSheet)
348 | .setState(ViewPagerBottomSheetBehavior.STATE_COLLAPSED);
349 | }
350 | fabulousFab.setVisibility(View.VISIBLE);
351 | viewMain.setVisibility(View.INVISIBLE);
352 | fabulousFab
353 | .animate()
354 | .scaleXBy(-scaleBy)
355 | .scaleYBy(-scaleBy)
356 | .setDuration(animDuration)
357 | .setListener(
358 | new AnimatorListenerAdapter() {
359 | @Override
360 | public void onAnimationEnd(Animator animation) {
361 | super.onAnimationEnd(animation);
362 | fabulousFab.animate().setListener(null);
363 | fabulousFab.setImageDrawable(fabIconResource);
364 | if (isFabOutsidePeekHeight) {
365 | bottomSheetBehavior.setPeekHeight(
366 | metrics.heightPixels - fabPosY + fabSize / 2 + fabOutsidePeekHeightBuffer);
367 | ViewPagerBottomSheetBehavior.from(bottomSheet)
368 | .setState(ViewPagerBottomSheetBehavior.STATE_COLLAPSED);
369 | bottomSheet.requestLayout();
370 | } else {
371 | bottomSheetBehavior.setPeekHeight((int) (metrics.density * peekHeight));
372 | }
373 | float from_y, to_y;
374 | from_y = fabOutsideYOffset;
375 | to_y =
376 | (metrics.density
377 | * ((float) (peekHeight / 2)
378 | - ((((metrics.heightPixels - fabPosY) - fabSize)
379 | / metrics.density))))
380 | + fabOutsideYOffset;
381 | AAH_ArcTranslateAnimation anim =
382 | new AAH_ArcTranslateAnimation(
383 | 0,
384 | -(float) (metrics.widthPixels / 2 - fabPosX - (float) (fabSize / 2)),
385 | from_y,
386 | to_y);
387 | anim.setDuration(animDuration);
388 | if (interpolator != null) {
389 | anim.setInterpolator(interpolator);
390 | }
391 | fabContainer.startAnimation(anim);
392 | anim.setAnimationListener(
393 | new Animation.AnimationListener() {
394 | @Override
395 | public void onAnimationStart(Animation animation) {}
396 |
397 | @Override
398 | public void onAnimationEnd(Animation animation) {
399 | fabulousFab.animate().setListener(null);
400 | fabulousFab.setVisibility(View.INVISIBLE);
401 | final Handler handler = new Handler();
402 | handler.postDelayed(
403 | () -> {
404 | // Do something after 100ms
405 | if (animationListener != null)
406 | animationListener.onCloseAnimationEnd();
407 | if (callbacks != null) {
408 | callbacks.onResult(object);
409 | }
410 | dismiss();
411 | },
412 | 50);
413 | }
414 |
415 | @Override
416 | public void onAnimationRepeat(Animation animation) {}
417 | });
418 | }
419 | });
420 | }
421 |
422 | @Override
423 | public void onStop() {
424 | parentFab.setVisibility(View.VISIBLE);
425 | super.onStop();
426 | }
427 |
428 | public interface Callbacks {
429 | void onResult(Object result);
430 | }
431 |
432 | public interface AnimationListener {
433 | void onOpenAnimationStart();
434 |
435 | void onOpenAnimationEnd();
436 |
437 | void onCloseAnimationStart();
438 |
439 | void onCloseAnimationEnd();
440 | }
441 |
442 | public void setPeekHeight(int peek_height) {
443 | this.peekHeight = peek_height;
444 | }
445 |
446 | public void setViewMain(View viewMain) {
447 | this.viewMain = viewMain;
448 | }
449 |
450 | public void setViewgroupStatic(View viewGroupStatic) {
451 | this.viewGroupStatic = viewGroupStatic;
452 | }
453 |
454 | public void setMainContentView(View contentView) {
455 | this.contentView = contentView;
456 | }
457 |
458 | public void setCallbacks(Callbacks callbacks) {
459 | this.callbacks = callbacks;
460 | }
461 |
462 | public void setAnimationListener(AnimationListener animationListener) {
463 | this.animationListener = animationListener;
464 | }
465 |
466 | public void setParentFab(FloatingActionButton parentFab) {
467 | this.parentFab = parentFab;
468 | }
469 |
470 | public void setAnimationDuration(int animDuration) {
471 | this.animDuration = animDuration;
472 | }
473 |
474 | public void setInterpolator(Interpolator interpolator) {
475 | this.interpolator = interpolator;
476 | }
477 |
478 | public void setViewPager(ViewPager viewPager) {
479 | this.viewPager = viewPager;
480 | }
481 | }
482 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/AAH_FilterView.java:
--------------------------------------------------------------------------------
1 | package com.allattentionhere.fabulousfilter;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import com.google.android.material.floatingactionbutton.FloatingActionButton;
7 | import android.util.AttributeSet;
8 | import android.widget.FrameLayout;
9 |
10 | import androidx.annotation.NonNull;
11 |
12 | /** Created by krupenghetiya on 26/06/17. */
13 | public class AAH_FilterView extends FrameLayout {
14 | @NonNull FrameLayout fabContainer;
15 | @NonNull FloatingActionButton fab;
16 |
17 | public AAH_FilterView(Context context) {
18 | super(context);
19 | init();
20 | }
21 |
22 | public AAH_FilterView(Context context, AttributeSet attrs) {
23 | super(context, attrs);
24 | init();
25 | }
26 |
27 | public AAH_FilterView(Context context, AttributeSet attrs, int defStyleAttr) {
28 | super(context, attrs, defStyleAttr);
29 | init();
30 | }
31 |
32 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
33 | public AAH_FilterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
34 | super(context, attrs, defStyleAttr, defStyleRes);
35 | init();
36 | }
37 |
38 | public void init() {
39 | fabContainer = new FrameLayout(getContext());
40 | fabContainer.setTag("aah_fl");
41 | fab = new FloatingActionButton(getContext());
42 | fab.setTag("aah_fab");
43 | fab.setCompatElevation(0);
44 | fabContainer.addView(fab);
45 | this.addView(fabContainer);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/viewpagerbottomsheet/BottomSheetUtils.java:
--------------------------------------------------------------------------------
1 | package com.allattentionhere.fabulousfilter.viewpagerbottomsheet;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import androidx.coordinatorlayout.widget.CoordinatorLayout;
6 | import androidx.viewpager.widget.ViewPager;
7 |
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.view.ViewParent;
11 |
12 | public final class BottomSheetUtils {
13 |
14 | public static void setupViewPager(final @NonNull ViewPager viewPager) {
15 | final @Nullable View bottomSheetParent = findBottomSheetParent(viewPager);
16 | if (bottomSheetParent != null) {
17 | viewPager.addOnPageChangeListener(
18 | new BottomSheetViewPagerListener(viewPager, bottomSheetParent));
19 | }
20 | }
21 |
22 | private static class BottomSheetViewPagerListener extends ViewPager.SimpleOnPageChangeListener {
23 | private final @NonNull ViewPager viewPager;
24 | private final @NonNull ViewPagerBottomSheetBehavior behavior;
25 |
26 | private BottomSheetViewPagerListener(
27 | @NonNull ViewPager viewPager, @NonNull View bottomSheetParent) {
28 | this.viewPager = viewPager;
29 | this.behavior = ViewPagerBottomSheetBehavior.from(bottomSheetParent);
30 | }
31 |
32 | @Override
33 | public void onPageSelected(int position) {
34 | viewPager.post(behavior::invalidateScrollingChild);
35 | }
36 | }
37 |
38 | private static @Nullable View findBottomSheetParent(final @NonNull View view) {
39 | View current = view;
40 | while (current != null) {
41 | final ViewGroup.LayoutParams params = current.getLayoutParams();
42 | if (params instanceof CoordinatorLayout.LayoutParams
43 | && ((CoordinatorLayout.LayoutParams) params).getBehavior()
44 | instanceof ViewPagerBottomSheetBehavior) {
45 | return current;
46 | }
47 | final ViewParent parent = current.getParent();
48 | current = !(parent instanceof View) ? null : (View) parent;
49 | }
50 | return null;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/viewpagerbottomsheet/ViewPagerBottomSheetBehavior.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 The Android Open Source Project
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.allattentionhere.fabulousfilter.viewpagerbottomsheet;
18 |
19 | import android.annotation.SuppressLint;
20 | import android.content.Context;
21 | import android.content.res.TypedArray;
22 | import android.os.Parcel;
23 | import android.os.Parcelable;
24 |
25 | import androidx.annotation.NonNull;
26 | import androidx.annotation.Nullable;
27 | import androidx.coordinatorlayout.widget.CoordinatorLayout;
28 | import androidx.core.os.ParcelableCompat;
29 | import androidx.core.os.ParcelableCompatCreatorCallbacks;
30 | import androidx.customview.view.AbsSavedState;
31 | import androidx.core.view.MotionEventCompat;
32 | import androidx.core.view.NestedScrollingChild;
33 | import androidx.core.view.VelocityTrackerCompat;
34 | import androidx.core.view.ViewCompat;
35 | import androidx.viewpager.widget.ViewPager;
36 | import androidx.customview.widget.ViewDragHelper;
37 | import android.util.AttributeSet;
38 | import android.util.TypedValue;
39 | import android.view.MotionEvent;
40 | import android.view.VelocityTracker;
41 | import android.view.View;
42 | import android.view.ViewConfiguration;
43 | import android.view.ViewGroup;
44 | import android.view.ViewParent;
45 |
46 | import com.allattentionhere.fabulousfilter.R;
47 |
48 | import java.lang.ref.WeakReference;
49 |
50 | public class ViewPagerBottomSheetBehavior extends CoordinatorLayout.Behavior {
51 |
52 | /** Callback for monitoring events about bottom sheets. */
53 | public abstract static class BottomSheetCallback {
54 |
55 | public abstract void onStateChanged(View bottomSheet, int newState);
56 |
57 | public abstract void onSlide(View bottomSheet, float slideOffset);
58 | }
59 |
60 | /** The bottom sheet is dragging. */
61 | public static final int STATE_DRAGGING = 1;
62 | /** The bottom sheet is settling. */
63 | public static final int STATE_SETTLING = 2;
64 |
65 | public static final int STATE_EXPANDED = 3;
66 | public static final int STATE_COLLAPSED = 4;
67 | public static final int STATE_HIDDEN = 5;
68 |
69 | public @interface State {}
70 |
71 | public static final int PEEK_HEIGHT_AUTO = -1;
72 | private static final float HIDE_THRESHOLD = 0.5f;
73 | private static final float HIDE_FRICTION = 0.1f;
74 |
75 | private boolean hideable;
76 | private boolean ignoreEvents;
77 | private boolean skipCollapsed;
78 | private boolean peekHeightAuto;
79 | private boolean nestedScrolled;
80 | private boolean touchingScrollingChild;
81 | private int initialY;
82 | private int minOffset;
83 | private int maxOffset;
84 | private int peekHeight;
85 | private int parentHeight;
86 | private int peekHeightMin;
87 | private int activePointerId;
88 | private int lastNestedScrollDy;
89 | private int state = STATE_COLLAPSED;
90 | private float maximumVelocity;
91 | private @Nullable ViewDragHelper viewDragHelper;
92 | private @Nullable WeakReference viewRef;
93 | private @Nullable WeakReference nestedScrollingChildRef;
94 | private @Nullable BottomSheetCallback callback;
95 | private @Nullable VelocityTracker velocityTracker;
96 |
97 | public ViewPagerBottomSheetBehavior() {}
98 |
99 | @SuppressLint("PrivateResource")
100 | public ViewPagerBottomSheetBehavior(Context context, AttributeSet attrs) {
101 | super(context, attrs);
102 | TypedArray styledAttributes =
103 | context.obtainStyledAttributes(attrs, R.styleable.BottomSheetBehavior_Layout);
104 | TypedValue peekValue =
105 | styledAttributes.peekValue(R.styleable.BottomSheetBehavior_Layout_behavior_peekHeight);
106 | if (peekValue != null && peekValue.data == PEEK_HEIGHT_AUTO) {
107 | setPeekHeight(peekValue.data);
108 | } else {
109 | setPeekHeight(
110 | styledAttributes.getDimensionPixelSize(
111 | R.styleable.BottomSheetBehavior_Layout_behavior_peekHeight, PEEK_HEIGHT_AUTO));
112 | }
113 | setHideable(
114 | styledAttributes.getBoolean(
115 | R.styleable.BottomSheetBehavior_Layout_behavior_hideable, false));
116 | this.skipCollapsed =
117 | styledAttributes.getBoolean(
118 | R.styleable.BottomSheetBehavior_Layout_behavior_skipCollapsed, false);
119 | styledAttributes.recycle();
120 | ViewConfiguration configuration = ViewConfiguration.get(context);
121 | maximumVelocity = configuration.getScaledMaximumFlingVelocity();
122 | }
123 |
124 | @Override
125 | public Parcelable onSaveInstanceState(@NonNull CoordinatorLayout parent, @NonNull V child) {
126 | return new SavedState(super.onSaveInstanceState(parent, child), state);
127 | }
128 |
129 | @Override
130 | public void onRestoreInstanceState(@NonNull CoordinatorLayout parent, @NonNull V child, @NonNull Parcelable state) {
131 | SavedState savedState = (SavedState) state;
132 | super.onRestoreInstanceState(parent, child, savedState.getSuperState());
133 | // Intermediate states are restored as collapsed state
134 | if (savedState.state == STATE_DRAGGING || savedState.state == STATE_SETTLING) {
135 | this.state = STATE_COLLAPSED;
136 | } else {
137 | this.state = savedState.state;
138 | }
139 | }
140 |
141 | @SuppressLint("PrivateResource")
142 | @Override
143 | public boolean onLayoutChild(
144 | @NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) {
145 | if (ViewCompat.getFitsSystemWindows(parent) && !ViewCompat.getFitsSystemWindows(child)) {
146 | ViewCompat.setFitsSystemWindows(child, true);
147 | }
148 | int savedTop = child.getTop();
149 | // First let the parent lay it out
150 | parent.onLayoutChild(child, layoutDirection);
151 | // Offset the bottom sheet
152 | parentHeight = parent.getHeight();
153 | int peekHeight = this.peekHeight;
154 | if (peekHeightAuto) {
155 | if (peekHeightMin == 0) {
156 | peekHeightMin =
157 | parent
158 | .getResources()
159 | .getDimensionPixelSize(R.dimen.design_bottom_sheet_peek_height_min);
160 | }
161 | peekHeight = Math.max(peekHeightMin, parentHeight - parent.getWidth() * 9 / 16);
162 | }
163 | minOffset = Math.max(0, parentHeight - child.getHeight());
164 | maxOffset = Math.max(parentHeight - peekHeight, minOffset);
165 | if (state == STATE_EXPANDED) {
166 | ViewCompat.offsetTopAndBottom(child, minOffset);
167 | } else if (hideable && state == STATE_HIDDEN) {
168 | ViewCompat.offsetTopAndBottom(child, parentHeight);
169 | } else if (state == STATE_COLLAPSED) {
170 | ViewCompat.offsetTopAndBottom(child, maxOffset);
171 | } else if (state == STATE_DRAGGING || state == STATE_SETTLING) {
172 | ViewCompat.offsetTopAndBottom(child, savedTop - child.getTop());
173 | }
174 | if (viewDragHelper == null) {
175 | viewDragHelper = ViewDragHelper.create(parent, mDragCallback);
176 | }
177 | viewRef = new WeakReference<>(child);
178 | nestedScrollingChildRef = new WeakReference<>(findScrollingChild(child));
179 | return true;
180 | }
181 |
182 | @Override
183 | public boolean onInterceptTouchEvent(
184 | @NonNull CoordinatorLayout parent, V child, @NonNull MotionEvent event) {
185 | if (!child.isShown()) {
186 | ignoreEvents = true;
187 | return false;
188 | }
189 | int action = MotionEventCompat.getActionMasked(event);
190 | // Record the velocity
191 | if (action == MotionEvent.ACTION_DOWN) {
192 | reset();
193 | }
194 | if (velocityTracker == null) {
195 | velocityTracker = VelocityTracker.obtain();
196 | }
197 | velocityTracker.addMovement(event);
198 | switch (action) {
199 | case MotionEvent.ACTION_UP:
200 | case MotionEvent.ACTION_CANCEL:
201 | touchingScrollingChild = false;
202 | activePointerId = MotionEvent.INVALID_POINTER_ID;
203 | // Reset the ignore flag
204 | if (ignoreEvents) {
205 | ignoreEvents = false;
206 | return false;
207 | }
208 | break;
209 | case MotionEvent.ACTION_DOWN:
210 | int initialX = (int) event.getX();
211 | initialY = (int) event.getY();
212 | View scroll = null;
213 | if (nestedScrollingChildRef != null) {
214 | scroll = nestedScrollingChildRef.get();
215 | }
216 | if (scroll != null && parent.isPointInChildBounds(scroll, initialX, initialY)) {
217 | activePointerId = event.getPointerId(event.getActionIndex());
218 | touchingScrollingChild = true;
219 | }
220 | ignoreEvents =
221 | activePointerId == MotionEvent.INVALID_POINTER_ID
222 | && !parent.isPointInChildBounds(child, initialX, initialY);
223 | break;
224 | }
225 | if (viewDragHelper != null
226 | && !ignoreEvents
227 | && viewDragHelper.shouldInterceptTouchEvent(event)) {
228 | return true;
229 | }
230 | // We have to handle cases that the ViewDragHelper does not capture the bottom sheet because
231 | // it is not the top most view of its parent. This is not necessary when the touch event is
232 | // happening over the scrolling content as nested scrolling logic handles that case.
233 | View scroll = null;
234 | if (nestedScrollingChildRef != null) {
235 | scroll = nestedScrollingChildRef.get();
236 | }
237 | return action == MotionEvent.ACTION_MOVE
238 | && scroll != null
239 | && !ignoreEvents
240 | && state != STATE_DRAGGING
241 | && !parent.isPointInChildBounds(scroll, (int) event.getX(), (int) event.getY())
242 | && Math.abs(initialY - event.getY()) > viewDragHelper.getTouchSlop();
243 | }
244 |
245 | @Override
246 | public boolean onTouchEvent(
247 | @NonNull CoordinatorLayout parent, V child, @NonNull MotionEvent event) {
248 | if (!child.isShown()) {
249 | return false;
250 | }
251 | int action = MotionEventCompat.getActionMasked(event);
252 | if (state == STATE_DRAGGING && action == MotionEvent.ACTION_DOWN) {
253 | return true;
254 | }
255 | if (viewDragHelper == null) {
256 | viewDragHelper = ViewDragHelper.create(parent, mDragCallback);
257 | }
258 | viewDragHelper.processTouchEvent(event);
259 | // Record the velocity
260 | if (action == MotionEvent.ACTION_DOWN) {
261 | reset();
262 | }
263 | if (velocityTracker == null) {
264 | velocityTracker = VelocityTracker.obtain();
265 | }
266 | velocityTracker.addMovement(event);
267 | // The ViewDragHelper tries to capture only the top-most View. We have to explicitly tell it
268 | // to capture the bottom sheet in case it is not captured and the touch slop is passed.
269 | if (action == MotionEvent.ACTION_MOVE && !ignoreEvents) {
270 | if (Math.abs(initialY - event.getY()) > viewDragHelper.getTouchSlop()) {
271 | viewDragHelper.captureChildView(child, event.getPointerId(event.getActionIndex()));
272 | }
273 | }
274 | return !ignoreEvents;
275 | }
276 |
277 | @Override
278 | public boolean onStartNestedScroll(
279 | @NonNull CoordinatorLayout coordinatorLayout,
280 | @NonNull V child,
281 | @NonNull View directTargetChild,
282 | @NonNull View target,
283 | int nestedScrollAxes) {
284 | lastNestedScrollDy = 0;
285 | nestedScrolled = false;
286 | return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
287 | }
288 |
289 | @Override
290 | public void onNestedPreScroll(
291 | @NonNull CoordinatorLayout coordinatorLayout,
292 | @NonNull V child,
293 | @NonNull View target,
294 | int dx,
295 | int dy,
296 | @NonNull int[] consumed) {
297 | View scrollingChild = null;
298 | if (nestedScrollingChildRef != null) {
299 | scrollingChild = nestedScrollingChildRef.get();
300 | }
301 | if (target != scrollingChild) {
302 | return;
303 | }
304 | int currentTop = child.getTop();
305 | int newTop = currentTop - dy;
306 | if (dy > 0) { // Upward
307 | if (newTop < minOffset) {
308 | consumed[1] = currentTop - minOffset;
309 | ViewCompat.offsetTopAndBottom(child, -consumed[1]);
310 | setStateInternal(STATE_EXPANDED);
311 | } else {
312 | consumed[1] = dy;
313 | ViewCompat.offsetTopAndBottom(child, -dy);
314 | setStateInternal(STATE_DRAGGING);
315 | }
316 | } else if (dy < 0) { // Downward
317 | if (!ViewCompat.canScrollVertically(target, -1)) {
318 | if (newTop <= maxOffset || hideable) {
319 | consumed[1] = dy;
320 | ViewCompat.offsetTopAndBottom(child, -dy);
321 | setStateInternal(STATE_DRAGGING);
322 | } else {
323 | consumed[1] = currentTop - maxOffset;
324 | ViewCompat.offsetTopAndBottom(child, -consumed[1]);
325 | setStateInternal(STATE_COLLAPSED);
326 | }
327 | }
328 | }
329 | dispatchOnSlide(child.getTop());
330 | lastNestedScrollDy = dy;
331 | nestedScrolled = true;
332 | }
333 |
334 | @Override
335 | public void onStopNestedScroll(
336 | @NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target) {
337 | if (child.getTop() == minOffset) {
338 | setStateInternal(STATE_EXPANDED);
339 | return;
340 | }
341 | if (nestedScrollingChildRef != null
342 | && (target != nestedScrollingChildRef.get() || !nestedScrolled)) {
343 | return;
344 | }
345 | int top;
346 | int targetState;
347 | if (lastNestedScrollDy > 0) {
348 | top = minOffset;
349 | targetState = STATE_EXPANDED;
350 | } else if (hideable && shouldHide(child, getYVelocity())) {
351 | top = parentHeight;
352 | targetState = STATE_HIDDEN;
353 | } else if (lastNestedScrollDy == 0) {
354 | int currentTop = child.getTop();
355 | if (Math.abs(currentTop - minOffset) < Math.abs(currentTop - maxOffset)) {
356 | top = minOffset;
357 | targetState = STATE_EXPANDED;
358 | } else {
359 | top = maxOffset;
360 | targetState = STATE_COLLAPSED;
361 | }
362 | } else {
363 | top = maxOffset;
364 | targetState = STATE_COLLAPSED;
365 | }
366 | if (viewDragHelper != null && viewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) {
367 | setStateInternal(STATE_SETTLING);
368 | ViewCompat.postOnAnimation(child, new SettleRunnable(child, targetState));
369 | } else {
370 | setStateInternal(targetState);
371 | }
372 | nestedScrolled = false;
373 | }
374 |
375 | @Override
376 | public boolean onNestedPreFling(
377 | @NonNull CoordinatorLayout coordinatorLayout,
378 | @NonNull V child,
379 | @NonNull View target,
380 | float velocityX,
381 | float velocityY) {
382 | return nestedScrollingChildRef != null
383 | && target == nestedScrollingChildRef.get()
384 | && (state != STATE_EXPANDED
385 | || super.onNestedPreFling(coordinatorLayout, child, target, velocityX, velocityY));
386 | }
387 |
388 | public void invalidateScrollingChild() {
389 | View scrollingChild = null;
390 | if (viewRef != null) {
391 | scrollingChild = findScrollingChild(viewRef.get());
392 | }
393 | nestedScrollingChildRef = new WeakReference<>(scrollingChild);
394 | }
395 |
396 | public final void setPeekHeight(int peekHeight) {
397 | boolean layout = false;
398 | if (peekHeight == PEEK_HEIGHT_AUTO) {
399 | if (!peekHeightAuto) {
400 | peekHeightAuto = true;
401 | layout = true;
402 | }
403 | } else if (peekHeightAuto || this.peekHeight != peekHeight) {
404 | peekHeightAuto = false;
405 | this.peekHeight = Math.max(0, peekHeight);
406 | maxOffset = parentHeight - peekHeight;
407 | layout = true;
408 | }
409 | if (layout && state == STATE_COLLAPSED && viewRef != null) {
410 | V view = viewRef.get();
411 | if (view != null) {
412 | view.requestLayout();
413 | }
414 | }
415 | }
416 |
417 | public void setHideable(boolean hideable) {
418 | this.hideable = hideable;
419 | }
420 |
421 | public void setBottomSheetCallback(BottomSheetCallback callback) {
422 | this.callback = callback;
423 | }
424 |
425 | public final void setState(final int state) {
426 | if (state == this.state) {
427 | return;
428 | }
429 | if (viewRef == null) {
430 | // The view is not laid out yet; modify mState and let onLayoutChild handle it later
431 | if (state == STATE_COLLAPSED
432 | || state == STATE_EXPANDED
433 | || (hideable && state == STATE_HIDDEN)) {
434 | this.state = state;
435 | }
436 | return;
437 | }
438 | final V child = viewRef.get();
439 | if (child == null) {
440 | return;
441 | }
442 | // Start the animation; wait until a pending layout if there is one.
443 | ViewParent parent = child.getParent();
444 | if (parent != null && parent.isLayoutRequested() && ViewCompat.isAttachedToWindow(child)) {
445 | child.post(() -> startSettlingAnimation(child, state));
446 | } else {
447 | startSettlingAnimation(child, state);
448 | }
449 | }
450 |
451 | public final int getState() {
452 | return state;
453 | }
454 |
455 | public void setStateInternal(int state) {
456 | if (this.state == state) {
457 | return;
458 | }
459 | this.state = state;
460 | View bottomSheet = null;
461 | if (viewRef != null) {
462 | bottomSheet = viewRef.get();
463 | }
464 | if (bottomSheet != null && callback != null) {
465 | callback.onStateChanged(bottomSheet, state);
466 | }
467 | }
468 |
469 | private void reset() {
470 | activePointerId = ViewDragHelper.INVALID_POINTER;
471 | if (velocityTracker != null) {
472 | velocityTracker.recycle();
473 | velocityTracker = null;
474 | }
475 | }
476 |
477 | private boolean shouldHide(@NonNull View child, float yvel) {
478 | if (skipCollapsed) {
479 | return true;
480 | }
481 | if (child.getTop() < maxOffset) {
482 | // It should not hide, but collapse.
483 | return false;
484 | }
485 | final float newTop = child.getTop() + yvel * HIDE_FRICTION;
486 | return Math.abs(newTop - maxOffset) / (float) peekHeight > HIDE_THRESHOLD;
487 | }
488 |
489 | private @Nullable View findScrollingChild(@Nullable View view) {
490 | if (view instanceof NestedScrollingChild) {
491 | return view;
492 | }
493 | if (view instanceof ViewPager) {
494 | ViewPager viewPager = (ViewPager) view;
495 | View currentViewPagerChild = getCurrentView(viewPager);
496 | return findScrollingChild(currentViewPagerChild);
497 | } else if (view instanceof ViewGroup) {
498 | ViewGroup group = (ViewGroup) view;
499 | for (int i = 0, count = group.getChildCount(); i < count; i++) {
500 | View scrollingChild = findScrollingChild(group.getChildAt(i));
501 | if (scrollingChild != null) {
502 | return scrollingChild;
503 | }
504 | }
505 | }
506 | return null;
507 | }
508 |
509 | private static @Nullable View getCurrentView(@NonNull ViewPager viewPager) {
510 | final int currentItem = viewPager.getCurrentItem();
511 | for (int i = 0; i < viewPager.getChildCount(); i++) {
512 | final View child = viewPager.getChildAt(i);
513 | final ViewPager.LayoutParams layoutParams = (ViewPager.LayoutParams) child.getLayoutParams();
514 | if (!layoutParams.isDecor && currentItem == viewPager.getCurrentItem()) {
515 | return child;
516 | }
517 | }
518 | return null;
519 | }
520 |
521 | private float getYVelocity() {
522 | if (velocityTracker != null) {
523 | velocityTracker.computeCurrentVelocity(1000, maximumVelocity);
524 | }
525 | return VelocityTrackerCompat.getYVelocity(velocityTracker, activePointerId);
526 | }
527 |
528 | private void startSettlingAnimation(View child, int state) {
529 | int top;
530 | if (state == STATE_COLLAPSED) {
531 | top = maxOffset;
532 | } else if (state == STATE_EXPANDED) {
533 | top = minOffset;
534 | } else if (hideable && state == STATE_HIDDEN) {
535 | top = parentHeight;
536 | } else {
537 | throw new IllegalArgumentException("Illegal state argument: " + state);
538 | }
539 | setStateInternal(STATE_SETTLING);
540 | if (viewDragHelper != null && viewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) {
541 | ViewCompat.postOnAnimation(child, new SettleRunnable(child, state));
542 | }
543 | }
544 |
545 | private final ViewDragHelper.Callback mDragCallback =
546 | new ViewDragHelper.Callback() {
547 |
548 | @Override
549 | public boolean tryCaptureView(@NonNull View child, int pointerId) {
550 | if (state == STATE_DRAGGING) {
551 | return false;
552 | }
553 | if (touchingScrollingChild) {
554 | return false;
555 | }
556 | if (state == STATE_EXPANDED && activePointerId == pointerId) {
557 | View scroll = nestedScrollingChildRef.get();
558 | if (scroll != null && ViewCompat.canScrollVertically(scroll, -1)) {
559 | // Let the content scroll up
560 | return false;
561 | }
562 | }
563 | return viewRef != null && viewRef.get() == child;
564 | }
565 |
566 | @Override
567 | public void onViewPositionChanged(
568 | @NonNull View changedView, int left, int top, int dx, int dy) {
569 | dispatchOnSlide(top);
570 | }
571 |
572 | @Override
573 | public void onViewDragStateChanged(int state) {
574 | if (state == ViewDragHelper.STATE_DRAGGING) {
575 | setStateInternal(STATE_DRAGGING);
576 | }
577 | }
578 |
579 | @Override
580 | public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
581 | int top;
582 | int targetState;
583 | if (yvel < 0) { // Moving up
584 | top = minOffset;
585 | targetState = STATE_EXPANDED;
586 | } else if (hideable && shouldHide(releasedChild, yvel)) {
587 | top = parentHeight;
588 | targetState = STATE_HIDDEN;
589 | } else if (yvel == 0.f) {
590 | int currentTop = releasedChild.getTop();
591 | if (Math.abs(currentTop - minOffset) < Math.abs(currentTop - maxOffset)) {
592 | top = minOffset;
593 | targetState = STATE_EXPANDED;
594 | } else {
595 | top = maxOffset;
596 | targetState = STATE_COLLAPSED;
597 | }
598 | } else {
599 | top = maxOffset;
600 | targetState = STATE_COLLAPSED;
601 | }
602 | if (viewDragHelper.settleCapturedViewAt(releasedChild.getLeft(), top)) {
603 | setStateInternal(STATE_SETTLING);
604 | ViewCompat.postOnAnimation(
605 | releasedChild, new SettleRunnable(releasedChild, targetState));
606 | } else {
607 | setStateInternal(targetState);
608 | }
609 | }
610 |
611 | @Override
612 | public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
613 | return constrain(top, minOffset, hideable ? parentHeight : maxOffset);
614 | }
615 |
616 | private int constrain(int amount, int low, int high) {
617 | return amount < low ? low : (Math.min(amount, high));
618 | }
619 |
620 | @Override
621 | public int clampViewPositionHorizontal(View child, int left, int dx) {
622 | return child.getLeft();
623 | }
624 |
625 | @Override
626 | public int getViewVerticalDragRange(@NonNull View child) {
627 | if (hideable) {
628 | return parentHeight - minOffset;
629 | } else {
630 | return maxOffset - minOffset;
631 | }
632 | }
633 | };
634 |
635 | private void dispatchOnSlide(int top) {
636 | View bottomSheet = null;
637 | if (viewRef != null) {
638 | bottomSheet = viewRef.get();
639 | }
640 | if (bottomSheet != null && callback != null) {
641 | if (top > maxOffset) {
642 | callback.onSlide(bottomSheet, (float) (maxOffset - top) / (parentHeight - maxOffset));
643 | } else {
644 | callback.onSlide(bottomSheet, (float) (maxOffset - top) / ((maxOffset - minOffset)));
645 | }
646 | }
647 | }
648 |
649 | private class SettleRunnable implements Runnable {
650 |
651 | private final View mView;
652 |
653 | private final int mTargetState;
654 |
655 | SettleRunnable(View view, int targetState) {
656 | mView = view;
657 | mTargetState = targetState;
658 | }
659 |
660 | @Override
661 | public void run() {
662 | if (viewDragHelper != null && viewDragHelper.continueSettling(true)) {
663 | ViewCompat.postOnAnimation(mView, this);
664 | } else {
665 | setStateInternal(mTargetState);
666 | }
667 | }
668 | }
669 |
670 | protected static class SavedState extends AbsSavedState {
671 |
672 | final int state;
673 |
674 | public SavedState(Parcel source) {
675 | this(source, null);
676 | }
677 |
678 | public SavedState(Parcel source, ClassLoader loader) {
679 | super(source, loader);
680 | //noinspection ResourceType
681 | state = source.readInt();
682 | }
683 |
684 | public SavedState(Parcelable superState, int state) {
685 | super(superState);
686 | this.state = state;
687 | }
688 |
689 | @Override
690 | public void writeToParcel(Parcel out, int flags) {
691 | super.writeToParcel(out, flags);
692 | out.writeInt(state);
693 | }
694 | }
695 |
696 | @SuppressWarnings("unchecked")
697 | public static ViewPagerBottomSheetBehavior from(V view) {
698 | ViewGroup.LayoutParams params = view.getLayoutParams();
699 | if (!(params instanceof CoordinatorLayout.LayoutParams)) {
700 | throw new IllegalArgumentException("The view is not a child of CoordinatorLayout");
701 | }
702 | CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params).getBehavior();
703 | if (!(behavior instanceof ViewPagerBottomSheetBehavior)) {
704 | throw new IllegalArgumentException(
705 | "The view is not associated with ViewPagerBottomSheetBehavior");
706 | }
707 | return (ViewPagerBottomSheetBehavior) behavior;
708 | }
709 | }
710 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/viewpagerbottomsheet/ViewPagerBottomSheetDialog.java:
--------------------------------------------------------------------------------
1 | package com.allattentionhere.fabulousfilter.viewpagerbottomsheet;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.os.Bundle;
7 |
8 | import androidx.annotation.Nullable;
9 | import androidx.coordinatorlayout.widget.CoordinatorLayout;
10 | import androidx.core.view.AccessibilityDelegateCompat;
11 | import androidx.core.view.ViewCompat;
12 | import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
13 | import androidx.appcompat.app.AppCompatDialog;
14 | import android.util.TypedValue;
15 | import android.view.View;
16 | import android.view.ViewGroup;
17 | import android.view.Window;
18 | import android.widget.FrameLayout;
19 |
20 | import com.allattentionhere.fabulousfilter.R;
21 |
22 | public final class ViewPagerBottomSheetDialog extends AppCompatDialog {
23 |
24 | private @Nullable ViewPagerBottomSheetBehavior behavior;
25 |
26 | boolean cancelable = true;
27 | private boolean canceledOnTouchOutside = true;
28 | private boolean canceledOnTouchOutsideSet;
29 |
30 | public ViewPagerBottomSheetDialog(Context context) {
31 | this(context, 0);
32 | }
33 |
34 | public ViewPagerBottomSheetDialog(Context context, int theme) {
35 | super(context, getThemeResId(context, theme));
36 | // We hide the title bar for any style configuration. Otherwise, there will be a gap
37 | // above the bottom sheet when it is expanded.
38 | supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
39 | }
40 |
41 | @Override
42 | public void setContentView(int layoutResId) {
43 | super.setContentView(wrapInBottomSheet(layoutResId, null, null));
44 | }
45 |
46 | @Override
47 | protected void onCreate(Bundle savedInstanceState) {
48 | super.onCreate(savedInstanceState);
49 | getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
50 | }
51 |
52 | @Override
53 | public void setContentView(View view) {
54 | super.setContentView(wrapInBottomSheet(0, view, null));
55 | }
56 |
57 | @Override
58 | public void setContentView(View view, ViewGroup.LayoutParams params) {
59 | super.setContentView(wrapInBottomSheet(0, view, params));
60 | }
61 |
62 | @Override
63 | public void setCancelable(boolean cancelable) {
64 | super.setCancelable(cancelable);
65 | if (this.cancelable != cancelable) {
66 | this.cancelable = cancelable;
67 | if (behavior != null) {
68 | behavior.setHideable(cancelable);
69 | }
70 | }
71 | }
72 |
73 | @Override
74 | public void setCanceledOnTouchOutside(boolean cancel) {
75 | super.setCanceledOnTouchOutside(cancel);
76 | if (cancel && !cancelable) {
77 | cancelable = true;
78 | }
79 | canceledOnTouchOutside = cancel;
80 | canceledOnTouchOutsideSet = true;
81 | }
82 |
83 | private View wrapInBottomSheet(
84 | int layoutResId, @Nullable View view, @Nullable ViewGroup.LayoutParams params) {
85 | final CoordinatorLayout coordinator =
86 | (CoordinatorLayout)
87 | View.inflate(getContext(), R.layout.design_view_pager_bottom_sheet_dialog, null);
88 | if (layoutResId != 0 && view == null) {
89 | view = getLayoutInflater().inflate(layoutResId, coordinator, false);
90 | }
91 | FrameLayout bottomSheet = coordinator.findViewById(R.id.design_bottom_sheet);
92 | behavior = ViewPagerBottomSheetBehavior.from(bottomSheet);
93 | behavior.setBottomSheetCallback(bottomSheetCallback);
94 | behavior.setHideable(cancelable);
95 | if (params == null) {
96 | bottomSheet.addView(view);
97 | } else {
98 | bottomSheet.addView(view, params);
99 | }
100 | // We treat the CoordinatorLayout as outside the dialog though it is technically inside
101 | coordinator
102 | .findViewById(R.id.touch_outside)
103 | .setOnClickListener(
104 | view1 -> {
105 | if (cancelable && isShowing() && shouldWindowCloseOnTouchOutside()) {
106 | cancel();
107 | }
108 | });
109 | // Handle accessibility events
110 | ViewCompat.setAccessibilityDelegate(
111 | bottomSheet,
112 | new AccessibilityDelegateCompat() {
113 | @Override
114 | public void onInitializeAccessibilityNodeInfo(
115 | View host, AccessibilityNodeInfoCompat info) {
116 | super.onInitializeAccessibilityNodeInfo(host, info);
117 | if (cancelable) {
118 | info.addAction(AccessibilityNodeInfoCompat.ACTION_DISMISS);
119 | info.setDismissable(true);
120 | } else {
121 | info.setDismissable(false);
122 | }
123 | }
124 |
125 | @Override
126 | public boolean performAccessibilityAction(View host, int action, Bundle args) {
127 | if (action == AccessibilityNodeInfoCompat.ACTION_DISMISS && cancelable) {
128 | cancel();
129 | return true;
130 | }
131 | return super.performAccessibilityAction(host, action, args);
132 | }
133 | });
134 | return coordinator;
135 | }
136 |
137 | private boolean shouldWindowCloseOnTouchOutside() {
138 | if (!canceledOnTouchOutsideSet) {
139 | TypedArray a =
140 | getContext().obtainStyledAttributes(new int[] {android.R.attr.windowCloseOnTouchOutside});
141 | canceledOnTouchOutside = a.getBoolean(0, true);
142 | a.recycle();
143 | canceledOnTouchOutsideSet = true;
144 | }
145 | return canceledOnTouchOutside;
146 | }
147 |
148 | @SuppressLint("PrivateResource")
149 | private static int getThemeResId(@Nullable Context context, int themeId) {
150 | if (themeId == 0) {
151 | // If the provided theme is 0, then retrieve the dialogTheme from our theme
152 | TypedValue outValue = new TypedValue();
153 | if (context != null
154 | && context.getTheme().resolveAttribute(R.attr.bottomSheetDialogTheme, outValue, true)) {
155 | themeId = outValue.resourceId;
156 | } else {
157 | // bottomSheetDialogTheme is not provided; we default to our light theme
158 | themeId = R.style.Theme_Design_Light_BottomSheetDialog;
159 | }
160 | }
161 | return themeId;
162 | }
163 |
164 | private final ViewPagerBottomSheetBehavior.BottomSheetCallback bottomSheetCallback =
165 | new ViewPagerBottomSheetBehavior.BottomSheetCallback() {
166 | @Override
167 | public void onStateChanged(
168 | View bottomSheet, @ViewPagerBottomSheetBehavior.State int newState) {
169 | if (newState == ViewPagerBottomSheetBehavior.STATE_HIDDEN) {
170 | cancel();
171 | }
172 | }
173 |
174 | @Override
175 | public void onSlide(View bottomSheet, float slideOffset) {}
176 | };
177 | }
178 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/java/com/allattentionhere/fabulousfilter/viewpagerbottomsheet/ViewPagerBottomSheetDialogFragment.java:
--------------------------------------------------------------------------------
1 | package com.allattentionhere.fabulousfilter.viewpagerbottomsheet;
2 |
3 | import android.app.Dialog;
4 | import android.os.Bundle;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
9 |
10 | public class ViewPagerBottomSheetDialogFragment extends BottomSheetDialogFragment {
11 |
12 | @NonNull
13 | @Override
14 | public Dialog onCreateDialog(Bundle savedInstanceState) {
15 | return new ViewPagerBottomSheetDialog(getContext(), getTheme());
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/res/anim/bottomsheet_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/res/anim/bottomsheet_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/res/layout/design_view_pager_bottom_sheet_dialog.xml:
--------------------------------------------------------------------------------
1 |
16 |
21 |
22 |
29 |
30 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Fabulous Filter Library
3 | com.allattentionhere.fabulousfilter.viewpagerbottomsheet.ViewPagerBottomSheetBehavior
4 |
5 |
--------------------------------------------------------------------------------
/fabulousfilter/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | android.enableJetifier=true
13 | android.useAndroidX=true
14 | org.gradle.jvmargs=-Xmx1536m
15 |
16 | # When configured, Gradle will run in incubating parallel mode.
17 | # This option should only be used with decoupled projects. More details, visit
18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
19 | # org.gradle.parallel=true
20 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Jul 16 12:01:40 BST 2022
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # 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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/newDemo1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/newDemo1.gif
--------------------------------------------------------------------------------
/newDemo2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Krupen/FabulousFilter/cabc9eb54610c58bb938f6e3a05a49471fe13873/newDemo2.gif
--------------------------------------------------------------------------------
/scripts/publish-module.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'maven-publish'
2 | apply plugin: 'signing'
3 |
4 | task androidSourcesJar(type: Jar) {
5 | archiveClassifier.set('sources')
6 | if (project.plugins.findPlugin("com.android.library")) {
7 | from android.sourceSets.main.java.srcDirs
8 | } else {
9 | from sourceSets.main.java.srcDirs
10 | }
11 | }
12 |
13 | artifacts {
14 | archives androidSourcesJar
15 | }
16 |
17 | group = PUBLISH_GROUP_ID
18 | version = PUBLISH_VERSION
19 |
20 | afterEvaluate {
21 | publishing {
22 | publications {
23 | release(MavenPublication) {
24 | // The coordinates of the library, being set from variables that
25 | // we'll set up later
26 | groupId PUBLISH_GROUP_ID
27 | artifactId PUBLISH_ARTIFACT_ID
28 | version PUBLISH_VERSION
29 |
30 | // Two artifacts, the `aar` (or `jar`) and the sources
31 | if (project.plugins.findPlugin("com.android.library")) {
32 | from components.release
33 | } else {
34 | artifact("$buildDir/libs/${project.getName()}-${version}.jar")
35 | }
36 |
37 | artifact androidSourcesJar
38 |
39 | // Mostly self-explanatory metadata
40 | pom {
41 | name = PUBLISH_ARTIFACT_ID
42 | description = PUBLISH_DESCRIPTION
43 | url = PUBLISH_URL
44 | licenses {
45 | license {
46 | name = PUBLISH_LICENSE_NAME
47 | url = PUBLISH_LICENSE_URL
48 | }
49 | }
50 | developers {
51 | developer {
52 | id = PUBLISH_DEVELOPER_ID
53 | name = PUBLISH_DEVELOPER_NAME
54 | email = PUBLISH_DEVELOPER_EMAIL
55 | }
56 | }
57 |
58 | // Version control info - if you're using GitHub, follow the
59 | // format as seen here
60 | scm {
61 | connection = PUBLISH_SCM_CONNECTION
62 | developerConnection = PUBLISH_SCM_DEVELOPER_CONNECTION
63 | url = PUBLISH_SCM_URL
64 | }
65 | }
66 | }
67 | }
68 | }
69 | }
70 |
71 | ext["signing.keyId"] = signing.keyId
72 | ext["signing.password"] = signing.password
73 | ext["signing.secretKeyRingFile"] = signing.secretKeyRingFile
74 |
75 | signing {
76 | sign publishing.publications
77 | }
--------------------------------------------------------------------------------
/scripts/publish-root.gradle:
--------------------------------------------------------------------------------
1 | // Create variables with empty default values
2 | ext["signing.keyId"] = ''
3 | ext["signing.password"] = ''
4 | ext["signing.secretKeyRingFile"] = ''
5 | ext["ossrhUsername"] = ''
6 | ext["ossrhPassword"] = ''
7 | ext["sonatypeStagingProfileId"] = ''
8 |
9 | File secretPropsFile = project.rootProject.file('local.properties')
10 | if (secretPropsFile.exists()) {
11 | // Read local.properties file first if it exists
12 | Properties p = new Properties()
13 | new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) }
14 | p.each { name, value -> ext[name] = value }
15 | } else {
16 | // Use system environment variables
17 | ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME')
18 | ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD')
19 | ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID')
20 | ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID')
21 | ext["signing.password"] = System.getenv('SIGNING_PASSWORD')
22 | ext["signing.secretKeyRingFile"] = System.getenv('SIGNING_SECRET_KEY_RING_FILE')
23 | }
24 |
25 | // Set up Sonatype repository
26 | nexusPublishing {
27 | repositories {
28 | sonatype {
29 | stagingProfileId = sonatypeStagingProfileId
30 | username = ossrhUsername
31 | password = ossrhPassword
32 | nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
33 | snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':fabulousfilter'
2 | include ':scripts'
3 |
--------------------------------------------------------------------------------