mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-04-20 14:23:09 +02:00
Compare commits
1393 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2d6d823a87 | ||
![]() |
02a9724587 | ||
![]() |
c17237015e | ||
![]() |
2681794676 | ||
![]() |
42e59ac0db | ||
![]() |
cac98ee3d4 | ||
![]() |
aeecc48639 | ||
![]() |
db444d89f0 | ||
![]() |
29971777a7 | ||
![]() |
88cd18b8c6 | ||
![]() |
30a77f1a99 | ||
![]() |
6de7ee9cee | ||
![]() |
d44b85073a | ||
![]() |
514fbafd00 | ||
![]() |
c35222cdfd | ||
![]() |
37a94595c0 | ||
![]() |
58d9dec33c | ||
![]() |
095403cc76 | ||
![]() |
7f3a607246 | ||
![]() |
ffee78d4f7 | ||
![]() |
f2a20c3aae | ||
![]() |
1e7dbba995 | ||
![]() |
0b8f3fe94b | ||
![]() |
0e8b0673ca | ||
![]() |
8450f6953e | ||
![]() |
ddefda08f1 | ||
![]() |
c5b173b40a | ||
![]() |
f10bc42c7b | ||
![]() |
6371d71b7a | ||
![]() |
09f0c986e0 | ||
![]() |
10043cc62c | ||
![]() |
f795412551 | ||
![]() |
6a7020a516 | ||
![]() |
137ea65e0f | ||
![]() |
50ef7f8617 | ||
![]() |
e1dbc2f050 | ||
![]() |
77e1acbb1e | ||
![]() |
6e19f37d79 | ||
0823e72328 | |||
![]() |
fadf1d7754 | ||
![]() |
1071a0848a | ||
![]() |
cefb0deba8 | ||
![]() |
53c813f014 | ||
![]() |
90a151c129 | ||
![]() |
9fd9721ae7 | ||
![]() |
ceca75ef4b | ||
![]() |
21c00bbe53 | ||
![]() |
db00566ebf | ||
![]() |
07ab1b984f | ||
![]() |
8177d4aa2d | ||
![]() |
beff1b6460 | ||
![]() |
31b569b02e | ||
![]() |
8bf77817d2 | ||
![]() |
87b7bd9b30 | ||
![]() |
27b61adf1d | ||
![]() |
8d7dc511ea | ||
![]() |
a0244841ad | ||
![]() |
12c0c6f2ec | ||
![]() |
aaa3b8626e | ||
![]() |
48c9e2dfe3 | ||
![]() |
81d4801d27 | ||
![]() |
5f8016061d | ||
![]() |
5007587192 | ||
![]() |
dfd1083e41 | ||
![]() |
a322986df5 | ||
![]() |
678baf46e5 | ||
![]() |
4077fe448d | ||
![]() |
f085e17ef7 | ||
![]() |
7fd2cad46b | ||
![]() |
93dc2ac9ab | ||
![]() |
ac53e267fc | ||
![]() |
86eb1a0f42 | ||
![]() |
710d82da27 | ||
![]() |
0123f50810 | ||
![]() |
6d3eb65445 | ||
![]() |
a9a0630226 | ||
![]() |
ec7577f999 | ||
![]() |
05c7c0012c | ||
![]() |
d65c6db954 | ||
![]() |
771dc437e6 | ||
![]() |
3d5d3847cc | ||
![]() |
726c22b70a | ||
![]() |
18cc60a80b | ||
![]() |
fedde9f739 | ||
![]() |
9fde97bef0 | ||
![]() |
742bd03e9e | ||
![]() |
62ffc652ab | ||
![]() |
bfd2e9883a | ||
![]() |
00e077d01f | ||
![]() |
c21d89cf60 | ||
![]() |
f52cc1b197 | ||
![]() |
c90ad97f55 | ||
![]() |
845e09d875 | ||
![]() |
158b69a8d3 | ||
![]() |
9535f53563 | ||
![]() |
eeb3fc4621 | ||
![]() |
41693a9fc8 | ||
![]() |
d3599b8c89 | ||
![]() |
ffd81f8b82 | ||
![]() |
2c34924052 | ||
![]() |
26ad6373e6 | ||
![]() |
cac8f94407 | ||
![]() |
6628b97faf | ||
![]() |
8424414317 | ||
![]() |
d8bb927703 | ||
![]() |
c8e8c172a2 | ||
![]() |
0d4dee765a | ||
![]() |
fd407b2b03 | ||
![]() |
40ed5a221f | ||
![]() |
5150467372 | ||
![]() |
63c5720f63 | ||
![]() |
6c93cd4217 | ||
![]() |
649d4f619a | ||
![]() |
ba10d10a10 | ||
![]() |
1450d63fcb | ||
![]() |
2ec06bc39a | ||
![]() |
6f12227c2e | ||
![]() |
3a91f87ccd | ||
![]() |
52a53334ca | ||
![]() |
3ab9602865 | ||
![]() |
dc19043f73 | ||
![]() |
cf25507850 | ||
![]() |
044cedff99 | ||
![]() |
4de066bf5f | ||
![]() |
8d174bda01 | ||
![]() |
e2fd714070 | ||
![]() |
8097e8d06d | ||
![]() |
93ccdbdeb7 | ||
![]() |
7ded400a30 | ||
![]() |
2ff784066e | ||
![]() |
6c96875c83 | ||
![]() |
9f3aaf6e86 | ||
![]() |
55369eaa8b | ||
![]() |
c983c16907 | ||
![]() |
c7362bce12 | ||
![]() |
7935d0f097 | ||
![]() |
4b64277948 | ||
![]() |
ef0996c80e | ||
![]() |
132729bbd9 | ||
![]() |
6d36ab27d1 | ||
![]() |
11fabb231f | ||
![]() |
6fd999f88c | ||
![]() |
7711413b30 | ||
![]() |
cdc0c9d458 | ||
![]() |
8e5f750a80 | ||
![]() |
f4e7e8978c | ||
![]() |
14952307b3 | ||
![]() |
96c542d6d2 | ||
![]() |
77d22b87aa | ||
![]() |
37c68443bd | ||
![]() |
9dbb5d70e9 | ||
![]() |
99afa77a63 | ||
![]() |
a5d0f4212d | ||
![]() |
a85f935eb4 | ||
![]() |
bb44fa066c | ||
![]() |
54a61c6254 | ||
![]() |
ac10874bf1 | ||
![]() |
fa55b4901a | ||
![]() |
86c41d9191 | ||
![]() |
0f90430387 | ||
![]() |
745523c620 | ||
![]() |
c1ef0e9d11 | ||
![]() |
8911ce2bc1 | ||
![]() |
2990fc5479 | ||
![]() |
48b7adb564 | ||
![]() |
2e97467c57 | ||
![]() |
f8ac9e793a | ||
![]() |
148597e578 | ||
![]() |
6c50a80b42 | ||
![]() |
1bf0679e92 | ||
![]() |
5b5dc5cade | ||
![]() |
46de915965 | ||
![]() |
98a89b1ca1 | ||
![]() |
6d1e18cce2 | ||
![]() |
8fe0f88be4 | ||
![]() |
aeed735521 | ||
![]() |
e314fafaff | ||
![]() |
2ab0dd7546 | ||
![]() |
aa06868a4e | ||
![]() |
9a6d56ec77 | ||
![]() |
2b104e6463 | ||
![]() |
afb1863827 | ||
![]() |
d8228748e4 | ||
![]() |
b0608c47c4 | ||
![]() |
dda0d88f19 | ||
![]() |
a1b5560977 | ||
![]() |
86f5811bda | ||
![]() |
3f11e75985 | ||
![]() |
c39b5442c9 | ||
![]() |
3b80adf355 | ||
![]() |
cae41d17b6 | ||
![]() |
519d75d9d9 | ||
![]() |
cb953ea8a8 | ||
![]() |
52968cafad | ||
![]() |
b7755dae96 | ||
![]() |
113ecc0ef1 | ||
![]() |
23bd9b8e05 | ||
![]() |
decfd2068a | ||
![]() |
a88cfb8ae3 | ||
![]() |
50cb0acc7d | ||
![]() |
27413a9745 | ||
![]() |
49a093201b | ||
![]() |
7c925cb88a | ||
![]() |
8745d7d526 | ||
![]() |
e02246f97d | ||
![]() |
e629e03b33 | ||
![]() |
e2ad3758e0 | ||
![]() |
f3e2d21b89 | ||
![]() |
fd62653d79 | ||
![]() |
ca3e6f7fc9 | ||
![]() |
d8abac1917 | ||
![]() |
2807659da3 | ||
![]() |
7884bf4077 | ||
![]() |
59f80c049c | ||
![]() |
f1e58db151 | ||
![]() |
74b766f18a | ||
![]() |
7e0f69d95d | ||
![]() |
fa318d4509 | ||
![]() |
63b74a9fda | ||
![]() |
1a543814f4 | ||
![]() |
50ae767fcd | ||
![]() |
44263ac95f | ||
![]() |
a6aca42c8c | ||
![]() |
83daae46b8 | ||
![]() |
6611fc5843 | ||
![]() |
fe82c86c93 | ||
![]() |
692555732d | ||
![]() |
d59286bb05 | ||
![]() |
91cfa7e945 | ||
![]() |
2d277e80cc | ||
![]() |
3cdca5eb33 | ||
![]() |
591abb4bb8 | ||
![]() |
0b4421c7a7 | ||
![]() |
325efd8b14 | ||
![]() |
959168771b | ||
![]() |
41217190bb | ||
![]() |
18c306b9ea | ||
![]() |
c6be1a7954 | ||
![]() |
e8e9f04050 | ||
![]() |
3700a71c39 | ||
![]() |
60f0628f5e | ||
![]() |
80dcd9aa69 | ||
![]() |
d60e622626 | ||
![]() |
91b685576b | ||
![]() |
2e3e3dcf3c | ||
![]() |
118f5e1794 | ||
![]() |
e902352a4b | ||
![]() |
2f7fcb6dc3 | ||
![]() |
21ddb9d706 | ||
![]() |
efa63452e7 | ||
![]() |
83f84de019 | ||
![]() |
b9aca981e5 | ||
![]() |
5913707519 | ||
![]() |
dd6a2c0979 | ||
![]() |
9fdee6e0c7 | ||
![]() |
b31bf5c1ab | ||
![]() |
cf4906f2f4 | ||
![]() |
680a5dfea3 | ||
![]() |
c1062cd7ed | ||
![]() |
8edc581f0b | ||
![]() |
ea9d801d08 | ||
![]() |
8f72e11d0c | ||
![]() |
452271e8c0 | ||
![]() |
7b4effe889 | ||
![]() |
e2bf48d1b6 | ||
![]() |
c88056ddb9 | ||
![]() |
96dbb0a057 | ||
![]() |
288c80ea26 | ||
![]() |
5a217aca01 | ||
![]() |
4bed62aa6f | ||
![]() |
a4d604e146 | ||
![]() |
ae4405ef78 | ||
![]() |
71ca51e813 | ||
![]() |
1bf07d736f | ||
![]() |
c011f550bb | ||
![]() |
909899612e | ||
![]() |
4184fbb2cd | ||
![]() |
75010c0771 | ||
![]() |
5562498e84 | ||
![]() |
c2d0940a80 | ||
![]() |
baa98f25c5 | ||
![]() |
26645ee83c | ||
![]() |
85d74bec1c | ||
![]() |
fd0fc652a3 | ||
![]() |
c85dac2e4d | ||
![]() |
c855f08f9c | ||
![]() |
a31c68e87a | ||
![]() |
99021f6b3a | ||
![]() |
e2b47db3fd | ||
![]() |
8609956ae7 | ||
![]() |
e25ca930e0 | ||
![]() |
47ec1899a1 | ||
![]() |
1e8fb6a9ae | ||
![]() |
02eb5b7ee4 | ||
![]() |
776806caef | ||
![]() |
755b846b50 | ||
![]() |
73f3ba17de | ||
![]() |
07fb1e0e12 | ||
![]() |
297867cbf3 | ||
![]() |
db598af28a | ||
![]() |
ec765c9070 | ||
![]() |
5eaa754401 | ||
![]() |
b48b5589f4 | ||
![]() |
634ef16bc5 | ||
![]() |
ccf0bdaf05 | ||
![]() |
4647da7803 | ||
![]() |
613f271c4e | ||
![]() |
8b1529f240 | ||
![]() |
3eb09033bf | ||
![]() |
12619f6bde | ||
![]() |
f5ceaa9afe | ||
![]() |
777ae945e0 | ||
![]() |
3eae8fb58b | ||
![]() |
b14ef5cd78 | ||
![]() |
98bf4f3bdc | ||
![]() |
2d6cf50ca7 | ||
![]() |
95baf9fb9c | ||
![]() |
61b7410bd0 | ||
![]() |
dd0972b528 | ||
![]() |
d5c10fbd2b | ||
![]() |
d17f6297d3 | ||
![]() |
3ae785a45c | ||
![]() |
dd254d4bec | ||
![]() |
e04bd75f1f | ||
![]() |
929ccb53db | ||
![]() |
72319a4613 | ||
![]() |
e389e6c073 | ||
![]() |
cd6951dcbb | ||
![]() |
02d60754b6 | ||
![]() |
6884251646 | ||
![]() |
582e2059d8 | ||
![]() |
ea2974bfae | ||
![]() |
b8ff649c96 | ||
![]() |
8661ecdafb | ||
![]() |
fe8cbc061d | ||
![]() |
b4459e1fd4 | ||
![]() |
fd6553871f | ||
![]() |
a4ca44e1ce | ||
![]() |
e124c429d1 | ||
![]() |
e9a2dae1e4 | ||
![]() |
8b0f3490e3 | ||
![]() |
131606a6cf | ||
![]() |
cacafa205e | ||
![]() |
9c620de1e7 | ||
![]() |
3e98fb967b | ||
![]() |
8db81478f3 | ||
![]() |
8f9861bac6 | ||
![]() |
5b35e3500e | ||
![]() |
fc4c297bef | ||
![]() |
e7cb699bcf | ||
![]() |
5301b4efad | ||
![]() |
bf595dd09c | ||
![]() |
cb4b168b2a | ||
![]() |
b2fcbb8289 | ||
![]() |
df7982d11b | ||
![]() |
7ed9bac0db | ||
![]() |
e6c42ccb87 | ||
![]() |
73378571a2 | ||
![]() |
1cb18b554b | ||
![]() |
b9e7e80e11 | ||
![]() |
114d855c81 | ||
![]() |
1108f2eb71 | ||
![]() |
2a3b1422ef | ||
![]() |
5690a136f1 | ||
![]() |
4bea803220 | ||
![]() |
5ac1f94302 | ||
![]() |
62fdfe754e | ||
![]() |
9ba1bf130f | ||
![]() |
37c0ff2ac7 | ||
![]() |
6287f694f4 | ||
![]() |
4469323fe0 | ||
![]() |
ebbb9e4904 | ||
![]() |
7e38445c98 | ||
![]() |
bf03601e83 | ||
![]() |
e6dec4c6c0 | ||
![]() |
891be2f9dd | ||
![]() |
1f6da2babe | ||
![]() |
cce47ed472 | ||
![]() |
2808c66840 | ||
![]() |
17351066d1 | ||
![]() |
b5d5685b4c | ||
![]() |
3093850a4a | ||
![]() |
93233f6afa | ||
![]() |
76838fcc41 | ||
![]() |
34e44a7a36 | ||
![]() |
5242d15ebd | ||
![]() |
fe90fc6442 | ||
![]() |
dc08abac53 | ||
![]() |
f72f8228f0 | ||
![]() |
5c87ae2711 | ||
![]() |
abcd6916b3 | ||
![]() |
6824960731 | ||
![]() |
726a37d5d6 | ||
![]() |
704a55d789 | ||
![]() |
bf5fb5f623 | ||
![]() |
1af65de548 | ||
![]() |
06407ee439 | ||
![]() |
db265fa12b | ||
![]() |
e721261e84 | ||
![]() |
c5eb67271e | ||
![]() |
a5f5c740c9 | ||
![]() |
1b271bd20e | ||
![]() |
d191982da6 | ||
![]() |
6e9a0b217d | ||
![]() |
df4b6ec3e5 | ||
![]() |
d9b91d6de8 | ||
![]() |
dd6e536f88 | ||
![]() |
a5cbee2b45 | ||
![]() |
7a43ef4dee | ||
![]() |
549a542879 | ||
![]() |
0f84732f80 | ||
![]() |
4045da7fc5 | ||
![]() |
ae6af77aef | ||
![]() |
fdad2d9e1a | ||
![]() |
2d01a8c4d4 | ||
![]() |
6c4a1b54ba | ||
![]() |
37879ca07e | ||
![]() |
2834ab1050 | ||
![]() |
9ef37c46ef | ||
![]() |
1364691a46 | ||
![]() |
2933e214c6 | ||
![]() |
a58a557fd0 | ||
![]() |
43d71c082b | ||
![]() |
3eb99a4bf5 | ||
![]() |
ea7b4438e8 | ||
![]() |
208d097986 | ||
![]() |
07561c6484 | ||
![]() |
930ad12f5b | ||
![]() |
b4595446a3 | ||
![]() |
efcd2d80da | ||
![]() |
da953c9b1c | ||
![]() |
177ffd92f7 | ||
![]() |
85379b0beb | ||
![]() |
cf4aa552e7 | ||
![]() |
b6d625a1fc | ||
![]() |
78333e0077 | ||
![]() |
ea3598bb6d | ||
![]() |
e91d99652c | ||
![]() |
d78dad5090 | ||
![]() |
0615593d94 | ||
![]() |
15f9db5ca6 | ||
![]() |
75b3485ab4 | ||
![]() |
50e7bf14d4 | ||
![]() |
147f4c39e5 | ||
![]() |
9e95d05182 | ||
![]() |
9ccb6e0a24 | ||
![]() |
fd31cafd8f | ||
![]() |
92d7a46314 | ||
![]() |
7aaefa977b | ||
![]() |
530034d7da | ||
![]() |
44647946e0 | ||
![]() |
efd63797e4 | ||
![]() |
74820fe67d | ||
![]() |
e825af0ff0 | ||
![]() |
256f6c8732 | ||
![]() |
22abad35cc | ||
![]() |
6a33088352 | ||
![]() |
01c41645ab | ||
![]() |
54f74d2a3c | ||
![]() |
e0688fe79b | ||
![]() |
36c7bb1127 | ||
![]() |
045205754e | ||
![]() |
e34e4d6906 | ||
![]() |
481af64137 | ||
![]() |
2b3a7f6b41 | ||
![]() |
e3fe03c5fc | ||
![]() |
9740e0b7bf | ||
![]() |
58a26cc0c6 | ||
![]() |
d201c0c448 | ||
![]() |
359432d24d | ||
![]() |
edf8ec20f0 | ||
![]() |
3ad9e5da1f | ||
![]() |
459bbf78b2 | ||
![]() |
d0baf02750 | ||
![]() |
a5bb7d9c6e | ||
![]() |
a939d95ea3 | ||
![]() |
4c081c970e | ||
![]() |
b75ab76c2a | ||
![]() |
9da6dbccb3 | ||
![]() |
66444ae35b | ||
![]() |
3e8b3de2b7 | ||
![]() |
85ac5769a1 | ||
![]() |
93e3d5994a | ||
![]() |
0cf24c527b | ||
![]() |
97c5acd6ba | ||
![]() |
30aeb70647 | ||
![]() |
b599d679c4 | ||
![]() |
1eecd24d91 | ||
![]() |
c698dfdb73 | ||
![]() |
c7a44f5ced | ||
![]() |
c8ee6ff1e7 | ||
![]() |
552acd4043 | ||
![]() |
ede101ea20 | ||
![]() |
13c2640ed5 | ||
![]() |
dd0739fd4b | ||
![]() |
9023f13932 | ||
![]() |
f8456fb087 | ||
![]() |
df7044cc64 | ||
![]() |
9b48041cd9 | ||
![]() |
46cecf3474 | ||
![]() |
c27254bcad | ||
![]() |
80333cdea4 | ||
![]() |
6aee3ea420 | ||
![]() |
a11a44b768 | ||
![]() |
e869107101 | ||
![]() |
5903bbe59d | ||
![]() |
6c0ddd3e6d | ||
![]() |
621a7ac642 | ||
![]() |
e86b47fb1b | ||
![]() |
98fb7ac8c9 | ||
![]() |
f49e39e858 | ||
![]() |
8fc57cd3f5 | ||
![]() |
a9eda087e0 | ||
![]() |
3f36a284ee | ||
![]() |
1814fd67e1 | ||
![]() |
54e49af943 | ||
![]() |
d6a67a0da6 | ||
![]() |
28725c6400 | ||
![]() |
4fc965d970 | ||
![]() |
2aaf713d58 | ||
![]() |
c7d2ac4e3e | ||
![]() |
ae20c30c88 | ||
![]() |
aef3f66654 | ||
![]() |
c7abde8f11 | ||
![]() |
2fcff33bd6 | ||
![]() |
b08e4c2d3d | ||
![]() |
73ff09052c | ||
![]() |
9649afd43f | ||
![]() |
ed3a245b51 | ||
![]() |
477730708f | ||
![]() |
f39d0c595d | ||
![]() |
0a127ac6ee | ||
![]() |
46407f9647 | ||
![]() |
6ecb97b87e | ||
![]() |
ecdaaeae65 | ||
![]() |
a0c302b663 | ||
![]() |
b31039ecd9 | ||
![]() |
5c84086f42 | ||
![]() |
752cdfa8d6 | ||
![]() |
6b75715e87 | ||
![]() |
8e3d404352 | ||
![]() |
810cfd8092 | ||
![]() |
bd2a9524c6 | ||
![]() |
d780d5118d | ||
![]() |
b9e0d91220 | ||
![]() |
f1570b8eb9 | ||
![]() |
de0f29a09e | ||
![]() |
c0d11c91e3 | ||
![]() |
22c540a3d4 | ||
![]() |
0d5bb331f3 | ||
![]() |
b7e35d0322 | ||
![]() |
7bcd6bf038 | ||
![]() |
0e52fb7386 | ||
![]() |
ea4591144b | ||
![]() |
7627d184a2 | ||
![]() |
076b485fda | ||
![]() |
339bb9c8f6 | ||
![]() |
09cb97e367 | ||
![]() |
4e1f2ed41a | ||
![]() |
281b6a95ef | ||
![]() |
e40871c0d0 | ||
![]() |
b74eeed994 | ||
![]() |
ccde482364 | ||
![]() |
a02033d0f3 | ||
![]() |
6c6bc89f57 | ||
![]() |
1e3da45340 | ||
![]() |
0d366adddb | ||
![]() |
2c24eba46d | ||
![]() |
7c6dbca986 | ||
![]() |
33a8fa2a1e | ||
![]() |
300e2c4bc2 | ||
![]() |
f883318bd2 | ||
![]() |
b44fa6b2e4 | ||
![]() |
5460c1e2a0 | ||
![]() |
137c975e81 | ||
![]() |
001de4a88c | ||
![]() |
5dcb3fd580 | ||
![]() |
f13995aa5c | ||
![]() |
e23deb5ca6 | ||
![]() |
9cc98fcf08 | ||
![]() |
d688b379a2 | ||
![]() |
d6a796e25e | ||
![]() |
e02d3e571d | ||
![]() |
907b75b22d | ||
![]() |
c3660b5f80 | ||
![]() |
7ff10df70c | ||
![]() |
83e1b21ec3 | ||
![]() |
deb54e4b24 | ||
![]() |
48873caecc | ||
![]() |
cadd1a3dbd | ||
![]() |
f09f069b2c | ||
![]() |
1fb5aaed5d | ||
![]() |
65ba330d5f | ||
![]() |
795317f13f | ||
![]() |
031cc05209 | ||
![]() |
0ac8e1d9c1 | ||
![]() |
4389dc9d79 | ||
![]() |
b13257cb78 | ||
![]() |
fcffa2afeb | ||
![]() |
3c2f85f263 | ||
![]() |
0a2323acf3 | ||
![]() |
45c2948ed1 | ||
![]() |
f72a6103b5 | ||
![]() |
9261848369 | ||
![]() |
7f4e45c57c | ||
![]() |
180154b684 | ||
![]() |
a4f58eb19b | ||
![]() |
fada483d55 | ||
![]() |
3ae9ba3d61 | ||
![]() |
15102fe818 | ||
![]() |
8864bb2a5e | ||
![]() |
ef1cdd5b20 | ||
![]() |
35f4f34342 | ||
![]() |
1a8134459a | ||
![]() |
a6ce3a5068 | ||
![]() |
328b20f78b | ||
![]() |
771712da99 | ||
![]() |
65e0e10db6 | ||
![]() |
62e0e53354 | ||
![]() |
a5461a488a | ||
![]() |
192dd0c4c7 | ||
![]() |
c49755c0eb | ||
![]() |
c8c758958d | ||
![]() |
e068f1944f | ||
![]() |
97412a3736 | ||
![]() |
9167d53a1a | ||
![]() |
6436a17036 | ||
![]() |
5ab5dbe940 | ||
![]() |
d68ab0d010 | ||
![]() |
f70a1f5730 | ||
![]() |
85106a01d7 | ||
![]() |
90e99e241a | ||
![]() |
3f61ab8299 | ||
![]() |
f685a4dceb | ||
![]() |
67b794ce2b | ||
![]() |
e8dad29e5d | ||
![]() |
13a3f66db3 | ||
![]() |
dc9e6081c5 | ||
![]() |
26f8c03570 | ||
![]() |
97e0f36f09 | ||
![]() |
27e49b10fd | ||
![]() |
97dc8d12f1 | ||
![]() |
9b13552b73 | ||
![]() |
d8559637a5 | ||
![]() |
00a90a14dc | ||
![]() |
d56afb034b | ||
![]() |
0327ba37f1 | ||
![]() |
12a54e58b5 | ||
![]() |
238250e8c9 | ||
![]() |
041bfc6cc0 | ||
![]() |
8a4866cb62 | ||
![]() |
0e4d609bbf | ||
![]() |
f07b12bd87 | ||
![]() |
0413dbffa2 | ||
![]() |
c214b48409 | ||
![]() |
91a6366548 | ||
![]() |
03c9932b8c | ||
![]() |
ea4919a25d | ||
![]() |
f98b174857 | ||
![]() |
c0aeb0d2f3 | ||
![]() |
fcb627aac6 | ||
![]() |
7f0aea29cd | ||
![]() |
f6dcbb6594 | ||
![]() |
b790421693 | ||
![]() |
f5a7799924 | ||
![]() |
b052b5bd66 | ||
![]() |
12d8de1def | ||
![]() |
9303483470 | ||
![]() |
f8adc86a0e | ||
![]() |
db57c258c5 | ||
![]() |
ddb2760c16 | ||
![]() |
14d267a95a | ||
![]() |
a6c4053896 | ||
![]() |
949a68ec1d | ||
![]() |
93333a8c48 | ||
![]() |
da48c059ec | ||
![]() |
ee5566d1ef | ||
![]() |
b794b30346 | ||
![]() |
0db6393bb0 | ||
![]() |
fcc3c55110 | ||
![]() |
328c07eaf4 | ||
![]() |
b004ec048e | ||
![]() |
b9f83875a0 | ||
![]() |
8c869d082b | ||
![]() |
043f8210ba | ||
![]() |
41a79caf83 | ||
![]() |
0427fa6087 | ||
![]() |
2f3c912dbe | ||
![]() |
219a7443c0 | ||
![]() |
6deb408d80 | ||
![]() |
c6e1ff2164 | ||
![]() |
bc0918a115 | ||
![]() |
55ff9173be | ||
![]() |
d4d548846f | ||
![]() |
ef4527f140 | ||
![]() |
0b1e7242bb | ||
![]() |
30b6ac2a06 | ||
![]() |
a7fa7cb5e4 | ||
![]() |
f3e87f9016 | ||
![]() |
a983af6c28 | ||
![]() |
114c841f0c | ||
![]() |
e271048577 | ||
![]() |
b8c5925e82 | ||
![]() |
9bda6c8869 | ||
![]() |
d1608d308c | ||
![]() |
b8e1e1d33a | ||
![]() |
8099a037e7 | ||
![]() |
af23c932a6 | ||
![]() |
4edabbb186 | ||
![]() |
37a5bea79b | ||
![]() |
40cdc7d713 | ||
![]() |
49825aca48 | ||
![]() |
1d57c4e705 | ||
![]() |
87ae5787ee | ||
![]() |
20f16c25a3 | ||
![]() |
6f1ec79d9b | ||
![]() |
18c7eea89c | ||
![]() |
f73060aeb6 | ||
![]() |
2f653b83b6 | ||
![]() |
445dec907d | ||
![]() |
927316d24b | ||
![]() |
3957453ed6 | ||
![]() |
0296c704cb | ||
![]() |
1e7fe972de | ||
![]() |
c95bc656ea | ||
![]() |
a082d95b04 | ||
![]() |
6866dd4801 | ||
![]() |
2186da416e | ||
![]() |
22d859fcde | ||
![]() |
39514b69b3 | ||
![]() |
c384736840 | ||
![]() |
507657f273 | ||
![]() |
60641742ed | ||
![]() |
0fc6f07986 | ||
![]() |
1b2bdc0580 | ||
![]() |
9bac239f77 | ||
![]() |
371acb2d2a | ||
![]() |
454f82e139 | ||
![]() |
e8da249353 | ||
![]() |
c7950c53da | ||
![]() |
b5502478e4 | ||
![]() |
4480a7e486 | ||
![]() |
7c7dff743b | ||
![]() |
c568cd3f2e | ||
![]() |
6ec2bc6f21 | ||
![]() |
af3b6f3a97 | ||
![]() |
d855118610 | ||
![]() |
c9992d9fe8 | ||
![]() |
85fe2636cc | ||
![]() |
35f4a31a76 | ||
![]() |
1e494ebb70 | ||
![]() |
ed93627505 | ||
![]() |
b9b4b0036f | ||
![]() |
4aa31424d6 | ||
![]() |
8a825227cb | ||
![]() |
cc1b581d7e | ||
![]() |
9936d90ae2 | ||
![]() |
df1a241b2b | ||
![]() |
ae89b33fb7 | ||
![]() |
e05b483f5c | ||
![]() |
715f536b23 | ||
![]() |
930813fb8a | ||
![]() |
acd5e9b998 | ||
![]() |
06011bf4ae | ||
![]() |
30e15b813c | ||
![]() |
fcd7a7f349 | ||
![]() |
42ef40439e | ||
![]() |
098beb14fe | ||
![]() |
0b186a754a | ||
![]() |
d00963b53d | ||
![]() |
e282af0e80 | ||
![]() |
630361849c | ||
![]() |
88a1de50ca | ||
![]() |
d8263d0b6a | ||
![]() |
611ab0f100 | ||
![]() |
70c307b796 | ||
![]() |
054a233ad6 | ||
![]() |
55268f1c43 | ||
![]() |
1bec6d281c | ||
![]() |
f17a02be54 | ||
![]() |
4e8fdd2225 | ||
![]() |
59819b4a96 | ||
![]() |
673378d8d9 | ||
![]() |
30044d6b21 | ||
![]() |
ee43d40680 | ||
![]() |
1354faf8c7 | ||
![]() |
1bfb3781ab | ||
![]() |
d7d0c6f822 | ||
![]() |
2bea18dc3c | ||
![]() |
f998f2d956 | ||
![]() |
faa77ee5fb | ||
![]() |
88ec463284 | ||
![]() |
b7df71d7d9 | ||
![]() |
6a28dbd2c4 | ||
![]() |
010f7fa1fe | ||
![]() |
209f98594f | ||
![]() |
54121c99a3 | ||
![]() |
f6f1370edf | ||
![]() |
d5863485f9 | ||
![]() |
afc88d316b | ||
![]() |
b141279811 | ||
![]() |
3c8afb0609 | ||
![]() |
1997ea25d5 | ||
![]() |
f4b49eecd4 | ||
![]() |
a4493ec964 | ||
![]() |
af8bda9e92 | ||
![]() |
06d252e4ca | ||
![]() |
67be456bb0 | ||
![]() |
aa5e225148 | ||
![]() |
367f46fac8 | ||
![]() |
d2f14093ec | ||
![]() |
43ed621879 | ||
![]() |
15c8134d13 | ||
![]() |
c2b8f71467 | ||
![]() |
a6b91c3a14 | ||
![]() |
164cfbfd0d | ||
![]() |
0bb340e96e | ||
![]() |
f0447dc455 | ||
![]() |
626bbfa7a4 | ||
![]() |
169a900f01 | ||
![]() |
d0992eaf54 | ||
![]() |
fc21d757c3 | ||
![]() |
54363ee919 | ||
![]() |
fdad3b9997 | ||
![]() |
4ad826ebe8 | ||
![]() |
f5e1e9fdd9 | ||
![]() |
82b232d0e5 | ||
![]() |
c8c1fe5367 | ||
![]() |
71128e0244 | ||
![]() |
453bcaa1f6 | ||
![]() |
48898ab1d4 | ||
![]() |
a095520d0d | ||
![]() |
2e0c6fa6a5 | ||
![]() |
bfbc0861df | ||
![]() |
3a500f3f28 | ||
![]() |
df8094c39c | ||
![]() |
448fd0e884 | ||
![]() |
4717b4549e | ||
![]() |
57a8d72f1c | ||
![]() |
7e57617e04 | ||
![]() |
37ddd643ac | ||
![]() |
bcf3fef303 | ||
![]() |
7ac4d24106 | ||
![]() |
93e5bce778 | ||
![]() |
d48beba307 | ||
![]() |
760338496c | ||
![]() |
b52e7a3078 | ||
![]() |
78c5b6b2a5 | ||
![]() |
60a3c38951 | ||
![]() |
4763033f24 | ||
![]() |
3b0570d21c | ||
![]() |
16bf478d1a | ||
![]() |
5bf181b6d1 | ||
![]() |
21b2e5d194 | ||
![]() |
759afcf3ca | ||
![]() |
d48c7844a4 | ||
![]() |
7d8caa8df7 | ||
![]() |
62f53930da | ||
![]() |
9a45cbb679 | ||
![]() |
8e5a10f6d8 | ||
![]() |
10c57d2272 | ||
![]() |
67d4d0f898 | ||
![]() |
97e0d04842 | ||
![]() |
3ba30ede92 | ||
![]() |
1035e411ab | ||
![]() |
d5ae4b7ec9 | ||
![]() |
111d040cf9 | ||
![]() |
8cc594d170 | ||
![]() |
d8a8bed68d | ||
![]() |
eedbd954bd | ||
![]() |
0eb8366027 | ||
![]() |
894135104b | ||
![]() |
7b2e408efc | ||
![]() |
e4115c122e | ||
![]() |
537b16949e | ||
![]() |
ca60ceb2a7 | ||
![]() |
0fad12fea5 | ||
![]() |
6cd2c23aac | ||
![]() |
512baaa43f | ||
![]() |
d097fcc973 | ||
![]() |
621dbd459c | ||
![]() |
840ab4b0c4 | ||
![]() |
904be34a87 | ||
![]() |
b7fc6fcc38 | ||
![]() |
55c6e40d6d | ||
![]() |
4dfb015057 | ||
![]() |
e40a0ba2bb | ||
![]() |
fd48f10df9 | ||
![]() |
6a54e7fef7 | ||
![]() |
5c4d6ed140 | ||
![]() |
9ed1be3594 | ||
![]() |
c5ce582678 | ||
![]() |
2050083bce | ||
![]() |
92e6bdb562 | ||
![]() |
93e70c38b7 | ||
![]() |
45b96179a5 | ||
![]() |
a29a534a40 | ||
![]() |
8e2297359c | ||
![]() |
92ba7248ef | ||
![]() |
f657d37cbd | ||
![]() |
9e312f60bf | ||
![]() |
85f72b78f7 | ||
![]() |
40acb67ceb | ||
![]() |
3ae8100bda | ||
![]() |
1a3dc41edf | ||
![]() |
27f9b8a04e | ||
![]() |
86669a491a | ||
![]() |
b111d33b04 | ||
![]() |
ea5720d1c8 | ||
![]() |
53675122c6 | ||
![]() |
4ba7997bc1 | ||
![]() |
19c446d267 | ||
![]() |
1abb9ac378 | ||
![]() |
f9c7492726 | ||
![]() |
6ece6ca52a | ||
![]() |
f6a8e9d2fa | ||
![]() |
878de34546 | ||
![]() |
7b97ef316d | ||
![]() |
aafa87c661 | ||
![]() |
26eb2e4381 | ||
![]() |
4b08ea7a89 | ||
![]() |
7f1f2d0039 | ||
![]() |
0227762ddc | ||
![]() |
ff0de8afc2 | ||
![]() |
ddf66ef061 | ||
![]() |
52ecfba0a5 | ||
![]() |
e123ff1bec | ||
![]() |
45753583ee | ||
![]() |
5a77c481a2 | ||
![]() |
4e796542d7 | ||
![]() |
ae42c227a8 | ||
![]() |
fc58035bbf | ||
![]() |
834c4fc5f4 | ||
![]() |
33fcffd2bd | ||
![]() |
18b83e2ed8 | ||
![]() |
f05b39736c | ||
![]() |
31a293c5c0 | ||
![]() |
1e6952c86a | ||
![]() |
21ad38d33f | ||
![]() |
1589a05a37 | ||
![]() |
3f19e5d465 | ||
![]() |
5e9bd98bba | ||
![]() |
d626d98421 | ||
![]() |
bce74a408c | ||
![]() |
30c5b2d1c9 | ||
![]() |
95a150f7d8 | ||
![]() |
45d31d2358 | ||
![]() |
fb59dfc677 | ||
![]() |
30303f50ac | ||
![]() |
a2fa133831 | ||
![]() |
d735dcea05 | ||
![]() |
a96fcabba5 | ||
![]() |
21fd59c196 | ||
![]() |
15f126416f | ||
![]() |
7f1f9f81a6 | ||
![]() |
de6b77baba | ||
![]() |
c8e3a3d258 | ||
![]() |
52ef24ae7b | ||
![]() |
1553173300 | ||
![]() |
f5b2c24ee3 | ||
![]() |
2ddbc6bbac | ||
![]() |
eae7189981 | ||
![]() |
f292b3637d | ||
![]() |
aff0b361a2 | ||
![]() |
9f78b86c57 | ||
![]() |
4950627850 | ||
![]() |
5265f3eb6a | ||
![]() |
3cca5e8e9a | ||
![]() |
e9ca109c57 | ||
![]() |
344da53888 | ||
![]() |
62ae3c4c4b | ||
![]() |
6f95eb3c3f | ||
![]() |
f350a86946 | ||
![]() |
868e529e62 | ||
![]() |
62d82c88a1 | ||
![]() |
a86e995113 | ||
![]() |
5e2c7e89ab | ||
![]() |
4a38906194 | ||
![]() |
cc3e6d97dd | ||
![]() |
90d6fb56d1 | ||
![]() |
9b5cf3f636 | ||
![]() |
3723abbbbb | ||
![]() |
a626427788 | ||
![]() |
35d88f8c78 | ||
![]() |
c65872b29b | ||
![]() |
e472d34f4d | ||
![]() |
1257596104 | ||
![]() |
5dd6519d27 | ||
![]() |
e607577407 | ||
![]() |
ade12e729f | ||
![]() |
eee83ebb94 | ||
![]() |
39ff47e866 | ||
![]() |
6c81a506e9 | ||
![]() |
a24620de31 | ||
![]() |
70de47408a | ||
![]() |
04103d1c84 | ||
![]() |
d20102c3bd | ||
![]() |
f165ee32e5 | ||
![]() |
60ad2e81f3 | ||
![]() |
5ca8b642da | ||
![]() |
f40cd7f26c | ||
![]() |
e04b519e9b | ||
![]() |
658e59bed6 | ||
![]() |
cb5eb19abc | ||
![]() |
d336531ca8 | ||
![]() |
30ee71f4e3 | ||
![]() |
844d5b33bc | ||
![]() |
e3741f1c75 | ||
![]() |
21a6e4d8c6 | ||
![]() |
ec14ba76c9 | ||
![]() |
90e7b1e9c7 | ||
![]() |
a09d943344 | ||
![]() |
52ac40c826 | ||
![]() |
8f8eb64364 | ||
![]() |
fe40ab0ab4 | ||
![]() |
5991ef820f | ||
![]() |
d67c2a90b1 | ||
![]() |
e85d6fbc3b | ||
![]() |
62a9604bd2 | ||
![]() |
0aae2174c1 | ||
![]() |
b66bd6fec9 | ||
![]() |
b399a3f5ad | ||
![]() |
1f5927eec0 | ||
![]() |
2d838e7003 | ||
![]() |
f242c30476 | ||
![]() |
2cf204ff79 | ||
![]() |
38fc9e97bb | ||
![]() |
3e4accb82c | ||
![]() |
b905283b61 | ||
![]() |
c7e5df5c91 | ||
![]() |
99006d7923 | ||
![]() |
16320b4486 | ||
![]() |
d70b0c0c3f | ||
![]() |
41cebc554f | ||
![]() |
6a2c863fcc | ||
![]() |
92e0fc2847 | ||
![]() |
9978a11c52 | ||
![]() |
cf77623e9c | ||
![]() |
7ce4acc687 | ||
![]() |
ffbac126bd | ||
![]() |
0f11b02047 | ||
![]() |
b8cf731dd0 | ||
![]() |
ad5afac174 | ||
![]() |
cf69273de1 | ||
![]() |
13279a915d | ||
![]() |
3defe2d343 | ||
![]() |
2c86414e74 | ||
![]() |
9e4f816009 | ||
![]() |
b48afde7f1 | ||
![]() |
13cdaadcf7 | ||
![]() |
44fc1c4532 | ||
![]() |
ddb1ecaa99 | ||
![]() |
50ada5f95b | ||
![]() |
40ba9e8434 | ||
![]() |
d6f9b81de6 | ||
![]() |
b085d94fea | ||
![]() |
90343e1e39 | ||
![]() |
883d8f31c4 | ||
![]() |
2e18c5a668 | ||
![]() |
c1ca104021 | ||
![]() |
e7db4e9326 | ||
![]() |
203a42eb1b | ||
![]() |
c83f20983b | ||
![]() |
25f504cadf | ||
![]() |
07ce718e3c | ||
![]() |
83264b5973 | ||
![]() |
1acf1547d5 | ||
![]() |
5d3de35c10 | ||
![]() |
8f8d613f6e | ||
![]() |
6a161b3c97 | ||
![]() |
3e97572100 | ||
![]() |
fc3b6fd1e0 | ||
![]() |
9bc7f9ac11 | ||
![]() |
0a2f252405 | ||
![]() |
09bc658f97 | ||
![]() |
7b04202a00 | ||
![]() |
acf364166b | ||
![]() |
4e88efae94 | ||
![]() |
8df24dc1c4 | ||
![]() |
8482c27689 | ||
![]() |
d1265dc1f2 | ||
![]() |
47d395de71 | ||
![]() |
5b443e02a3 | ||
![]() |
f8a7d52b1d | ||
![]() |
a133a96819 | ||
![]() |
c71b8f994c | ||
![]() |
9b02c97926 | ||
![]() |
ab06efc934 | ||
![]() |
928b73f139 | ||
![]() |
a36fb09bc3 | ||
![]() |
eaed4b76aa | ||
![]() |
6d8960f089 | ||
![]() |
ca3b6d0705 | ||
![]() |
c2e7931ea6 | ||
![]() |
d1a5d8cba9 | ||
![]() |
c2f91e6867 | ||
![]() |
55e32b8d88 | ||
![]() |
462b1df767 | ||
![]() |
d17d2c8417 | ||
![]() |
6892832fff | ||
![]() |
66d54c7c45 | ||
![]() |
d432685aa8 | ||
![]() |
37f3d76fb8 | ||
![]() |
7961a74995 | ||
![]() |
9d590508ad | ||
![]() |
f79b7eaf83 | ||
![]() |
ae13bf946f | ||
![]() |
f116c4f1f4 | ||
![]() |
867c8920a8 | ||
![]() |
6e6dd34872 | ||
![]() |
0759468fa7 | ||
![]() |
1b1fb09211 | ||
![]() |
de414c912c | ||
![]() |
d274a2fed1 | ||
![]() |
285b7e9b9e | ||
![]() |
875efcff7e | ||
![]() |
07ae37167d | ||
![]() |
f689f4d427 | ||
![]() |
19bc2b8b37 | ||
![]() |
673116e27e | ||
![]() |
59fcb0a050 | ||
![]() |
cd76f99bbf | ||
![]() |
6a4994b9c2 | ||
![]() |
63960c5e05 | ||
![]() |
540afb6a28 | ||
![]() |
ae10b8abbd | ||
![]() |
db2ebab879 | ||
![]() |
6ec3d062df | ||
![]() |
86b6060a09 | ||
![]() |
83d123e341 | ||
![]() |
34061695f9 | ||
![]() |
de68476442 | ||
![]() |
678a81a44b | ||
![]() |
cfb3096d53 | ||
![]() |
9b7aca745a | ||
![]() |
82852389fa | ||
![]() |
ce06084e6f | ||
![]() |
3ca051983f | ||
![]() |
cd379e4175 | ||
![]() |
62fdfa2b6f | ||
![]() |
9866017f7e | ||
![]() |
67f98b08c6 | ||
![]() |
fdb5f7ec02 | ||
![]() |
04c3c7ca6e | ||
![]() |
f424315d97 | ||
![]() |
c907a8df37 | ||
![]() |
37ea65e3fc | ||
![]() |
a3e5f824c8 | ||
![]() |
e0c850a455 | ||
![]() |
1c6815f708 | ||
![]() |
9a20511935 | ||
![]() |
965f5e73d9 | ||
![]() |
13b58a1d56 | ||
![]() |
0a3261b8b3 | ||
![]() |
dbdfc7fdd8 | ||
![]() |
56062f5bfa | ||
![]() |
0cbba2eb45 | ||
![]() |
aa84356dd6 | ||
![]() |
efaad0a4dd | ||
![]() |
71015c0137 | ||
![]() |
85b5667a7e | ||
![]() |
dfdc6817a1 | ||
![]() |
058345b9c9 | ||
![]() |
831b7876b4 | ||
![]() |
729cf6f08e | ||
![]() |
860a16b32d | ||
![]() |
9f871c077b | ||
![]() |
a8f89abf7d | ||
![]() |
16102de619 | ||
![]() |
472e768369 | ||
![]() |
131a769c26 | ||
![]() |
4a0a6c54e4 | ||
![]() |
c83abe57d5 | ||
![]() |
c6e2519dcc | ||
![]() |
74db524db6 | ||
![]() |
810976d976 | ||
![]() |
eb0540b5cb | ||
![]() |
124437fd73 | ||
![]() |
69b512e3d1 | ||
![]() |
29d74e14bd | ||
![]() |
f42ec8435a | ||
![]() |
1052b824db | ||
![]() |
0742a6a74c | ||
![]() |
d4e9e1730f | ||
![]() |
4eeaa54a47 | ||
![]() |
5fa7409317 | ||
![]() |
0bcd190714 | ||
![]() |
563f08b0ab | ||
![]() |
1b75424604 | ||
![]() |
01ac26e67b | ||
![]() |
434ddd1342 | ||
![]() |
3925496595 | ||
![]() |
5711c02170 | ||
![]() |
ca1c691bf0 | ||
![]() |
39c8a743bb | ||
![]() |
14cd548dff | ||
![]() |
b72324805f | ||
![]() |
a049effa61 | ||
![]() |
23d55ec571 | ||
![]() |
385fe21d16 | ||
![]() |
399ae7e3dc | ||
![]() |
22726f8566 | ||
![]() |
d789d08f31 | ||
![]() |
07863fed6f | ||
![]() |
dcd355851d | ||
![]() |
aa161b5b0e | ||
![]() |
99ab9d586f | ||
![]() |
33c009befe | ||
![]() |
64019dccf7 | ||
![]() |
e3bb607303 | ||
![]() |
0b211c4f12 | ||
![]() |
38d0a173af | ||
![]() |
31b502bb6c | ||
![]() |
fa99b7fd11 | ||
![]() |
9c5653b52e | ||
![]() |
88ad8523a0 | ||
![]() |
a15f59fbd1 | ||
![]() |
bf73c75872 | ||
![]() |
dd99771c0b | ||
![]() |
01657ca002 | ||
![]() |
f2b3603531 | ||
![]() |
d6d73b19ec | ||
![]() |
2ad8a308b3 | ||
![]() |
81c6275255 | ||
![]() |
cfc5db2fe8 | ||
![]() |
5e90e9aa71 | ||
![]() |
debb0b1507 | ||
![]() |
188470a043 | ||
![]() |
f452a1b81c | ||
![]() |
42f70da162 | ||
![]() |
4e8b80822b | ||
![]() |
7ce7859a5f | ||
![]() |
13b970f4e8 | ||
![]() |
054426c9cc | ||
![]() |
10c439afad | ||
![]() |
46dd543b48 | ||
![]() |
28e0f3487c | ||
![]() |
ca10ee2fe5 | ||
![]() |
3e99c111bd | ||
![]() |
843a8e4298 | ||
![]() |
454e8caa0d | ||
![]() |
e38dc011bd | ||
![]() |
9aef3d56df | ||
![]() |
8c099bc137 | ||
![]() |
de82bc7e4d | ||
![]() |
5166228915 | ||
![]() |
35ed31f6b9 | ||
![]() |
05ce790587 | ||
![]() |
ff7f015146 | ||
![]() |
e2150e3018 | ||
![]() |
bbf8f05d3c | ||
![]() |
36c810fdbe | ||
![]() |
7822810b91 | ||
![]() |
9fefae3da3 | ||
![]() |
74ce9cd38d | ||
![]() |
bfcbeb7140 | ||
![]() |
5d3bebfdce | ||
![]() |
b8f58328cb | ||
![]() |
3540b09623 | ||
![]() |
25744037f5 | ||
![]() |
0395598efb | ||
![]() |
f44b64fcc5 | ||
![]() |
2a7535920e | ||
![]() |
9e6741d542 | ||
![]() |
0e5a32b253 | ||
![]() |
929287a553 | ||
![]() |
a0fe24ada0 | ||
![]() |
dd34e7d008 | ||
![]() |
92fb83ccf9 | ||
![]() |
b32ebe4479 | ||
![]() |
e138ca6eab | ||
![]() |
cf8afc03bc | ||
![]() |
8dc358b075 | ||
![]() |
24ab2e7795 | ||
![]() |
3f85825c4a | ||
![]() |
c03eca3804 | ||
![]() |
f79263e628 | ||
![]() |
e91b4fcf8b | ||
![]() |
0b7f9a08ef | ||
![]() |
440b76d302 | ||
![]() |
c433a615db | ||
![]() |
7b5269a1fe | ||
![]() |
33cfaef454 | ||
![]() |
fe62c93602 | ||
![]() |
bdc0ceb11d | ||
![]() |
b35df5ef11 | ||
![]() |
b59887d4e0 | ||
![]() |
da9ccf6d29 | ||
![]() |
6b80d7cbd0 | ||
![]() |
0e17a70193 | ||
![]() |
6ff439b20d | ||
![]() |
70d35e12e5 | ||
![]() |
7561087c78 | ||
![]() |
42b56fa4a2 | ||
![]() |
fb945470c0 | ||
![]() |
4f9b9c5f7b | ||
![]() |
3b273440cc | ||
![]() |
b0fb87acdb | ||
![]() |
ea36e8e9bd | ||
![]() |
0875d13737 | ||
![]() |
39050cdee5 | ||
![]() |
7594fdd578 | ||
![]() |
93d5596942 | ||
![]() |
93fcc0deb7 | ||
![]() |
f6b50fbb58 | ||
![]() |
cf0aa2788d | ||
![]() |
67fbb96cd9 | ||
![]() |
ed8ca00a85 | ||
![]() |
7b3e2a9ea0 | ||
![]() |
7686c451e6 | ||
![]() |
7eaa4caae2 | ||
![]() |
931d09d0b0 | ||
![]() |
554faf06a1 | ||
![]() |
38c5f5d7f6 | ||
![]() |
015416f2a8 | ||
![]() |
2730c73413 | ||
![]() |
bbaa405c59 | ||
![]() |
6127e574db | ||
![]() |
1b53c35ec5 | ||
![]() |
359fd4efed | ||
![]() |
f7412fea7f | ||
![]() |
f0bf6b8b81 | ||
![]() |
7a06593821 | ||
![]() |
ddf4fb0b46 | ||
![]() |
535d608829 | ||
![]() |
18e469af71 | ||
![]() |
ce921b9b85 | ||
![]() |
bb0a366ef1 | ||
![]() |
fabacfdcca | ||
![]() |
648699547e | ||
![]() |
c8c933fb20 | ||
![]() |
870a429f3d | ||
![]() |
23a9f24d52 | ||
![]() |
48a2ae3599 | ||
![]() |
04f3ce4d64 | ||
![]() |
57a70aa777 | ||
![]() |
cfdde4483f | ||
![]() |
c568a1f571 | ||
![]() |
74639e2b03 | ||
![]() |
a849f0e8a2 | ||
![]() |
ca022e1d8a | ||
![]() |
bc82f7edf6 | ||
![]() |
46d0459070 | ||
![]() |
0a578e9a28 | ||
![]() |
4c6b467847 | ||
![]() |
92880d40cf | ||
![]() |
d2f06a256f | ||
![]() |
293afca964 | ||
![]() |
b8304e7441 | ||
![]() |
d1164c8acd | ||
![]() |
9a3ab838b7 | ||
![]() |
e0a1a9a2ab | ||
![]() |
7da3101678 | ||
![]() |
81a67f9dcc | ||
![]() |
fef69da3cc | ||
![]() |
783734bf9e | ||
![]() |
4d8f43dde4 | ||
![]() |
982a12b5c1 | ||
![]() |
fd034128e8 | ||
![]() |
fea51fc493 | ||
![]() |
d7b2369a32 | ||
![]() |
2c4e0e3121 | ||
![]() |
2ae6d2a4a0 | ||
![]() |
0bf2026a64 | ||
![]() |
b17675ec0c | ||
![]() |
1a74c2a174 | ||
![]() |
07d4616974 | ||
![]() |
8d86f9c7af | ||
![]() |
54b56768c1 | ||
![]() |
c8f24611ba | ||
![]() |
0b0cd4c76e | ||
![]() |
f4b997b41f | ||
![]() |
ce0f2f74df | ||
![]() |
7d136d9d77 | ||
![]() |
26c801ebee | ||
![]() |
165a804ba9 | ||
![]() |
2d0f94a3a2 | ||
![]() |
eb9ec3e0de | ||
![]() |
b844914654 | ||
![]() |
5edd4d5922 | ||
![]() |
6b93ea25c6 | ||
![]() |
3a6087e421 | ||
![]() |
2870931481 | ||
![]() |
0cea6af5b1 | ||
![]() |
e344be0fa1 | ||
![]() |
4cbb573d17 | ||
![]() |
e95d9ee514 | ||
![]() |
a785db4d47 | ||
![]() |
76d39ac623 | ||
![]() |
1bdee7857c | ||
![]() |
3827aeb9b4 | ||
![]() |
4b5c14cbd5 | ||
![]() |
003ffa2251 |
BIN
.github/apk-badge.png
vendored
Normal file
BIN
.github/apk-badge.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
.github/google-play-badge.png
vendored
Normal file
BIN
.github/google-play-badge.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
.github/readme-banner.png
vendored
Normal file
BIN
.github/readme-banner.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
2
.github/utils/.gitignore
vendored
Normal file
2
.github/utils/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.env
|
||||
__pycache__/
|
55
.github/utils/_get_password.py
vendored
Normal file
55
.github/utils/_get_password.py
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
import base64
|
||||
import secrets
|
||||
from hashlib import sha256
|
||||
from typing import Tuple
|
||||
|
||||
import mysql.connector as mysql
|
||||
from Crypto.Cipher import AES
|
||||
|
||||
|
||||
def get_password(
|
||||
version_name: str,
|
||||
version_code: int,
|
||||
db_host: str,
|
||||
db_user: str,
|
||||
db_pass: str,
|
||||
db_name: str,
|
||||
) -> Tuple[str, bytes]:
|
||||
db = mysql.connect(
|
||||
host=db_host,
|
||||
user=db_user,
|
||||
password=db_pass,
|
||||
database=db_name,
|
||||
auth_plugin="mysql_native_password",
|
||||
)
|
||||
|
||||
password = base64.b64encode(secrets.token_bytes(16)).decode()
|
||||
iv = secrets.token_bytes(16)
|
||||
|
||||
key = f"{version_name}.{password}.{version_code}"
|
||||
key = sha256(key.encode()).digest()
|
||||
data = "ThisIsOurHardWorkPleaseDoNotCopyOrSteal(c)2019.KubaSz"
|
||||
data = sha256(data.encode()).digest()
|
||||
data = data + (chr(16) * 16).encode()
|
||||
|
||||
aes = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
|
||||
|
||||
app_password = base64.b64encode(aes.encrypt(data)).decode()
|
||||
|
||||
c = db.cursor()
|
||||
c.execute(
|
||||
"INSERT IGNORE INTO _appPasswords (versionCode, appPassword, password, iv) VALUES (%s, %s, %s, %s);",
|
||||
(version_code, app_password, password, iv),
|
||||
)
|
||||
db.commit()
|
||||
|
||||
c = db.cursor()
|
||||
c.execute(
|
||||
"SELECT password, iv FROM _appPasswords WHERE versionCode = %s;",
|
||||
(version_code,),
|
||||
)
|
||||
row = c.fetchone()
|
||||
|
||||
db.close()
|
||||
|
||||
return (row[0], row[1])
|
144
.github/utils/_utils.py
vendored
Normal file
144
.github/utils/_utils.py
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import Tuple
|
||||
|
||||
VERSION_NAME_REGEX = r'versionName: "(.+?)"'
|
||||
VERSION_CODE_REGEX = r"versionCode: ([0-9]+)"
|
||||
VERSION_NAME_FORMAT = 'versionName: "{}"'
|
||||
VERSION_CODE_FORMAT = "versionCode: {}"
|
||||
|
||||
|
||||
def get_project_dir() -> str:
|
||||
project_dir = sys.argv[1]
|
||||
if project_dir[-1:] == "/" or project_dir[-1:] == "\\":
|
||||
project_dir = project_dir[:-1]
|
||||
return project_dir
|
||||
|
||||
|
||||
def read_gradle_version(project_dir: str) -> Tuple[int, str]:
|
||||
GRADLE_PATH = f"{project_dir}/build.gradle"
|
||||
|
||||
with open(GRADLE_PATH, "r") as f:
|
||||
gradle = f.read()
|
||||
|
||||
version_name = re.search(VERSION_NAME_REGEX, gradle).group(1)
|
||||
version_code = int(re.search(VERSION_CODE_REGEX, gradle).group(1))
|
||||
|
||||
return (version_code, version_name)
|
||||
|
||||
|
||||
def write_gradle_version(project_dir: str, version_code: int, version_name: str):
|
||||
GRADLE_PATH = f"{project_dir}/build.gradle"
|
||||
|
||||
with open(GRADLE_PATH, "r") as f:
|
||||
gradle = f.read()
|
||||
|
||||
gradle = re.sub(
|
||||
VERSION_NAME_REGEX, VERSION_NAME_FORMAT.format(version_name), gradle
|
||||
)
|
||||
gradle = re.sub(
|
||||
VERSION_CODE_REGEX, VERSION_CODE_FORMAT.format(version_code), gradle
|
||||
)
|
||||
|
||||
with open(GRADLE_PATH, "w") as f:
|
||||
f.write(gradle)
|
||||
|
||||
|
||||
def build_version_code(version_name: str) -> int:
|
||||
version = version_name.split("+")[0].split("-")
|
||||
version_base = version[0]
|
||||
version_suffix = version[1] if len(version) == 2 else ""
|
||||
|
||||
base_parts = version_base.split(".")
|
||||
major = int(base_parts[0]) or 0
|
||||
minor = int(base_parts[1]) if len(base_parts) > 1 else 0
|
||||
patch = int(base_parts[2]) if len(base_parts) > 2 else 0
|
||||
|
||||
beta = 9
|
||||
rc = 9
|
||||
if "dev" in version_suffix:
|
||||
beta = 0
|
||||
rc = 0
|
||||
elif "beta." in version_suffix:
|
||||
beta = int(version_suffix.split(".")[1])
|
||||
rc = 0
|
||||
elif "rc." in version_suffix:
|
||||
beta = 0
|
||||
rc = int(version_suffix.split(".")[1])
|
||||
|
||||
version_code = beta + rc * 10 + patch * 100 + minor * 10000 + major * 1000000
|
||||
return version_code
|
||||
|
||||
|
||||
def get_changelog(project_dir: str, format: str) -> Tuple[str, str]:
|
||||
with open(
|
||||
f"{project_dir}/app/src/main/assets/pl-changelog.html", "r", encoding="utf-8"
|
||||
) as f:
|
||||
changelog = f.read()
|
||||
|
||||
title = re.search(r"<h3>(.+?)</h3>", changelog).group(1)
|
||||
content = re.search(r"(?s)<ul>(.+)</ul>", changelog).group(1).strip()
|
||||
content = "\n".join(line.strip() for line in content.split("\n"))
|
||||
|
||||
if format != "html":
|
||||
content = content.replace("<li>", "- ")
|
||||
content = content.replace("<br>", "\n")
|
||||
if format == "markdown":
|
||||
content = re.sub(r"<u>(.+?)</u>", "__\\1__", content)
|
||||
content = re.sub(r"<i>(.+?)</i>", "*\\1*", content)
|
||||
content = re.sub(r"<b>(.+?)</b>", "**\\1**", content)
|
||||
content = re.sub(r"</?.+?>", "", content)
|
||||
|
||||
return (title, content)
|
||||
|
||||
|
||||
def get_commit_log(project_dir: str, format: str, max_lines: int = None) -> str:
|
||||
last_tag = (
|
||||
subprocess.check_output("git describe --tags --abbrev=0".split(" "))
|
||||
.decode()
|
||||
.strip()
|
||||
)
|
||||
|
||||
log = subprocess.run(
|
||||
args=f"git log {last_tag}..HEAD --format=%an%x00%at%x00%h%x00%s%x00%D".split(
|
||||
" "
|
||||
),
|
||||
cwd=project_dir,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
log = log.stdout.strip().decode()
|
||||
|
||||
commits = [line.split("\x00") for line in log.split("\n")]
|
||||
if max_lines:
|
||||
commits = commits[:max_lines]
|
||||
|
||||
output = []
|
||||
valid = False
|
||||
|
||||
for commit in commits:
|
||||
if not commit[0]:
|
||||
continue
|
||||
if "origin/" in commit[4]:
|
||||
valid = True
|
||||
if not valid:
|
||||
continue
|
||||
date = datetime.fromtimestamp(float(commit[1]))
|
||||
date = date.strftime("%Y-%m-%d %H:%M:%S")
|
||||
if format == "html":
|
||||
output.append(f"<li>{commit[3]} <i> - {commit[0]}</i></li>")
|
||||
elif format == "markdown":
|
||||
output.append(f"[{date}] {commit[0]}\n {commit[3]}")
|
||||
elif format == "markdown_full":
|
||||
output.append(
|
||||
f"_[{date}] {commit[0]}_\n` `__`{commit[2]}`__ **{commit[3]}**"
|
||||
)
|
||||
elif format == "plain":
|
||||
output.append(f"- {commit[3]}")
|
||||
|
||||
if format == "markdown":
|
||||
output.insert(0, "```")
|
||||
output.append("```")
|
||||
|
||||
return "\n".join(output)
|
48
.github/utils/bump_nightly.py
vendored
Normal file
48
.github/utils/bump_nightly.py
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime, timedelta
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from _utils import (
|
||||
get_commit_log,
|
||||
get_project_dir,
|
||||
read_gradle_version,
|
||||
write_gradle_version,
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: bump_nightly.py <project dir>")
|
||||
exit(-1)
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
(version_code, version_name) = read_gradle_version(project_dir)
|
||||
version_name = version_name.split("+")[0]
|
||||
|
||||
date = datetime.now(tz=ZoneInfo("Europe/Warsaw"))
|
||||
if date.hour > 6:
|
||||
version_name += "+daily." + date.strftime("%Y%m%d-%H%M")
|
||||
else:
|
||||
date -= timedelta(days=1)
|
||||
version_name += "+nightly." + date.strftime("%Y%m%d")
|
||||
|
||||
print("appVersionName=" + version_name)
|
||||
print("appVersionCode=" + str(version_code))
|
||||
|
||||
write_gradle_version(project_dir, version_code, version_name)
|
||||
|
||||
commit_log = get_commit_log(project_dir, format="html", max_lines=10)
|
||||
|
||||
with open(
|
||||
f"{project_dir}/app/src/main/assets/pl-changelog.html", "r", encoding="utf-8"
|
||||
) as f:
|
||||
changelog = f.read()
|
||||
|
||||
changelog = re.sub(r"<h3>(.+?)</h3>", f"<h3>{version_name}</h3>", changelog)
|
||||
changelog = re.sub(r"(?s)<ul>(.+)</ul>", f"<ul>\n{commit_log}\n</ul>", changelog)
|
||||
|
||||
with open(
|
||||
f"{project_dir}/app/src/main/assets/pl-changelog.html", "w", encoding="utf-8"
|
||||
) as f:
|
||||
f.write(changelog)
|
41
.github/utils/bump_version.py
vendored
Normal file
41
.github/utils/bump_version.py
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from _get_password import get_password
|
||||
from _utils import build_version_code, write_gradle_version
|
||||
from sign import sign
|
||||
|
||||
if __name__ == "__main__":
|
||||
version_name = input("Enter version name: ")
|
||||
version_code = build_version_code(version_name)
|
||||
|
||||
print(f"Bumping version to {version_name} ({version_code})")
|
||||
|
||||
project_dir = "../.."
|
||||
|
||||
load_dotenv()
|
||||
DB_HOST = os.getenv("DB_HOST")
|
||||
DB_USER = os.getenv("DB_USER")
|
||||
DB_PASS = os.getenv("DB_PASS")
|
||||
DB_NAME = os.getenv("DB_NAME")
|
||||
|
||||
write_gradle_version(project_dir, version_code, version_name)
|
||||
(password, iv) = get_password(
|
||||
version_name, version_code, DB_HOST, DB_USER, DB_PASS, DB_NAME
|
||||
)
|
||||
|
||||
sign(project_dir, version_name, version_code, password, iv, commit=False)
|
||||
|
||||
print("Writing mock passwords")
|
||||
os.chdir(project_dir)
|
||||
os.system(
|
||||
"sed -i -E 's/\/\*([0-9a-f]{2} ?){16}\*\//\/*secret password - removed for source code publication*\//g' app/src/main/cpp/szkolny-signing.cpp"
|
||||
)
|
||||
os.system(
|
||||
"sed -i -E 's/\\t0x.., 0x(.)., 0x.(.), 0x.(.), 0x.., 0x.., 0x.., 0x.(.), 0x.., 0x.(.), 0x(.)., 0x(.)., 0x.., 0x.., 0x.., 0x.(.)/\\t0x\\3\\6, 0x\\7\\4, 0x\\1\\8, 0x\\2\\5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /g' app/src/main/cpp/szkolny-signing.cpp"
|
||||
)
|
||||
os.system(
|
||||
"sed -i -E 's/param1\..(.).(.).(.).(.)..(.)..(.)..(.)..(.).../param1.MTIzNDU2Nzg5MD\\5\\2\\7\\6\\1\\3\\4\8==/g' app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt"
|
||||
)
|
||||
input("Press any key to finish")
|
23
.github/utils/check_nightly.py
vendored
Normal file
23
.github/utils/check_nightly.py
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
import json
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
||||
if __name__ == "__main__":
|
||||
repo = os.getenv("GITHUB_REPOSITORY")
|
||||
sha = os.getenv("GITHUB_SHA")
|
||||
|
||||
if not repo or not sha:
|
||||
print("Missing GitHub environment variables.")
|
||||
exit(-1)
|
||||
|
||||
with requests.get(
|
||||
f"https://api.github.com/repos/{repo}/actions/runs?per_page=5&status=success"
|
||||
) as r:
|
||||
data = json.loads(r.text)
|
||||
runs = [run for run in data["workflow_runs"] if run["head_sha"] == sha]
|
||||
if runs:
|
||||
print("hasNewChanges=false")
|
||||
exit(0)
|
||||
|
||||
print("hasNewChanges=true")
|
71
.github/utils/extract_changelogs.py
vendored
Normal file
71
.github/utils/extract_changelogs.py
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _utils import get_changelog, get_commit_log, get_project_dir, read_gradle_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: extract_changelogs.py <project dir>")
|
||||
exit(-1)
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
(version_code, version_name) = read_gradle_version(project_dir)
|
||||
|
||||
print("appVersionName=" + version_name)
|
||||
print("appVersionCode=" + str(version_code))
|
||||
|
||||
dir = f"{project_dir}/app/release/whatsnew-{version_name}/"
|
||||
os.makedirs(dir, exist_ok=True)
|
||||
|
||||
print("changelogDir=" + dir)
|
||||
|
||||
(title, changelog) = get_changelog(project_dir, format="plain")
|
||||
|
||||
# plain text changelog - Firebase App Distribution
|
||||
with open(dir + "whatsnew_titled.txt", "w", encoding="utf-8") as f:
|
||||
f.write(title)
|
||||
f.write("\n")
|
||||
f.write(changelog)
|
||||
print("changelogPlainTitledFile=" + dir + "whatsnew_titled.txt")
|
||||
|
||||
print("changelogTitle=" + title)
|
||||
|
||||
# plain text changelog, max 500 chars - Google Play
|
||||
with open(dir + "whatsnew-pl-PL", "w", encoding="utf-8") as f:
|
||||
changelog_lines = changelog.split("\n")
|
||||
changelog = ""
|
||||
for line in changelog_lines:
|
||||
if len(changelog) + len(line) < 500:
|
||||
changelog += "\n" + line
|
||||
changelog = changelog.strip()
|
||||
f.write(changelog)
|
||||
|
||||
print("changelogPlainFile=" + dir + "whatsnew-pl-PL")
|
||||
|
||||
# markdown changelog - Discord webhook
|
||||
(_, changelog) = get_changelog(project_dir, format="markdown")
|
||||
with open(dir + "whatsnew.md", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("changelogMarkdownFile=" + dir + "whatsnew.md")
|
||||
|
||||
# html changelog - version info in DB
|
||||
(_, changelog) = get_changelog(project_dir, format="html")
|
||||
with open(dir + "whatsnew.html", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("changelogHtmlFile=" + dir + "whatsnew.html")
|
||||
|
||||
changelog = get_commit_log(project_dir, format="plain", max_lines=10)
|
||||
with open(dir + "commit_log.txt", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("commitLogPlainFile=" + dir + "commit_log.txt")
|
||||
|
||||
changelog = get_commit_log(project_dir, format="markdown", max_lines=10)
|
||||
with open(dir + "commit_log.md", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("commitLogMarkdownFile=" + dir + "commit_log.md")
|
||||
|
||||
changelog = get_commit_log(project_dir, format="html", max_lines=10)
|
||||
with open(dir + "commit_log.html", "w", encoding="utf-8") as f:
|
||||
f.write(changelog)
|
||||
print("commitLogHtmlFile=" + dir + "commit_log.html")
|
26
.github/utils/find_artifacts.py
vendored
Normal file
26
.github/utils/find_artifacts.py
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
|
||||
from _utils import get_project_dir
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: rename_artifacts.py <project dir>")
|
||||
exit(-1)
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
files = glob.glob(f"{project_dir}/app/release/*.*")
|
||||
for file in files:
|
||||
file_relative = file.replace(project_dir + "/", "")
|
||||
if "-aligned.apk" in file:
|
||||
os.unlink(file)
|
||||
elif "-signed.apk" in file:
|
||||
new_file = file.replace("-signed.apk", ".apk")
|
||||
if os.path.isfile(new_file):
|
||||
os.unlink(new_file)
|
||||
os.rename(file, new_file)
|
||||
elif ".apk" in file or ".aab" in file:
|
||||
print("signedReleaseFile=" + file)
|
||||
print("signedReleaseFileRelative=" + file_relative)
|
141
.github/utils/save_version.py
vendored
Normal file
141
.github/utils/save_version.py
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from time import time
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import mysql.connector as mysql
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from _utils import get_changelog, get_commit_log, get_project_dir, read_gradle_version
|
||||
|
||||
|
||||
def save_version(
|
||||
project_dir: str,
|
||||
db_host: str,
|
||||
db_user: str,
|
||||
db_pass: str,
|
||||
db_name: str,
|
||||
apk_server_release: str,
|
||||
apk_server_nightly: str,
|
||||
):
|
||||
db = mysql.connect(
|
||||
host=db_host,
|
||||
user=db_user,
|
||||
password=db_pass,
|
||||
database=db_name,
|
||||
auth_plugin="mysql_native_password",
|
||||
)
|
||||
|
||||
(version_code, version_name) = read_gradle_version(project_dir)
|
||||
(_, changelog) = get_changelog(project_dir, format="html")
|
||||
|
||||
types = ["dev", "beta", "nightly", "daily", "rc", "release"]
|
||||
build_type = [x for x in types if x in version_name]
|
||||
build_type = build_type[0] if build_type else "release"
|
||||
|
||||
if "+nightly." in version_name or "+daily." in version_name:
|
||||
changelog = get_commit_log(project_dir, format="html")
|
||||
build_type = "nightly"
|
||||
elif "-dev" in version_name:
|
||||
build_type = "dev"
|
||||
elif "-beta." in version_name:
|
||||
build_type = "beta"
|
||||
elif "-rc." in version_name:
|
||||
build_type = "rc"
|
||||
|
||||
build_date = int(time())
|
||||
apk_name = None
|
||||
bundle_name_play = None
|
||||
|
||||
files = glob.glob(f"{project_dir}/app/release/*.*")
|
||||
output_apk = f"Edziennik_{version_name}_official.apk"
|
||||
output_aab_play = f"Edziennik_{version_name}_play.aab"
|
||||
for file in files:
|
||||
if output_apk in file:
|
||||
build_date = int(os.stat(file).st_mtime)
|
||||
apk_name = output_apk
|
||||
if output_aab_play in file:
|
||||
build_date = int(os.stat(file).st_mtime)
|
||||
bundle_name_play = output_aab_play
|
||||
|
||||
build_date = datetime.fromtimestamp(
|
||||
build_date,
|
||||
tz=ZoneInfo("Europe/Warsaw"),
|
||||
).strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
if build_type in ["nightly", "daily"]:
|
||||
download_url = apk_server_nightly + apk_name if apk_name else None
|
||||
else:
|
||||
# download_url = apk_server_release + apk_name if apk_name else None
|
||||
download_url = (
|
||||
f"https://github.com/szkolny-eu/szkolny-android/releases/download/v{version_name}/{apk_name}"
|
||||
if apk_name
|
||||
else None
|
||||
)
|
||||
if download_url:
|
||||
print("downloadUrl=" + download_url)
|
||||
|
||||
cols = [
|
||||
"versionCode",
|
||||
"versionName",
|
||||
"releaseDate",
|
||||
"releaseNotes",
|
||||
"releaseType",
|
||||
"downloadUrl",
|
||||
"apkName",
|
||||
"bundleNamePlay",
|
||||
]
|
||||
updated = {
|
||||
"versionCode": version_code,
|
||||
"downloadUrl": download_url,
|
||||
"apkName": apk_name,
|
||||
"bundleNamePlay": bundle_name_play,
|
||||
}
|
||||
|
||||
values = [
|
||||
version_code,
|
||||
version_name,
|
||||
build_date,
|
||||
changelog,
|
||||
build_type,
|
||||
download_url,
|
||||
apk_name,
|
||||
bundle_name_play,
|
||||
]
|
||||
values.extend(val for val in updated.values() if val)
|
||||
|
||||
updated = ", ".join(f"{col} = %s" for (col, val) in updated.items() if val)
|
||||
|
||||
sql = f"INSERT INTO updates ({', '.join(cols)}) VALUES ({'%s, ' * (len(cols) - 1)}%s) ON DUPLICATE KEY UPDATE {updated};"
|
||||
|
||||
c = db.cursor()
|
||||
c.execute(sql, tuple(values))
|
||||
db.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: save_version.py <project dir>")
|
||||
exit(-1)
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
load_dotenv()
|
||||
DB_HOST = os.getenv("DB_HOST")
|
||||
DB_USER = os.getenv("DB_USER")
|
||||
DB_PASS = os.getenv("DB_PASS")
|
||||
DB_NAME = os.getenv("DB_NAME")
|
||||
APK_SERVER_RELEASE = os.getenv("APK_SERVER_RELEASE")
|
||||
APK_SERVER_NIGHTLY = os.getenv("APK_SERVER_NIGHTLY")
|
||||
|
||||
save_version(
|
||||
project_dir,
|
||||
DB_HOST,
|
||||
DB_USER,
|
||||
DB_PASS,
|
||||
DB_NAME,
|
||||
APK_SERVER_RELEASE,
|
||||
APK_SERVER_NIGHTLY,
|
||||
)
|
82
.github/utils/sign.py
vendored
Normal file
82
.github/utils/sign.py
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from _get_password import get_password
|
||||
from _utils import get_project_dir, read_gradle_version
|
||||
|
||||
|
||||
def sign(
|
||||
project_dir: str,
|
||||
version_name: str,
|
||||
version_code: int,
|
||||
password: str,
|
||||
iv: bytes,
|
||||
commit: bool = False,
|
||||
):
|
||||
SIGNING_PATH = f"{project_dir}/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt"
|
||||
CPP_PATH = f"{project_dir}/app/src/main/cpp/szkolny-signing.cpp"
|
||||
|
||||
with open(SIGNING_PATH, "r") as f:
|
||||
signing = f.read()
|
||||
|
||||
with open(CPP_PATH, "r") as f:
|
||||
cpp = f.read()
|
||||
|
||||
SIGNING_REGEX = r"\$param1\..*\.\$param2"
|
||||
CPP_REGEX = r"(?s)/\*.+?toys AES_IV\[16\] = {.+?};"
|
||||
|
||||
SIGNING_FORMAT = "$param1.{}.$param2"
|
||||
CPP_FORMAT = "/*{}*/\nstatic toys AES_IV[16] = {{\n\t{} }};"
|
||||
|
||||
iv_hex = " ".join(["{:02x}".format(x) for x in iv])
|
||||
iv_cpp = ", ".join(["0x{:02x}".format(x) for x in iv])
|
||||
|
||||
signing = re.sub(SIGNING_REGEX, SIGNING_FORMAT.format(password), signing)
|
||||
cpp = re.sub(CPP_REGEX, CPP_FORMAT.format(iv_hex, iv_cpp), cpp)
|
||||
|
||||
with open(SIGNING_PATH, "w") as f:
|
||||
f.write(signing)
|
||||
|
||||
with open(CPP_PATH, "w") as f:
|
||||
f.write(cpp)
|
||||
|
||||
if commit:
|
||||
os.chdir(project_dir)
|
||||
os.system("git add .")
|
||||
os.system(
|
||||
f'git commit -m "[{version_name}] Update build.gradle, signing and changelog."'
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: sign.py <project dir> [commit]")
|
||||
exit(-1)
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
load_dotenv()
|
||||
DB_HOST = os.getenv("DB_HOST")
|
||||
DB_USER = os.getenv("DB_USER")
|
||||
DB_PASS = os.getenv("DB_PASS")
|
||||
DB_NAME = os.getenv("DB_NAME")
|
||||
|
||||
(version_code, version_name) = read_gradle_version(project_dir)
|
||||
(password, iv) = get_password(
|
||||
version_name, version_code, DB_HOST, DB_USER, DB_PASS, DB_NAME
|
||||
)
|
||||
|
||||
print("appVersionName=" + version_name)
|
||||
print("appVersionCode=" + str(version_code))
|
||||
|
||||
sign(
|
||||
project_dir,
|
||||
version_name,
|
||||
version_code,
|
||||
password,
|
||||
iv,
|
||||
commit="commit" in sys.argv,
|
||||
)
|
119
.github/utils/webhook_discord.py
vendored
Normal file
119
.github/utils/webhook_discord.py
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import requests
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from _utils import get_changelog, get_commit_log, get_project_dir, read_gradle_version
|
||||
|
||||
|
||||
def post_webhook(
|
||||
project_dir: str,
|
||||
apk_file: str,
|
||||
download_url: str,
|
||||
webhook_release: str,
|
||||
webhook_testing: str,
|
||||
):
|
||||
(_, version_name) = read_gradle_version(project_dir)
|
||||
|
||||
types = ["dev", "beta", "nightly", "daily", "rc", "release"]
|
||||
build_type = [x for x in types if x in version_name]
|
||||
build_type = build_type[0] if build_type else None
|
||||
|
||||
testing = ["dev", "beta", "nightly", "daily"]
|
||||
testing = build_type in testing
|
||||
|
||||
if testing:
|
||||
build_date = int(os.stat(apk_file).st_mtime)
|
||||
if build_date:
|
||||
build_date = datetime.fromtimestamp(
|
||||
build_date,
|
||||
tz=ZoneInfo("Europe/Warsaw"),
|
||||
).strftime("%Y-%m-%d %H:%M")
|
||||
|
||||
# untagged release, get commit log
|
||||
if build_type in ["nightly", "daily"]:
|
||||
changelog = get_commit_log(project_dir, format="markdown", max_lines=5)
|
||||
else:
|
||||
changelog = get_changelog(project_dir, format="markdown")
|
||||
|
||||
webhook = get_webhook_testing(
|
||||
version_name, build_type, changelog, download_url, build_date
|
||||
)
|
||||
requests.post(url=webhook_testing, json=webhook)
|
||||
else:
|
||||
changelog = get_changelog(project_dir, format="markdown")
|
||||
webhook = get_webhook_release(version_name, changelog, download_url)
|
||||
requests.post(url=webhook_release, json=webhook)
|
||||
|
||||
|
||||
def get_webhook_release(version_name: str, changelog: str, download_url: str):
|
||||
(title, content) = changelog
|
||||
return {
|
||||
"content": (
|
||||
f"__**{title}**__\n{content}\n[Szkolny.eu {version_name}]({download_url})"
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def get_webhook_testing(
|
||||
version_name: str,
|
||||
build_type: str,
|
||||
changelog: str,
|
||||
download_url: str,
|
||||
build_date: str,
|
||||
):
|
||||
return {
|
||||
"embeds": [
|
||||
{
|
||||
"title": f"Nowa wersja {build_type} aplikacji Szkolny.eu",
|
||||
"description": f"Dostępna jest nowa wersja testowa **{build_type}**.",
|
||||
"color": 2201331,
|
||||
"fields": [
|
||||
{
|
||||
"name": f"Wersja `{version_name}`",
|
||||
"value": (
|
||||
f"[Pobierz .APK]({download_url})"
|
||||
if download_url
|
||||
else "*Pobieranie niedostępne*"
|
||||
),
|
||||
"inline": False,
|
||||
},
|
||||
{
|
||||
"name": "Data kompilacji",
|
||||
"value": build_date or "-",
|
||||
"inline": False,
|
||||
},
|
||||
{
|
||||
"name": "Ostatnie zmiany",
|
||||
"value": changelog or "-",
|
||||
"inline": False,
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("usage: webhook_discord.py <project dir>")
|
||||
exit(-1)
|
||||
|
||||
project_dir = get_project_dir()
|
||||
|
||||
load_dotenv()
|
||||
APK_FILE = os.getenv("APK_FILE")
|
||||
DOWNLOAD_URL = os.getenv("DOWNLOAD_URL")
|
||||
WEBHOOK_RELEASE = os.getenv("WEBHOOK_RELEASE")
|
||||
WEBHOOK_TESTING = os.getenv("WEBHOOK_TESTING")
|
||||
|
||||
post_webhook(
|
||||
project_dir,
|
||||
APK_FILE,
|
||||
DOWNLOAD_URL,
|
||||
WEBHOOK_RELEASE,
|
||||
WEBHOOK_TESTING,
|
||||
)
|
195
.github/workflows/_build.yml
vendored
Normal file
195
.github/workflows/_build.yml
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
name: "[reusable] Szkolny.eu Build"
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
nightly:
|
||||
type: boolean
|
||||
default: false
|
||||
build-apk:
|
||||
type: boolean
|
||||
default: false
|
||||
build-aab:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
release-ssh:
|
||||
type: boolean
|
||||
default: false
|
||||
release-github:
|
||||
type: boolean
|
||||
default: false
|
||||
release-firebase:
|
||||
type: boolean
|
||||
default: false
|
||||
release-google-play:
|
||||
type: boolean
|
||||
default: false
|
||||
release-discord:
|
||||
type: boolean
|
||||
default: false
|
||||
secrets:
|
||||
APK_SERVER_NIGHTLY:
|
||||
APK_SERVER_RELEASE:
|
||||
DB_HOST:
|
||||
DB_NAME:
|
||||
DB_PASS:
|
||||
DB_USER:
|
||||
FIREBASE_APP_ID:
|
||||
FIREBASE_GROUPS_NIGHTLY:
|
||||
FIREBASE_GROUPS_RELEASE:
|
||||
FIREBASE_SERVICE_ACCOUNT_JSON:
|
||||
KEY_ALIAS_PASSWORD:
|
||||
KEY_ALIAS:
|
||||
KEY_STORE_PASSWORD:
|
||||
KEY_STORE:
|
||||
PLAY_RELEASE_TRACK:
|
||||
PLAY_SERVICE_ACCOUNT_JSON:
|
||||
SSH_IP:
|
||||
SSH_KEY:
|
||||
SSH_PATH_NIGHTLY:
|
||||
SSH_PATH_RELEASE:
|
||||
SSH_USERNAME:
|
||||
WEBHOOK_RELEASE:
|
||||
WEBHOOK_TESTING:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Setup JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "temurin"
|
||||
java-version: "17"
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
- name: Install Python packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
python-dotenv
|
||||
pycryptodome
|
||||
mysql-connector-python
|
||||
requests
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
- name: Bump nightly version
|
||||
if: ${{ inputs.nightly }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/bump_nightly.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
- name: Write signing passwords and keystore
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
KEY_STORE: ${{ secrets.KEY_STORE }}
|
||||
run: |
|
||||
python $GITHUB_WORKSPACE/.github/utils/sign.py $GITHUB_WORKSPACE commit >> $GITHUB_OUTPUT
|
||||
echo $KEY_STORE | base64 --decode > keystore.jks
|
||||
- name: Clean build artifacts
|
||||
run: |
|
||||
rm -rf app/release/*
|
||||
rm -rf app/build/outputs/apk/*
|
||||
rm -rf app/build/outputs/bundle/*
|
||||
|
||||
- name: Build app with Gradle
|
||||
if: ${{ inputs.build-apk || inputs.build-aab }}
|
||||
run: |
|
||||
chmod +x ./gradlew
|
||||
./gradlew \
|
||||
${{ inputs.build-apk && 'assembleOfficialRelease' || '' }} \
|
||||
${{ inputs.build-aab && 'bundlePlayRelease' || '' }} \
|
||||
-P android.injected.signing.store.file=${{ github.workspace }}/keystore.jks \
|
||||
-P android.injected.signing.store.password=${{ secrets.KEY_STORE_PASSWORD }} \
|
||||
-P android.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \
|
||||
-P android.injected.signing.key.password=${{ secrets.KEY_ALIAS_PASSWORD }}
|
||||
|
||||
- name: Upload release to server
|
||||
if: ${{ inputs.release-ssh }}
|
||||
uses: easingthemes/ssh-deploy@v2.1.6
|
||||
env:
|
||||
REMOTE_HOST: ${{ secrets.SSH_IP }}
|
||||
REMOTE_USER: ${{ secrets.SSH_USERNAME }}
|
||||
SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
|
||||
SOURCE: app/release/
|
||||
TARGET: ${{ inputs.nightly && secrets.SSH_PATH_NIGHTLY || secrets.SSH_PATH_RELEASE }}
|
||||
|
||||
- name: Find signed artifacts
|
||||
id: artifacts
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/find_artifacts.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
- name: Extract release changelogs
|
||||
id: changelog
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/extract_changelogs.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
- name: Save version to database
|
||||
id: save
|
||||
env:
|
||||
DB_HOST: ${{ secrets.DB_HOST }}
|
||||
DB_USER: ${{ secrets.DB_USER }}
|
||||
DB_PASS: ${{ secrets.DB_PASS }}
|
||||
DB_NAME: ${{ secrets.DB_NAME }}
|
||||
APK_SERVER_RELEASE: ${{ secrets.APK_SERVER_RELEASE }}
|
||||
APK_SERVER_NIGHTLY: ${{ secrets.APK_SERVER_NIGHTLY }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/save_version.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Release on GitHub
|
||||
if: ${{ inputs.release-github }}
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.changelogTitle }}
|
||||
body_path: ${{ steps.changelog.outputs.changelogMarkdownFile }}
|
||||
files: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Distribute to App Distribution
|
||||
if: ${{ inputs.release-firebase }}
|
||||
uses: wzieba/Firebase-Distribution-Github-Action@v1
|
||||
with:
|
||||
appId: ${{ secrets.FIREBASE_APP_ID }}
|
||||
serviceCredentialsFileContent: ${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON }}
|
||||
file: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
groups: ${{ inputs.nightly && secrets.FIREBASE_GROUPS_NIGHTLY || secrets.FIREBASE_GROUPS_RELEASE }}
|
||||
releaseNotesFile: ${{ inputs.nightly && steps.changelog.outputs.commitLogPlainFile || steps.changelog.outputs.changelogPlainTitledFile }}
|
||||
|
||||
- name: Publish AAB to Google Play
|
||||
if: ${{ inputs.release-google-play }}
|
||||
uses: r0adkll/upload-google-play@v1
|
||||
with:
|
||||
serviceAccountJsonPlainText: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
||||
packageName: pl.szczodrzynski.edziennik
|
||||
releaseFiles: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
releaseName: ${{ steps.changelog.outputs.appVersionName }}
|
||||
track: ${{ secrets.PLAY_RELEASE_TRACK }}
|
||||
whatsNewDirectory: ${{ steps.changelog.outputs.changelogDir }}
|
||||
status: completed
|
||||
|
||||
- name: Post Discord webhook
|
||||
if: ${{ inputs.release-discord }}
|
||||
env:
|
||||
APK_FILE: ${{ steps.artifacts.outputs.signedReleaseFile }}
|
||||
DOWNLOAD_URL: ${{ steps.save.outputs.downloadUrl }}
|
||||
WEBHOOK_RELEASE: ${{ secrets.WEBHOOK_RELEASE }}
|
||||
WEBHOOK_TESTING: ${{ secrets.WEBHOOK_TESTING }}
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/webhook_discord.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: ${{ steps.changelog.outputs.appVersionName }}
|
||||
path: |
|
||||
app/release/whatsnew*/
|
||||
app/release/*.apk
|
||||
app/release/*.aab
|
||||
app/release/*.json
|
||||
app/release/*.txt
|
13
.github/workflows/push-master.yml
vendored
Normal file
13
.github/workflows/push-master.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
name: Push (master)
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
jobs:
|
||||
build:
|
||||
name: Build for Google Play (AAB)
|
||||
uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop
|
||||
with:
|
||||
build-aab: true
|
||||
release-ssh: true
|
||||
release-google-play: true
|
||||
secrets: inherit
|
15
.github/workflows/release.yml
vendored
Normal file
15
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
name: Release
|
||||
on:
|
||||
push:
|
||||
tags: ["v*.*.*"]
|
||||
jobs:
|
||||
build:
|
||||
name: Build release (APK)
|
||||
uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop
|
||||
with:
|
||||
build-apk: true
|
||||
release-ssh: true
|
||||
release-github: true
|
||||
release-firebase: true
|
||||
release-discord: true
|
||||
secrets: inherit
|
42
.github/workflows/schedule-dispatch.yml
vendored
Normal file
42
.github/workflows/schedule-dispatch.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
name: Schedule/dispatch
|
||||
on:
|
||||
schedule:
|
||||
# 23:30 UTC, 0:30 or 1:30 CET/CEST
|
||||
- cron: "30 23 * * *"
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
check:
|
||||
name: Check new changes
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
hasNewChanges: ${{ steps.nightly.outputs.hasNewChanges }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
clean: false
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
- name: Install packages
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
requests
|
||||
- name: Check new changes
|
||||
id: nightly
|
||||
run: python $GITHUB_WORKSPACE/.github/utils/check_nightly.py $GITHUB_WORKSPACE >> $GITHUB_OUTPUT
|
||||
|
||||
build:
|
||||
name: Build nightly release (APK)
|
||||
needs:
|
||||
- check
|
||||
if: ${{ needs.check.outputs.hasNewChanges == 'true' }}
|
||||
uses: szkolny-eu/szkolny-android/.github/workflows/_build.yml@develop
|
||||
with:
|
||||
nightly: true
|
||||
build-apk: true
|
||||
release-ssh: true
|
||||
release-firebase: true
|
||||
release-discord: true
|
||||
secrets: inherit
|
194
.gitignore
vendored
194
.gitignore
vendored
@ -1,5 +1,11 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/android,androidstudio,gradle,java,kotlin
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=android,androidstudio,gradle,java,kotlin
|
||||
|
||||
### Android ###
|
||||
# Built application files
|
||||
*.apk
|
||||
*.aar
|
||||
*.ap_
|
||||
*.aab
|
||||
|
||||
@ -23,7 +29,7 @@ build/
|
||||
local.properties
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
proguard/
|
||||
# proguard/
|
||||
|
||||
# Log Files
|
||||
*.log
|
||||
@ -40,7 +46,7 @@ captures/
|
||||
.idea/tasks.xml
|
||||
.idea/gradle.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/dictionaries
|
||||
#.idea/dictionaries
|
||||
.idea/libraries
|
||||
# Android Studio 3 in .gitignore file.
|
||||
.idea/caches
|
||||
@ -50,11 +56,12 @@ captures/
|
||||
|
||||
# Keystore files
|
||||
# Uncomment the following lines if you do not want to check your keystore files in.
|
||||
*.jks
|
||||
*.keystore
|
||||
#*.jks
|
||||
#*.keystore
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
.externalNativeBuild
|
||||
.cxx/
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
@ -80,3 +87,182 @@ lint/generated/
|
||||
lint/outputs/
|
||||
lint/tmp/
|
||||
# lint/reports/
|
||||
|
||||
### Android Patch ###
|
||||
gen-external-apklibs
|
||||
output-metadata.json
|
||||
|
||||
# Replacement of .externalNativeBuild directories introduced
|
||||
# with Android Studio 3.5.
|
||||
|
||||
### Java ###
|
||||
# Compiled class file
|
||||
|
||||
# Log file
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
!/*/libs/*.jar
|
||||
|
||||
### Kotlin ###
|
||||
# Compiled class file
|
||||
|
||||
# Log file
|
||||
|
||||
# BlueJ files
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
|
||||
# Package Files #
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
|
||||
### Gradle ###
|
||||
.gradle
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
### Gradle Patch ###
|
||||
**/build/
|
||||
|
||||
### AndroidStudio ###
|
||||
# Covers files to be ignored for android development using Android Studio.
|
||||
|
||||
# Built application files
|
||||
|
||||
# Files for the ART/Dalvik VM
|
||||
|
||||
# Java class files
|
||||
|
||||
# Generated files
|
||||
|
||||
# Gradle files
|
||||
|
||||
# Signing files
|
||||
.signing/
|
||||
|
||||
# Local configuration file (sdk path, etc)
|
||||
|
||||
# Proguard folder generated by Eclipse
|
||||
|
||||
# Log Files
|
||||
|
||||
# Android Studio
|
||||
/*/build/
|
||||
/*/local.properties
|
||||
/*/out
|
||||
/*/*/build
|
||||
/*/*/production
|
||||
*.ipr
|
||||
*~
|
||||
*.swp
|
||||
|
||||
# Keystore files
|
||||
*.jks
|
||||
*.keystore
|
||||
|
||||
# Google Services (e.g. APIs or Firebase)
|
||||
# google-services.json
|
||||
|
||||
# Android Patch
|
||||
|
||||
# External native build folder generated in Android Studio 2.2 and later
|
||||
|
||||
# NDK
|
||||
obj/
|
||||
|
||||
# IntelliJ IDEA
|
||||
*.iws
|
||||
/out/
|
||||
|
||||
# User-specific configurations
|
||||
.idea/caches/
|
||||
.idea/libraries/
|
||||
.idea/shelf/
|
||||
.idea/.name
|
||||
.idea/compiler.xml
|
||||
.idea/copyright/profiles_settings.xml
|
||||
.idea/encodings.xml
|
||||
.idea/misc.xml
|
||||
.idea/scopes/scope_settings.xml
|
||||
.idea/vcs.xml
|
||||
.idea/jsLibraryMappings.xml
|
||||
.idea/datasources.xml
|
||||
.idea/dataSources.ids
|
||||
.idea/sqlDataSources.xml
|
||||
.idea/dynamic.xml
|
||||
.idea/uiDesigner.xml
|
||||
.idea/jarRepositories.xml
|
||||
|
||||
# OS-specific files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Legacy Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
.cproject
|
||||
.settings/
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
|
||||
# Package Files #
|
||||
|
||||
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/mongoSettings.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
### AndroidStudio Patch ###
|
||||
|
||||
!/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/android,androidstudio,gradle,java,kotlin
|
||||
|
||||
signatures/
|
||||
.idea/*.xml
|
||||
|
35
.idea/codeStyles/Project.xml
generated
35
.idea/codeStyles/Project.xml
generated
@ -1,6 +1,35 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="LAYOUT_SETTINGS">
|
||||
<value>
|
||||
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="MANIFEST_SETTINGS">
|
||||
<value>
|
||||
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="OTHER_SETTINGS">
|
||||
<value>
|
||||
<option name="INSERT_LINE_BREAK_BEFORE_NAMESPACE_DECLARATION" value="true" />
|
||||
</value>
|
||||
</option>
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="JSON">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="4" />
|
||||
<option name="USE_TAB_CHARACTER" value="true" />
|
||||
<option name="SMART_TABS" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
@ -112,5 +141,11 @@
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="PARAMETER_ANNOTATION_WRAP" value="2" />
|
||||
<option name="ENUM_CONSTANTS_WRAP" value="2" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
6
.idea/copyright/Antoni.xml
generated
Normal file
6
.idea/copyright/Antoni.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (c) Antoni Czaplicki &#36;{today.year}-&#36;{today.month}-&#36;{today.day}. " />
|
||||
<option name="myName" value="Antoni" />
|
||||
</copyright>
|
||||
</component>
|
6
.idea/copyright/Kacper.xml
generated
Normal file
6
.idea/copyright/Kacper.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (c) Kacper Ziubryniewicz &#36;{today.year}-&#36;{today.month}-&#36;{today.day}" />
|
||||
<option name="myName" value="Kacper" />
|
||||
</copyright>
|
||||
</component>
|
6
.idea/copyright/kubasz.xml
generated
Normal file
6
.idea/copyright/kubasz.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (c) Kuba Szczodrzyński &#36;{today.year}-&#36;{today.month}-&#36;{today.day}. " />
|
||||
<option name="myName" value="kubasz" />
|
||||
</copyright>
|
||||
</component>
|
21
.idea/dictionaries/Kuba.xml
generated
Normal file
21
.idea/dictionaries/Kuba.xml
generated
Normal file
@ -0,0 +1,21 @@
|
||||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="Kuba">
|
||||
<words>
|
||||
<w>autoryzacji</w>
|
||||
<w>ciasteczko</w>
|
||||
<w>csrf</w>
|
||||
<w>daynight</w>
|
||||
<w>edziennik</w>
|
||||
<w>eggfall</w>
|
||||
<w>elearning</w>
|
||||
<w>gson</w>
|
||||
<w>hebe</w>
|
||||
<w>idziennik</w>
|
||||
<w>kuba</w>
|
||||
<w>synergia</w>
|
||||
<w>szczodrzyński</w>
|
||||
<w>szkolny</w>
|
||||
<w>usos</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
9
.idea/discord.xml
generated
9
.idea/discord.xml
generated
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="true" />
|
||||
</component>
|
||||
<component name="ProjectNotificationSettings">
|
||||
<option name="askShowProject" value="false" />
|
||||
</component>
|
||||
</project>
|
4
.idea/encodings.xml
generated
4
.idea/encodings.xml
generated
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||
</project>
|
6
.idea/kotlinc.xml
generated
6
.idea/kotlinc.xml
generated
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Kotlin2JvmCompilerArguments">
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
</component>
|
||||
</project>
|
49
.idea/misc.xml
generated
49
.idea/misc.xml
generated
@ -1,49 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
||||
</configurations>
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
|
||||
<option name="myDefaultNotNull" value="androidx.annotation.RecentlyNonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="10">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="9">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
12
.idea/runConfigurations.xml
generated
12
.idea/runConfigurations.xml
generated
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
621
LICENSE
Normal file
621
LICENSE
Normal file
@ -0,0 +1,621 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
@ -1,59 +0,0 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion "28.0.3"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 6102
|
||||
versionName "6.1.2"
|
||||
|
||||
resValue "string", "materialdrawer_lib_version", "6.1.2"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
debugMinify {
|
||||
debuggable = true
|
||||
minifyEnabled = true
|
||||
proguardFiles 'proguard-android.txt'
|
||||
}
|
||||
}
|
||||
productFlavors {
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "androidx.appcompat:appcompat:${androidXAppCompat}"
|
||||
implementation "androidx.recyclerview:recyclerview:${androidXRecyclerView}"
|
||||
implementation "androidx.annotation:annotation:1.0.2"
|
||||
implementation "com.google.android.material:material:${googleMaterial}"
|
||||
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.15'
|
||||
|
||||
// add the constraintLayout used to create the items and headers
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
|
||||
// used to base on some backwards compatible themes
|
||||
// contains util classes to support various android versions, and clean up code
|
||||
// comes with the awesome "Holder"-Pattern
|
||||
// https://github.com/mikepenz/Materialize
|
||||
api 'com.mikepenz:materialize:1.2.0'
|
||||
|
||||
// used to provide out of the box icon font support. simplifies development,
|
||||
// and provides scalable icons. the core is very very light
|
||||
// https://github.com/mikepenz/Android-Iconics
|
||||
api "com.mikepenz:iconics-core:${iconics}"
|
||||
|
||||
// used to fill the RecyclerView with the DrawerItems
|
||||
// and provides single and multi selection, expandable items
|
||||
// https://github.com/mikepenz/FastAdapter
|
||||
api 'com.mikepenz:fastadapter:3.3.0'
|
||||
api 'com.mikepenz:fastadapter-extensions-expandable:3.3.0'
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
POM_NAME=MaterialDrawer Library
|
||||
POM_DESCRIPTION=The flexible, easy to use, all in one drawer library for your Android project.
|
||||
POM_ARTIFACT_ID=materialdrawer
|
||||
POM_PACKAGING=aar
|
@ -1,2 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.mikepenz.materialdrawer" />
|
Binary file not shown.
@ -1,455 +0,0 @@
|
||||
package com.mikepenz.materialdrawer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import pl.droidsonroids.gif.GifDrawable;
|
||||
import pl.droidsonroids.gif.GifImageView;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 27.02.15.
|
||||
*/
|
||||
public class AccountHeader {
|
||||
protected final static double NAVIGATION_DRAWER_ACCOUNT_ASPECT_RATIO = 9d / 16d;
|
||||
|
||||
protected static final String BUNDLE_SELECTION_HEADER = "bundle_selection_header";
|
||||
|
||||
|
||||
protected final AccountHeaderBuilder mAccountHeaderBuilder;
|
||||
|
||||
protected AccountHeader(AccountHeaderBuilder accountHeaderBuilder) {
|
||||
this.mAccountHeaderBuilder = accountHeaderBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* the protected getter for the AccountHeaderBuilder
|
||||
*
|
||||
* @return the AccountHeaderBuilder
|
||||
*/
|
||||
protected AccountHeaderBuilder getAccountHeaderBuilder() {
|
||||
return mAccountHeaderBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Root view for the Header
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public View getView() {
|
||||
return mAccountHeaderBuilder.mAccountHeaderContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the drawer for the AccountHeader so we can use it for the select
|
||||
*
|
||||
* @param drawer
|
||||
*/
|
||||
public void setDrawer(Drawer drawer) {
|
||||
mAccountHeaderBuilder.mDrawer = drawer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header background view so the dev can set everything on it
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public GifImageView getHeaderBackgroundView() {
|
||||
return mAccountHeaderBuilder.mAccountHeaderBackground;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the background for the header via the ImageHolder class
|
||||
*
|
||||
* @param imageHolder
|
||||
*/
|
||||
public void setHeaderBackground(ImageHolder imageHolder) {
|
||||
ImageHolder.applyTo(imageHolder, mAccountHeaderBuilder.mAccountHeaderBackground);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background for the Header
|
||||
*
|
||||
* @param headerBackground
|
||||
*/
|
||||
public void setBackground(Drawable headerBackground) {
|
||||
mAccountHeaderBuilder.mAccountHeaderBackground.setImageDrawable(headerBackground);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the background for the header as file name
|
||||
*
|
||||
* @param headerBackgroundPath
|
||||
* @return
|
||||
*/
|
||||
public void setBackground(String headerBackgroundPath) {
|
||||
try {
|
||||
if (headerBackgroundPath.endsWith(".gif")) {
|
||||
setHeaderBackground(new ImageHolder(new GifDrawable(headerBackgroundPath)));
|
||||
}
|
||||
else {
|
||||
setHeaderBackground(new ImageHolder(Uri.parse(headerBackgroundPath)));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the background for the Header as resource
|
||||
*
|
||||
* @param headerBackgroundRes
|
||||
*/
|
||||
public void setBackgroundRes(@DrawableRes int headerBackgroundRes) {
|
||||
mAccountHeaderBuilder.mAccountHeaderBackground.setImageResource(headerBackgroundRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the selection list (show or hide it)
|
||||
*
|
||||
* @param ctx
|
||||
*/
|
||||
public void toggleSelectionList(Context ctx) {
|
||||
mAccountHeaderBuilder.toggleSelectionList(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns if the selection list is currently shown
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSelectionListShown() {
|
||||
return mAccountHeaderBuilder.mSelectionListShown;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* set this to false if you want to hide the first line of the selection box in the header (first line would be the name)
|
||||
*
|
||||
* @param selectionFirstLineShown
|
||||
*/
|
||||
public void setSelectionFirstLineShown(boolean selectionFirstLineShown) {
|
||||
mAccountHeaderBuilder.mSelectionFirstLineShown = selectionFirstLineShown;
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* set this to false if you want to hide the second line of the selection box in the header (second line would be the e-mail)
|
||||
*
|
||||
* @param selectionSecondLineShown
|
||||
*/
|
||||
public void setSelectionSecondLineShown(boolean selectionSecondLineShown) {
|
||||
mAccountHeaderBuilder.mSelectionSecondLineShown = selectionSecondLineShown;
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* set this to define the first line in the selection area if there is no profile
|
||||
* note this will block any values from profiles!
|
||||
*
|
||||
* @param selectionFirstLine
|
||||
*/
|
||||
public void setSelectionFirstLine(String selectionFirstLine) {
|
||||
mAccountHeaderBuilder.mSelectionFirstLine = selectionFirstLine;
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* set this to define the second line in the selection area if there is no profile
|
||||
* note this will block any values from profiles!
|
||||
*
|
||||
* @param selectionSecondLine
|
||||
*/
|
||||
public void setSelectionSecondLine(String selectionSecondLine) {
|
||||
mAccountHeaderBuilder.mSelectionSecondLine = selectionSecondLine;
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the current list of profiles set for this header
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<IProfile> getProfiles() {
|
||||
return mAccountHeaderBuilder.mProfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new list of profiles for the header
|
||||
*
|
||||
* @param profiles
|
||||
*/
|
||||
public void setProfiles(List<IProfile> profiles) {
|
||||
mAccountHeaderBuilder.mProfiles = profiles;
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the given profile and sets it to the new active profile
|
||||
*
|
||||
* @param profile
|
||||
*/
|
||||
public void setActiveProfile(IProfile profile) {
|
||||
setActiveProfile(profile, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the given profile and sets it to the new active profile
|
||||
*
|
||||
* @param profile
|
||||
*/
|
||||
public void setActiveProfile(IProfile profile, boolean fireOnProfileChanged) {
|
||||
final boolean isCurrentSelectedProfile = mAccountHeaderBuilder.switchProfiles(profile);
|
||||
//if the selectionList is shown we should also update the current selected profile in the list
|
||||
if (mAccountHeaderBuilder.mDrawer != null && isSelectionListShown()) {
|
||||
mAccountHeaderBuilder.mDrawer.setSelection(profile.getIdentifier(), false);
|
||||
}
|
||||
//fire the event if enabled and a listener is set
|
||||
if (fireOnProfileChanged && mAccountHeaderBuilder.mOnAccountHeaderListener != null) {
|
||||
mAccountHeaderBuilder.mOnAccountHeaderListener.onProfileChanged(null, profile, isCurrentSelectedProfile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a profile by its identifier
|
||||
*
|
||||
* @param identifier
|
||||
*/
|
||||
public void setActiveProfile(long identifier) {
|
||||
setActiveProfile(identifier, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a profile by its identifier
|
||||
*
|
||||
* @param identifier
|
||||
*/
|
||||
public void setActiveProfile(long identifier, boolean fireOnProfileChanged) {
|
||||
if (mAccountHeaderBuilder.mProfiles != null) {
|
||||
for (IProfile profile : mAccountHeaderBuilder.mProfiles) {
|
||||
if (profile != null) {
|
||||
if (profile.getIdentifier() == identifier) {
|
||||
setActiveProfile(profile, fireOnProfileChanged);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current active profile
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public IProfile getActiveProfile() {
|
||||
return mAccountHeaderBuilder.mCurrentProfile;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper method to update a profile using it's identifier
|
||||
*
|
||||
* @param newProfile
|
||||
*/
|
||||
public void updateProfile(@NonNull IProfile newProfile) {
|
||||
updateProfileByIdentifier(newProfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to update a profile using it's identifier
|
||||
*
|
||||
* @param newProfile
|
||||
*/
|
||||
@Deprecated
|
||||
public void updateProfileByIdentifier(@NonNull IProfile newProfile) {
|
||||
int found = getPositionByIdentifier(newProfile.getIdentifier());
|
||||
if (found > -1) {
|
||||
mAccountHeaderBuilder.mProfiles.set(found, newProfile);
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add new profiles to the existing list of profiles
|
||||
*
|
||||
* @param profiles
|
||||
*/
|
||||
public void addProfiles(@NonNull IProfile... profiles) {
|
||||
if (mAccountHeaderBuilder.mProfiles == null) {
|
||||
mAccountHeaderBuilder.mProfiles = new ArrayList<>();
|
||||
}
|
||||
|
||||
Collections.addAll(mAccountHeaderBuilder.mProfiles, profiles);
|
||||
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new profile at a specific position to the list
|
||||
*
|
||||
* @param profile
|
||||
* @param position
|
||||
*/
|
||||
public void addProfile(@NonNull IProfile profile, int position) {
|
||||
if (mAccountHeaderBuilder.mProfiles == null) {
|
||||
mAccountHeaderBuilder.mProfiles = new ArrayList<>();
|
||||
}
|
||||
mAccountHeaderBuilder.mProfiles.add(position, profile);
|
||||
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a profile from the given position
|
||||
*
|
||||
* @param position
|
||||
*/
|
||||
public void removeProfile(int position) {
|
||||
if (mAccountHeaderBuilder.mProfiles != null && mAccountHeaderBuilder.mProfiles.size() > position) {
|
||||
mAccountHeaderBuilder.mProfiles.remove(position);
|
||||
}
|
||||
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the profile with the given identifier
|
||||
*
|
||||
* @param identifier
|
||||
*/
|
||||
public void removeProfileByIdentifier(long identifier) {
|
||||
int found = getPositionByIdentifier(identifier);
|
||||
if (found > -1) {
|
||||
mAccountHeaderBuilder.mProfiles.remove(found);
|
||||
}
|
||||
|
||||
mAccountHeaderBuilder.updateHeaderAndList();
|
||||
}
|
||||
|
||||
/**
|
||||
* try to remove the given profile
|
||||
*
|
||||
* @param profile
|
||||
*/
|
||||
public void removeProfile(@NonNull IProfile profile) {
|
||||
removeProfileByIdentifier(profile.getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the header
|
||||
*/
|
||||
public void clear() {
|
||||
mAccountHeaderBuilder.mProfiles = null;
|
||||
|
||||
//calculate the profiles to set
|
||||
mAccountHeaderBuilder.calculateProfiles();
|
||||
|
||||
//process and build the profiles
|
||||
mAccountHeaderBuilder.buildProfiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the position of a profile by it's identifier
|
||||
*
|
||||
* @param identifier
|
||||
* @return
|
||||
*/
|
||||
private int getPositionByIdentifier(long identifier) {
|
||||
int found = -1;
|
||||
if (mAccountHeaderBuilder.mProfiles != null && identifier != -1) {
|
||||
for (int i = 0; i < mAccountHeaderBuilder.mProfiles.size(); i++) {
|
||||
if (mAccountHeaderBuilder.mProfiles.get(i) != null) {
|
||||
if (mAccountHeaderBuilder.mProfiles.get(i).getIdentifier() == identifier) {
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* add the values to the bundle for saveInstanceState
|
||||
*
|
||||
* @param savedInstanceState
|
||||
* @return
|
||||
*/
|
||||
public Bundle saveInstanceState(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
savedInstanceState.putInt(BUNDLE_SELECTION_HEADER, mAccountHeaderBuilder.getCurrentSelection());
|
||||
}
|
||||
return savedInstanceState;
|
||||
}
|
||||
|
||||
|
||||
public interface OnAccountHeaderListener {
|
||||
/**
|
||||
* the event when the profile changes
|
||||
*
|
||||
* @param view
|
||||
* @param profile
|
||||
* @return if the event was consumed
|
||||
*/
|
||||
boolean onProfileChanged(View view, IProfile profile, boolean current);
|
||||
}
|
||||
|
||||
public interface OnAccountHeaderItemLongClickListener {
|
||||
/**
|
||||
* the event when the profile item is longClicked inside the list
|
||||
*
|
||||
* @param view
|
||||
* @param profile
|
||||
* @param current
|
||||
* @return if the event was consumed
|
||||
*/
|
||||
boolean onProfileLongClick(View view, IProfile profile, boolean current);
|
||||
}
|
||||
|
||||
public interface OnAccountHeaderProfileImageListener {
|
||||
/**
|
||||
* the event when the profile image is clicked
|
||||
*
|
||||
* @param view
|
||||
* @param profile
|
||||
* @return if the event was consumed
|
||||
*/
|
||||
boolean onProfileImageClick(View view, IProfile profile, boolean current);
|
||||
|
||||
/**
|
||||
* the event when the profile image is long clicked
|
||||
*
|
||||
* @param view
|
||||
* @param profile
|
||||
* @return if the event was consumed
|
||||
*/
|
||||
boolean onProfileImageLongClick(View view, IProfile profile, boolean current);
|
||||
}
|
||||
|
||||
public interface OnAccountHeaderSelectionViewClickListener {
|
||||
/**
|
||||
* the event when the user clicks the selection list under the profile icons
|
||||
*
|
||||
* @param view
|
||||
* @param profile
|
||||
* @return if the event was consumed
|
||||
*/
|
||||
boolean onClick(View view, IProfile profile);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,447 +0,0 @@
|
||||
package com.mikepenz.materialdrawer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.mikepenz.materialdrawer.model.AbstractDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.ContainerDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Selectable;
|
||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.drawerlayout.widget.DrawerLayout;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 23.05.15.
|
||||
*/
|
||||
class DrawerUtils {
|
||||
/**
|
||||
* helper method to handle the onClick of the footer
|
||||
*
|
||||
* @param drawer
|
||||
* @param drawerItem
|
||||
* @param v
|
||||
* @param fireOnClick true if we should call the listener, false if not, null to not call the listener and not close the drawer
|
||||
*/
|
||||
public static void onFooterDrawerItemClick(DrawerBuilder drawer, IDrawerItem drawerItem, View v, Boolean fireOnClick) {
|
||||
boolean checkable = !(drawerItem != null && drawerItem instanceof Selectable && !drawerItem.isSelectable());
|
||||
if (checkable) {
|
||||
drawer.resetStickyFooterSelection();
|
||||
|
||||
v.setActivated(true);
|
||||
v.setSelected(true);
|
||||
|
||||
//remove the selection in the list
|
||||
drawer.getAdapter().deselect();
|
||||
|
||||
//find the position of the clicked footer item
|
||||
if (drawer.mStickyFooterView != null && drawer.mStickyFooterView instanceof LinearLayout) {
|
||||
LinearLayout footer = (LinearLayout) drawer.mStickyFooterView;
|
||||
for (int i = 0; i < footer.getChildCount(); i++) {
|
||||
if (footer.getChildAt(i) == v) {
|
||||
drawer.mCurrentStickyFooterSelection = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (fireOnClick != null) {
|
||||
boolean consumed = false;
|
||||
|
||||
if (fireOnClick) {
|
||||
if (drawerItem instanceof AbstractDrawerItem && ((AbstractDrawerItem) drawerItem).getOnDrawerItemClickListener() != null) {
|
||||
consumed = ((AbstractDrawerItem) drawerItem).getOnDrawerItemClickListener().onItemClick(v, -1, drawerItem);
|
||||
}
|
||||
|
||||
if (drawer.mOnDrawerItemClickListener != null) {
|
||||
consumed = drawer.mOnDrawerItemClickListener.onItemClick(v, -1, drawerItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (!consumed) {
|
||||
//close the drawer after click
|
||||
drawer.closeDrawerDelayed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to set the selection of the footer
|
||||
*
|
||||
* @param drawer
|
||||
* @param position
|
||||
* @param fireOnClick
|
||||
*/
|
||||
public static void setStickyFooterSelection(DrawerBuilder drawer, int position, Boolean fireOnClick) {
|
||||
if (position > -1) {
|
||||
if (drawer.mStickyFooterView != null && drawer.mStickyFooterView instanceof LinearLayout) {
|
||||
LinearLayout footer = (LinearLayout) drawer.mStickyFooterView;
|
||||
if (drawer.mStickyFooterDivider) {
|
||||
position = position + 1;
|
||||
}
|
||||
if (footer.getChildCount() > position && position >= 0) {
|
||||
IDrawerItem drawerItem = (IDrawerItem) footer.getChildAt(position).getTag(R.id.material_drawer_item);
|
||||
onFooterDrawerItemClick(drawer, drawerItem, footer.getChildAt(position), fireOnClick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates the position of an drawerItem. searching by it's identifier
|
||||
*
|
||||
* @param identifier
|
||||
* @return
|
||||
*/
|
||||
public static int getPositionByIdentifier(DrawerBuilder drawer, long identifier) {
|
||||
if (identifier != -1) {
|
||||
for (int i = 0; i < drawer.getAdapter().getItemCount(); i++) {
|
||||
if (drawer.getAdapter().getItem(i).getIdentifier() == identifier) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the drawerItem with the specific identifier from a drawerItem list
|
||||
*
|
||||
* @param drawerItems
|
||||
* @param identifier
|
||||
* @return
|
||||
*/
|
||||
public static IDrawerItem getDrawerItem(List<IDrawerItem> drawerItems, long identifier) {
|
||||
if (identifier != -1) {
|
||||
for (IDrawerItem drawerItem : drawerItems) {
|
||||
if (drawerItem.getIdentifier() == identifier) {
|
||||
return drawerItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the drawerItem by a defined tag from a drawerItem list
|
||||
*
|
||||
* @param drawerItems
|
||||
* @param tag
|
||||
* @return
|
||||
*/
|
||||
public static IDrawerItem getDrawerItem(List<IDrawerItem> drawerItems, Object tag) {
|
||||
if (tag != null) {
|
||||
for (IDrawerItem drawerItem : drawerItems) {
|
||||
if (tag.equals(drawerItem.getTag())) {
|
||||
return drawerItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculates the position of an drawerItem inside the footer. searching by it's identifier
|
||||
*
|
||||
* @param identifier
|
||||
* @return
|
||||
*/
|
||||
public static int getStickyFooterPositionByIdentifier(DrawerBuilder drawer, long identifier) {
|
||||
if (identifier != -1) {
|
||||
if (drawer.mStickyFooterView != null && drawer.mStickyFooterView instanceof LinearLayout) {
|
||||
LinearLayout footer = (LinearLayout) drawer.mStickyFooterView;
|
||||
|
||||
int shadowOffset = 0;
|
||||
for (int i = 0; i < footer.getChildCount(); i++) {
|
||||
Object o = footer.getChildAt(i).getTag(R.id.material_drawer_item);
|
||||
|
||||
//count up the shadowOffset to return the correct position of the given item
|
||||
if (o == null && drawer.mStickyFooterDivider) {
|
||||
shadowOffset = shadowOffset + 1;
|
||||
}
|
||||
|
||||
if (o != null && o instanceof IDrawerItem && ((IDrawerItem) o).getIdentifier() == identifier) {
|
||||
return i - shadowOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to handle the headerView
|
||||
*
|
||||
* @param drawer
|
||||
*/
|
||||
public static void handleHeaderView(DrawerBuilder drawer) {
|
||||
//use the AccountHeader if set
|
||||
if (drawer.mAccountHeader != null) {
|
||||
if (drawer.mAccountHeaderSticky) {
|
||||
drawer.mStickyHeaderView = drawer.mAccountHeader.getView();
|
||||
} else {
|
||||
drawer.mHeaderView = drawer.mAccountHeader.getView();
|
||||
drawer.mHeaderDivider = drawer.mAccountHeader.mAccountHeaderBuilder.mDividerBelowHeader;
|
||||
drawer.mHeaderPadding = drawer.mAccountHeader.mAccountHeaderBuilder.mPaddingBelowHeader;
|
||||
}
|
||||
}
|
||||
|
||||
//sticky header view
|
||||
if (drawer.mStickyHeaderView != null) {
|
||||
//add the sticky footer view and align it to the bottom
|
||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP, 1);
|
||||
drawer.mStickyHeaderView.setId(R.id.material_drawer_sticky_header);
|
||||
drawer.mSliderLayout.addView(drawer.mStickyHeaderView, 0, layoutParams);
|
||||
|
||||
//now align the recyclerView below the stickyFooterView ;)
|
||||
RelativeLayout.LayoutParams layoutParamsListView = (RelativeLayout.LayoutParams) drawer.mRecyclerView.getLayoutParams();
|
||||
layoutParamsListView.addRule(RelativeLayout.BELOW, R.id.material_drawer_sticky_header);
|
||||
drawer.mRecyclerView.setLayoutParams(layoutParamsListView);
|
||||
|
||||
//set a background color or the elevation will not work
|
||||
drawer.mStickyHeaderView.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(drawer.mActivity, R.attr.material_drawer_background, R.color.material_drawer_background));
|
||||
|
||||
if (drawer.mStickyHeaderShadow) {
|
||||
//add a shadow
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
drawer.mStickyHeaderView.setElevation(UIUtils.convertDpToPixel(4, drawer.mActivity));
|
||||
} else {
|
||||
View view = new View(drawer.mActivity);
|
||||
view.setBackgroundResource(R.drawable.material_drawer_shadow_bottom);
|
||||
drawer.mSliderLayout.addView(view, RelativeLayout.LayoutParams.MATCH_PARENT, (int) UIUtils.convertDpToPixel(4, drawer.mActivity));
|
||||
//now align the shadow below the stickyHeader ;)
|
||||
RelativeLayout.LayoutParams lps = (RelativeLayout.LayoutParams) view.getLayoutParams();
|
||||
lps.addRule(RelativeLayout.BELOW, R.id.material_drawer_sticky_header);
|
||||
view.setLayoutParams(lps);
|
||||
}
|
||||
}
|
||||
|
||||
//remove the padding of the recyclerView again we have the header on top of it
|
||||
drawer.mRecyclerView.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
// set the header (do this before the setAdapter because some devices will crash else
|
||||
if (drawer.mHeaderView != null) {
|
||||
if (drawer.mRecyclerView == null) {
|
||||
throw new RuntimeException("can't use a headerView without a recyclerView");
|
||||
}
|
||||
|
||||
if (drawer.mHeaderPadding) {
|
||||
drawer.getHeaderAdapter().add(new ContainerDrawerItem().withView(drawer.mHeaderView).withHeight(drawer.mHeiderHeight).withDivider(drawer.mHeaderDivider).withViewPosition(ContainerDrawerItem.Position.TOP));
|
||||
} else {
|
||||
drawer.getHeaderAdapter().add(new ContainerDrawerItem().withView(drawer.mHeaderView).withHeight(drawer.mHeiderHeight).withDivider(drawer.mHeaderDivider).withViewPosition(ContainerDrawerItem.Position.NONE));
|
||||
}
|
||||
//set the padding on the top to 0
|
||||
drawer.mRecyclerView.setPadding(drawer.mRecyclerView.getPaddingLeft(), 0, drawer.mRecyclerView.getPaddingRight(), drawer.mRecyclerView.getPaddingBottom());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* small helper to rebuild the FooterView
|
||||
*
|
||||
* @param drawer
|
||||
*/
|
||||
public static void rebuildStickyFooterView(final DrawerBuilder drawer) {
|
||||
if (drawer.mSliderLayout != null) {
|
||||
if (drawer.mStickyFooterView != null) {
|
||||
drawer.mStickyFooterView.removeAllViews();
|
||||
|
||||
//create the divider
|
||||
if (drawer.mStickyFooterDivider) {
|
||||
addStickyFooterDivider(drawer.mStickyFooterView.getContext(), drawer.mStickyFooterView);
|
||||
}
|
||||
|
||||
//fill the footer with items
|
||||
DrawerUtils.fillStickyDrawerItemFooter(drawer, drawer.mStickyFooterView, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
IDrawerItem drawerItem = (IDrawerItem) v.getTag(R.id.material_drawer_item);
|
||||
com.mikepenz.materialdrawer.DrawerUtils.onFooterDrawerItemClick(drawer, drawerItem, v, true);
|
||||
}
|
||||
});
|
||||
|
||||
drawer.mStickyFooterView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
//there was no footer yet. now just create one
|
||||
DrawerUtils.handleFooterView(drawer, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
IDrawerItem drawerItem = (IDrawerItem) v.getTag(R.id.material_drawer_item);
|
||||
DrawerUtils.onFooterDrawerItemClick(drawer, drawerItem, v, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setStickyFooterSelection(drawer, drawer.mCurrentStickyFooterSelection, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to handle the footerView
|
||||
*
|
||||
* @param drawer
|
||||
*/
|
||||
public static void handleFooterView(DrawerBuilder drawer, View.OnClickListener onClickListener) {
|
||||
Context ctx = drawer.mSliderLayout.getContext();
|
||||
|
||||
//use the StickyDrawerItems if set
|
||||
if (drawer.mStickyDrawerItems != null && drawer.mStickyDrawerItems.size() > 0) {
|
||||
drawer.mStickyFooterView = DrawerUtils.buildStickyDrawerItemFooter(ctx, drawer, onClickListener);
|
||||
}
|
||||
|
||||
//sticky footer view
|
||||
if (drawer.mStickyFooterView != null) {
|
||||
//add the sticky footer view and align it to the bottom
|
||||
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
|
||||
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, 1);
|
||||
drawer.mStickyFooterView.setId(R.id.material_drawer_sticky_footer);
|
||||
drawer.mSliderLayout.addView(drawer.mStickyFooterView, layoutParams);
|
||||
|
||||
if ((drawer.mTranslucentNavigationBar || drawer.mFullscreen) && Build.VERSION.SDK_INT >= 19) {
|
||||
drawer.mStickyFooterView.setPadding(0, 0, 0, UIUtils.getNavigationBarHeight(ctx));
|
||||
}
|
||||
|
||||
//now align the recyclerView above the stickyFooterView ;)
|
||||
RelativeLayout.LayoutParams layoutParamsListView = (RelativeLayout.LayoutParams) drawer.mRecyclerView.getLayoutParams();
|
||||
layoutParamsListView.addRule(RelativeLayout.ABOVE, R.id.material_drawer_sticky_footer);
|
||||
drawer.mRecyclerView.setLayoutParams(layoutParamsListView);
|
||||
|
||||
//handle shadow on top of the sticky footer
|
||||
if (drawer.mStickyFooterShadow) {
|
||||
drawer.mStickyFooterShadowView = new View(ctx);
|
||||
drawer.mStickyFooterShadowView.setBackgroundResource(R.drawable.material_drawer_shadow_top);
|
||||
drawer.mSliderLayout.addView(drawer.mStickyFooterShadowView, RelativeLayout.LayoutParams.MATCH_PARENT, ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_sticky_footer_elevation));
|
||||
//now align the shadow below the stickyHeader ;)
|
||||
RelativeLayout.LayoutParams lps = (RelativeLayout.LayoutParams) drawer.mStickyFooterShadowView.getLayoutParams();
|
||||
lps.addRule(RelativeLayout.ABOVE, R.id.material_drawer_sticky_footer);
|
||||
drawer.mStickyFooterShadowView.setLayoutParams(lps);
|
||||
}
|
||||
|
||||
//remove the padding of the recyclerView again we have the footer below it
|
||||
drawer.mRecyclerView.setPadding(drawer.mRecyclerView.getPaddingLeft(), drawer.mRecyclerView.getPaddingTop(), drawer.mRecyclerView.getPaddingRight(), ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_padding));
|
||||
}
|
||||
|
||||
// set the footer (do this before the setAdapter because some devices will crash else
|
||||
if (drawer.mFooterView != null) {
|
||||
if (drawer.mRecyclerView == null) {
|
||||
throw new RuntimeException("can't use a footerView without a recyclerView");
|
||||
}
|
||||
|
||||
if (drawer.mFooterDivider) {
|
||||
drawer.getFooterAdapter().add(new ContainerDrawerItem().withView(drawer.mFooterView).withViewPosition(ContainerDrawerItem.Position.BOTTOM));
|
||||
} else {
|
||||
drawer.getFooterAdapter().add(new ContainerDrawerItem().withView(drawer.mFooterView).withViewPosition(ContainerDrawerItem.Position.NONE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* build the sticky footer item view
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ViewGroup buildStickyDrawerItemFooter(Context ctx, DrawerBuilder drawer, View.OnClickListener onClickListener) {
|
||||
//create the container view
|
||||
final LinearLayout linearLayout = new LinearLayout(ctx);
|
||||
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
//set the background color to the drawer background color (if it has alpha the shadow won't be visible)
|
||||
linearLayout.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(ctx, R.attr.material_drawer_background, R.color.material_drawer_background));
|
||||
|
||||
//create the divider
|
||||
if (drawer.mStickyFooterDivider) {
|
||||
addStickyFooterDivider(ctx, linearLayout);
|
||||
}
|
||||
|
||||
fillStickyDrawerItemFooter(drawer, linearLayout, onClickListener);
|
||||
|
||||
return linearLayout;
|
||||
}
|
||||
|
||||
/**
|
||||
* adds the shadow to the stickyFooter
|
||||
*
|
||||
* @param ctx
|
||||
* @param footerView
|
||||
*/
|
||||
private static void addStickyFooterDivider(Context ctx, ViewGroup footerView) {
|
||||
LinearLayout divider = new LinearLayout(ctx);
|
||||
LinearLayout.LayoutParams dividerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
divider.setMinimumHeight((int) UIUtils.convertDpToPixel(1, ctx));
|
||||
divider.setOrientation(LinearLayout.VERTICAL);
|
||||
divider.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(ctx, R.attr.material_drawer_divider, R.color.material_drawer_divider));
|
||||
footerView.addView(divider, dividerParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to fill the sticky footer with it's elements
|
||||
*
|
||||
* @param drawer
|
||||
* @param container
|
||||
* @param onClickListener
|
||||
*/
|
||||
public static void fillStickyDrawerItemFooter(DrawerBuilder drawer, ViewGroup container, View.OnClickListener onClickListener) {
|
||||
//add all drawer items
|
||||
for (IDrawerItem drawerItem : drawer.mStickyDrawerItems) {
|
||||
View view = drawerItem.generateView(container.getContext(), container);
|
||||
view.setTag(drawerItem);
|
||||
|
||||
if (drawerItem.isEnabled()) {
|
||||
//UIUtils.setBackground(view, UIUtils.getSelectableBackground(container.getContext(), selected_color, drawerItem.isSelectedBackgroundAnimated()));
|
||||
view.setOnClickListener(onClickListener);
|
||||
}
|
||||
|
||||
container.addView(view);
|
||||
|
||||
//for android API 17 --> Padding not applied via xml
|
||||
DrawerUIUtils.setDrawerVerticalPadding(view);
|
||||
}
|
||||
//and really. don't ask about this. it won't set the padding if i don't set the padding for the container
|
||||
container.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* helper to extend the layoutParams of the drawer
|
||||
*
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public static DrawerLayout.LayoutParams processDrawerLayoutParams(DrawerBuilder drawer, DrawerLayout.LayoutParams params) {
|
||||
if (params != null) {
|
||||
if (drawer.mDrawerGravity != null && (drawer.mDrawerGravity == Gravity.RIGHT || drawer.mDrawerGravity == Gravity.END)) {
|
||||
params.rightMargin = 0;
|
||||
if (Build.VERSION.SDK_INT >= 17) {
|
||||
params.setMarginEnd(0);
|
||||
}
|
||||
|
||||
params.leftMargin = drawer.mActivity.getResources().getDimensionPixelSize(R.dimen.material_drawer_margin);
|
||||
if (Build.VERSION.SDK_INT >= 17) {
|
||||
params.setMarginEnd(drawer.mActivity.getResources().getDimensionPixelSize(R.dimen.material_drawer_margin));
|
||||
}
|
||||
}
|
||||
|
||||
if (drawer.mDrawerWidth > -1) {
|
||||
params.width = drawer.mDrawerWidth;
|
||||
} else {
|
||||
params.width = DrawerUIUtils.getOptimalDrawerWidth(drawer.mActivity);
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
}
|
@ -1,544 +0,0 @@
|
||||
package com.mikepenz.materialdrawer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.mikepenz.fastadapter.FastAdapter;
|
||||
import com.mikepenz.fastadapter.IAdapter;
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter;
|
||||
import com.mikepenz.fastadapter.listeners.OnClickListener;
|
||||
import com.mikepenz.fastadapter.listeners.OnLongClickListener;
|
||||
import com.mikepenz.materialdrawer.interfaces.ICrossfader;
|
||||
import com.mikepenz.materialdrawer.model.MiniDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.MiniProfileDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 15.07.15.
|
||||
* Don't count this for real yet. it's just a quick try on creating a Gmail like panel
|
||||
*/
|
||||
public class MiniDrawer {
|
||||
public static final int PROFILE = 1;
|
||||
public static final int ITEM = 2;
|
||||
|
||||
private LinearLayout mContainer;
|
||||
private RecyclerView mRecyclerView;
|
||||
protected FastAdapter<IDrawerItem> mAdapter;
|
||||
protected ItemAdapter<IDrawerItem> mItemAdapter;
|
||||
|
||||
private Drawer mDrawer;
|
||||
|
||||
/**
|
||||
* Provide the Drawer which will be used as dataSource for the drawerItems
|
||||
*
|
||||
* @param drawer
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withDrawer(@NonNull Drawer drawer) {
|
||||
this.mDrawer = drawer;
|
||||
return this;
|
||||
}
|
||||
|
||||
private AccountHeader mAccountHeader;
|
||||
|
||||
/**
|
||||
* Provide the AccountHeader which will be used as the dataSource for the profiles
|
||||
*
|
||||
* @param accountHeader
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withAccountHeader(@NonNull AccountHeader accountHeader) {
|
||||
this.mAccountHeader = accountHeader;
|
||||
return this;
|
||||
}
|
||||
|
||||
private ICrossfader mCrossFader;
|
||||
|
||||
/**
|
||||
* Provide the Crossfader implementation which is used with this MiniDrawer
|
||||
*
|
||||
* @param crossFader
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withCrossFader(@NonNull ICrossfader crossFader) {
|
||||
this.mCrossFader = crossFader;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mInnerShadow = false;
|
||||
|
||||
/**
|
||||
* set to true if you want to show the innerShadow on the MiniDrawer
|
||||
*
|
||||
* @param innerShadow
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withInnerShadow(boolean innerShadow) {
|
||||
this.mInnerShadow = innerShadow;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mInRTL = false;
|
||||
|
||||
/**
|
||||
* set to true if you want the MiniDrawer in RTL mode
|
||||
*
|
||||
* @param inRTL
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withInRTL(boolean inRTL) {
|
||||
this.mInRTL = inRTL;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mIncludeSecondaryDrawerItems = false;
|
||||
|
||||
/**
|
||||
* set to true if you also want to display secondaryDrawerItems
|
||||
*
|
||||
* @param includeSecondaryDrawerItems
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withIncludeSecondaryDrawerItems(boolean includeSecondaryDrawerItems) {
|
||||
this.mIncludeSecondaryDrawerItems = includeSecondaryDrawerItems;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mEnableSelectedMiniDrawerItemBackground = false;
|
||||
|
||||
/**
|
||||
* set to true if you want to display the background for the miniDrawerItem
|
||||
*
|
||||
* @param enableSelectedMiniDrawerItemBackground
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withEnableSelectedMiniDrawerItemBackground(boolean enableSelectedMiniDrawerItemBackground) {
|
||||
this.mEnableSelectedMiniDrawerItemBackground = enableSelectedMiniDrawerItemBackground;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mEnableProfileClick = true;
|
||||
|
||||
/**
|
||||
* set to false if you do not want the profile image to toggle to the normal drawers profile selection
|
||||
*
|
||||
* @param enableProfileClick
|
||||
* @return this
|
||||
*/
|
||||
public MiniDrawer withEnableProfileClick(boolean enableProfileClick) {
|
||||
this.mEnableProfileClick = enableProfileClick;
|
||||
return this;
|
||||
}
|
||||
|
||||
private OnMiniDrawerItemClickListener mOnMiniDrawerItemClickListener;
|
||||
|
||||
/**
|
||||
* Define the onMiniDrawerItemClickListener called before any logic in the MiniDrawer is run, allows you to intercept the default behavior
|
||||
*
|
||||
* @param onMiniDrawerItemClickListener
|
||||
* @return this
|
||||
*/
|
||||
public MiniDrawer withOnMiniDrawerItemClickListener(OnMiniDrawerItemClickListener onMiniDrawerItemClickListener) {
|
||||
this.mOnMiniDrawerItemClickListener = onMiniDrawerItemClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private OnClickListener<IDrawerItem> mOnMiniDrawerItemOnClickListener;
|
||||
|
||||
/**
|
||||
* Define an onClickListener for the MiniDrawer item adapter. WARNING: this will completely overwrite the default behavior
|
||||
* You may want to check the `OnMiniDrawerItemClickListener` (withOnMiniDrawerItemClickListener) which just hooks into the default behavior
|
||||
*
|
||||
* @param onMiniDrawerItemOnClickListener
|
||||
* @return this
|
||||
*/
|
||||
public MiniDrawer withOnMiniDrawerItemOnClickListener(OnClickListener<IDrawerItem> onMiniDrawerItemOnClickListener) {
|
||||
this.mOnMiniDrawerItemOnClickListener = onMiniDrawerItemOnClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
private OnLongClickListener<IDrawerItem> mOnMiniDrawerItemLongClickListener;
|
||||
|
||||
/**
|
||||
* Define an onLongClickListener for the MiniDrawer item adapter
|
||||
*
|
||||
* @param onMiniDrawerItemLongClickListener
|
||||
* @return
|
||||
*/
|
||||
public MiniDrawer withOnMiniDrawerItemLongClickListener(OnLongClickListener<IDrawerItem> onMiniDrawerItemLongClickListener) {
|
||||
this.mOnMiniDrawerItemLongClickListener = onMiniDrawerItemLongClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the RecyclerView of this MiniDrawer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the FastAdapter of this MiniDrawer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public FastAdapter<IDrawerItem> getAdapter() {
|
||||
return mAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the ItemAdapter of this MiniDrawer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ItemAdapter<IDrawerItem> getItemAdapter() {
|
||||
return mItemAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the Drawer used to fill this MiniDrawer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Drawer getDrawer() {
|
||||
return mDrawer;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the AccountHeader used to fill the this MiniDrawer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public AccountHeader getAccountHeader() {
|
||||
return mAccountHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the Crossfader used for this MiniDrawer
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ICrossfader getCrossFader() {
|
||||
return mCrossFader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* the defined FastAdapter.OnClickListener which completely replaces the original behavior
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public OnClickListener getOnMiniDrawerItemOnClickListener() {
|
||||
return mOnMiniDrawerItemOnClickListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public OnLongClickListener getOnMiniDrawerItemLongClickListener() {
|
||||
return mOnMiniDrawerItemLongClickListener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* generates a MiniDrawerItem from a IDrawerItem
|
||||
*
|
||||
* @param drawerItem
|
||||
* @return
|
||||
*/
|
||||
public IDrawerItem generateMiniDrawerItem(IDrawerItem drawerItem) {
|
||||
if (drawerItem instanceof SecondaryDrawerItem) {
|
||||
if (drawerItem.isExcludeFromMiniDrawer()) {
|
||||
return null;
|
||||
}
|
||||
return mIncludeSecondaryDrawerItems ? new MiniDrawerItem((SecondaryDrawerItem) drawerItem).withEnableSelectedBackground(mEnableSelectedMiniDrawerItemBackground).withSelectedBackgroundAnimated(false) : null;
|
||||
} else if (drawerItem instanceof PrimaryDrawerItem) {
|
||||
if (drawerItem.isExcludeFromMiniDrawer()) {
|
||||
return null;
|
||||
}
|
||||
return new MiniDrawerItem((PrimaryDrawerItem) drawerItem).withEnableSelectedBackground(mEnableSelectedMiniDrawerItemBackground).withSelectedBackgroundAnimated(false);
|
||||
} else if (drawerItem instanceof ProfileDrawerItem) {
|
||||
if (drawerItem.isExcludeFromMiniDrawer()) {
|
||||
return null;
|
||||
}
|
||||
MiniProfileDrawerItem mpdi = new MiniProfileDrawerItem((ProfileDrawerItem) drawerItem);
|
||||
mpdi.withEnabled(mEnableProfileClick);
|
||||
return mpdi;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the type of a IDrawerItem
|
||||
*
|
||||
* @param drawerItem
|
||||
* @return
|
||||
*/
|
||||
public int getMiniDrawerType(IDrawerItem drawerItem) {
|
||||
if (drawerItem instanceof MiniProfileDrawerItem) {
|
||||
return PROFILE;
|
||||
} else if (drawerItem instanceof MiniDrawerItem) {
|
||||
return ITEM;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* build the MiniDrawer
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
public View build(Context ctx) {
|
||||
mContainer = new LinearLayout(ctx);
|
||||
if (mInnerShadow) {
|
||||
if (!mInRTL) {
|
||||
mContainer.setBackgroundResource(R.drawable.material_drawer_shadow_left);
|
||||
} else {
|
||||
mContainer.setBackgroundResource(R.drawable.material_drawer_shadow_right);
|
||||
}
|
||||
}
|
||||
|
||||
//create and append recyclerView
|
||||
mRecyclerView = new RecyclerView(ctx);
|
||||
mContainer.addView(mRecyclerView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||
|
||||
//set the itemAnimator
|
||||
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
//some style improvements on older devices
|
||||
mRecyclerView.setFadingEdgeLength(0);
|
||||
//set the drawing cache background to the same color as the slider to improve performance
|
||||
//mRecyclerView.setDrawingCacheBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(mActivity, R.attr.material_drawer_background, R.color.material_drawer_background));
|
||||
mRecyclerView.setClipToPadding(false);
|
||||
//additional stuff
|
||||
mRecyclerView.setLayoutManager(new LinearLayoutManager(ctx));
|
||||
//adapter
|
||||
mItemAdapter = new ItemAdapter<>();
|
||||
mAdapter = FastAdapter.with(mItemAdapter);
|
||||
mAdapter.withSelectable(true);
|
||||
mAdapter.withAllowDeselection(false);
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
|
||||
//if the activity with the drawer should be fullscreen add the padding for the statusbar
|
||||
if (mDrawer != null && mDrawer.mDrawerBuilder != null && (mDrawer.mDrawerBuilder.mFullscreen || mDrawer.mDrawerBuilder.mTranslucentStatusBar)) {
|
||||
mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), UIUtils.getStatusBarHeight(ctx), mRecyclerView.getPaddingRight(), mRecyclerView.getPaddingBottom());
|
||||
}
|
||||
|
||||
//if the activity with the drawer should be fullscreen add the padding for the navigationBar
|
||||
if (mDrawer != null && mDrawer.mDrawerBuilder != null && (mDrawer.mDrawerBuilder.mFullscreen || mDrawer.mDrawerBuilder.mTranslucentNavigationBar) && ctx.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), UIUtils.getNavigationBarHeight(ctx));
|
||||
}
|
||||
|
||||
//set the adapter with the items
|
||||
createItems();
|
||||
|
||||
return mContainer;
|
||||
}
|
||||
|
||||
/**
|
||||
* call this method to trigger the onProfileClick on the MiniDrawer
|
||||
*/
|
||||
public void onProfileClick() {
|
||||
//crossfade if we are cross faded
|
||||
if (mCrossFader != null) {
|
||||
if (mCrossFader.isCrossfaded()) {
|
||||
mCrossFader.crossfade();
|
||||
}
|
||||
}
|
||||
|
||||
//update the current profile
|
||||
if (mAccountHeader != null) {
|
||||
IProfile profile = mAccountHeader.getActiveProfile();
|
||||
if (profile instanceof IDrawerItem) {
|
||||
mItemAdapter.set(0, generateMiniDrawerItem((IDrawerItem) profile));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* call this method to trigger the onItemClick on the MiniDrawer
|
||||
*
|
||||
* @param selectedDrawerItem
|
||||
* @return
|
||||
*/
|
||||
public boolean onItemClick(IDrawerItem selectedDrawerItem) {
|
||||
//We only need to clear if the new item is selectable
|
||||
if (selectedDrawerItem.isSelectable()) {
|
||||
//crossfade if we are cross faded
|
||||
if (mCrossFader != null) {
|
||||
if (mCrossFader.isCrossfaded()) {
|
||||
mCrossFader.crossfade();
|
||||
}
|
||||
}
|
||||
//update everything
|
||||
setSelection(selectedDrawerItem.getIdentifier());
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set the selection of the MiniDrawer
|
||||
*
|
||||
* @param identifier the identifier of the item which should be selected (-1 for none)
|
||||
*/
|
||||
public void setSelection(long identifier) {
|
||||
if (identifier == -1) {
|
||||
mAdapter.deselect();
|
||||
}
|
||||
int count = mAdapter.getItemCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
IDrawerItem item = mAdapter.getItem(i);
|
||||
if (item.getIdentifier() == identifier && !item.isSelected()) {
|
||||
mAdapter.deselect();
|
||||
mAdapter.select(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update a MiniDrawerItem (after updating the main Drawer) via its identifier
|
||||
*
|
||||
* @param identifier the identifier of the item which was updated
|
||||
*/
|
||||
public void updateItem(long identifier) {
|
||||
if (mDrawer != null && mAdapter != null && mItemAdapter.getAdapterItems() != null && identifier != -1) {
|
||||
IDrawerItem drawerItem = DrawerUtils.getDrawerItem(getDrawerItems(), identifier);
|
||||
for (int i = 0; i < mItemAdapter.getAdapterItems().size(); i++) {
|
||||
if (mItemAdapter.getAdapterItems().get(i).getIdentifier() == drawerItem.getIdentifier()) {
|
||||
IDrawerItem miniDrawerItem = generateMiniDrawerItem(drawerItem);
|
||||
if (miniDrawerItem != null) {
|
||||
mItemAdapter.set(i, miniDrawerItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates the items for the MiniDrawer
|
||||
*/
|
||||
public void createItems() {
|
||||
mItemAdapter.clear();
|
||||
|
||||
int profileOffset = 0;
|
||||
if (mAccountHeader != null && mAccountHeader.getAccountHeaderBuilder().mProfileImagesVisible) {
|
||||
IProfile profile = mAccountHeader.getActiveProfile();
|
||||
if (profile instanceof IDrawerItem) {
|
||||
mItemAdapter.add(generateMiniDrawerItem((IDrawerItem) profile));
|
||||
profileOffset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int select = -1;
|
||||
if (mDrawer != null) {
|
||||
if (getDrawerItems() != null) {
|
||||
//migrate to miniDrawerItems
|
||||
int length = getDrawerItems().size();
|
||||
|
||||
int position = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
IDrawerItem miniDrawerItem = generateMiniDrawerItem(getDrawerItems().get(i));
|
||||
if (miniDrawerItem != null) {
|
||||
if (miniDrawerItem.isSelected()) {
|
||||
select = position;
|
||||
}
|
||||
mItemAdapter.add(miniDrawerItem);
|
||||
position = position + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (select >= 0) {
|
||||
//+1 because of the profile
|
||||
mAdapter.select(select + profileOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//listener
|
||||
if (mOnMiniDrawerItemOnClickListener != null) {
|
||||
mAdapter.withOnClickListener(mOnMiniDrawerItemOnClickListener);
|
||||
} else {
|
||||
mAdapter.withOnClickListener(new OnClickListener<IDrawerItem>() {
|
||||
@Override
|
||||
public boolean onClick(View v, IAdapter<IDrawerItem> adapter, final IDrawerItem item, final int position) {
|
||||
int type = getMiniDrawerType(item);
|
||||
|
||||
//if a listener is defined and we consume the event return
|
||||
if (mOnMiniDrawerItemClickListener != null && mOnMiniDrawerItemClickListener.onItemClick(v, position, item, type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == ITEM) {
|
||||
//fire the onClickListener also if the specific drawerItem is not Selectable
|
||||
if (item.isSelectable()) {
|
||||
//make sure we are on the original drawerItemList
|
||||
if (mAccountHeader != null && mAccountHeader.isSelectionListShown()) {
|
||||
mAccountHeader.toggleSelectionList(v.getContext());
|
||||
}
|
||||
IDrawerItem drawerItem = mDrawer.getDrawerItem(item.getIdentifier());
|
||||
if (drawerItem != null && !drawerItem.isSelected()) {
|
||||
//set the selection
|
||||
mDrawer.setSelection(item, true);
|
||||
}
|
||||
} else if (mDrawer.getOnDrawerItemClickListener() != null) {
|
||||
//get the original `DrawerItem` from the Drawer as this one will contain all information
|
||||
mDrawer.getOnDrawerItemClickListener().onItemClick(v, position, DrawerUtils.getDrawerItem(getDrawerItems(), item.getIdentifier()));
|
||||
}
|
||||
} else if (type == PROFILE) {
|
||||
if (mAccountHeader != null && !mAccountHeader.isSelectionListShown()) {
|
||||
mAccountHeader.toggleSelectionList(v.getContext());
|
||||
}
|
||||
if (mCrossFader != null) {
|
||||
mCrossFader.crossfade();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
mAdapter.withOnLongClickListener(mOnMiniDrawerItemLongClickListener);
|
||||
mRecyclerView.scrollToPosition(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns always the original drawerItems and not the switched content
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<IDrawerItem> getDrawerItems() {
|
||||
return mDrawer.getOriginalDrawerItems() != null ? mDrawer.getOriginalDrawerItems() : mDrawer.getDrawerItems();
|
||||
}
|
||||
|
||||
|
||||
public interface OnMiniDrawerItemClickListener {
|
||||
/**
|
||||
* @param view
|
||||
* @param position
|
||||
* @param drawerItem
|
||||
* @param type either MiniDrawer.PROFILE or MiniDrawer.ITEM
|
||||
* @return true if the event was consumed
|
||||
*/
|
||||
boolean onItemClick(View view, int position, IDrawerItem drawerItem, int type);
|
||||
}
|
||||
}
|
@ -1,232 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.holder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.model.utils.BadgeDrawableBuilder;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.annotation.Dimension;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import static androidx.annotation.Dimension.DP;
|
||||
import static androidx.annotation.Dimension.PX;
|
||||
|
||||
/**
|
||||
* Class to allow defining a BadgeStyle for the `BadgeDrawerItem`
|
||||
*/
|
||||
public class BadgeStyle {
|
||||
private int mGradientDrawable = R.drawable.material_drawer_badge;
|
||||
private Drawable mBadgeBackground;
|
||||
private ColorHolder mColor;
|
||||
private ColorHolder mColorPressed;
|
||||
private ColorHolder mTextColor;
|
||||
private ColorStateList mTextColorStateList;
|
||||
private DimenHolder mCorners;
|
||||
private DimenHolder mPaddingTopBottom = DimenHolder.fromDp(2); //2 looks best
|
||||
private DimenHolder mPaddingLeftRight = DimenHolder.fromDp(3); //3 looks best
|
||||
private DimenHolder mMinWidth = DimenHolder.fromDp(20); //20 looks nice
|
||||
|
||||
public int getGradientDrawable() {
|
||||
return mGradientDrawable;
|
||||
}
|
||||
|
||||
public BadgeStyle withGradientDrawable(@DrawableRes int gradientDrawable) {
|
||||
this.mGradientDrawable = gradientDrawable;
|
||||
this.mBadgeBackground = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Drawable getBadgeBackground() {
|
||||
return mBadgeBackground;
|
||||
}
|
||||
|
||||
public BadgeStyle withBadgeBackground(Drawable badgeBackground) {
|
||||
this.mBadgeBackground = badgeBackground;
|
||||
this.mGradientDrawable = -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorHolder getColor() {
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public BadgeStyle withColor(@ColorInt int color) {
|
||||
this.mColor = ColorHolder.fromColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withColorRes(@ColorRes int color) {
|
||||
this.mColor = ColorHolder.fromColorRes(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorHolder getColorPressed() {
|
||||
return mColorPressed;
|
||||
}
|
||||
|
||||
public BadgeStyle withColorPressed(@ColorInt int colorPressed) {
|
||||
this.mColorPressed = ColorHolder.fromColor(colorPressed);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withColorPressedRes(@ColorRes int colorPressed) {
|
||||
this.mColorPressed = ColorHolder.fromColorRes(colorPressed);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorHolder getTextColor() {
|
||||
return mTextColor;
|
||||
}
|
||||
|
||||
public BadgeStyle withTextColor(@ColorInt int textColor) {
|
||||
this.mTextColor = ColorHolder.fromColor(textColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withTextColorRes(@ColorRes int textColor) {
|
||||
this.mTextColor = ColorHolder.fromColorRes(textColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withTextColorStateList(ColorStateList textColorStateList) {
|
||||
this.mTextColor = null;
|
||||
this.mTextColorStateList = textColorStateList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimenHolder getCorners() {
|
||||
return mCorners;
|
||||
}
|
||||
|
||||
public BadgeStyle withCorners(@Dimension(unit = PX) int cornersPx) {
|
||||
this.mCorners = DimenHolder.fromPixel(cornersPx);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withCornersDp(@Dimension(unit = DP) int corners) {
|
||||
this.mCorners = DimenHolder.fromDp(corners);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withCorners(DimenHolder corners) {
|
||||
this.mCorners = corners;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimenHolder getPaddingLeftRight() {
|
||||
return mPaddingLeftRight;
|
||||
}
|
||||
|
||||
public BadgeStyle withPaddingLeftRightPx(@Dimension(unit = PX) int paddingLeftRight) {
|
||||
this.mPaddingLeftRight = DimenHolder.fromPixel(paddingLeftRight);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withPaddingLeftRightDp(@Dimension(unit = DP) int paddingLeftRight) {
|
||||
this.mPaddingLeftRight = DimenHolder.fromDp(paddingLeftRight);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withPaddingLeftRightRes(@DimenRes int paddingLeftRight) {
|
||||
this.mPaddingLeftRight = DimenHolder.fromResource(paddingLeftRight);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimenHolder getPaddingTopBottom() {
|
||||
return mPaddingTopBottom;
|
||||
}
|
||||
|
||||
public BadgeStyle withPaddingTopBottomPx(@Dimension(unit = PX) int paddingTopBottom) {
|
||||
this.mPaddingTopBottom = DimenHolder.fromPixel(paddingTopBottom);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withPaddingTopBottomDp(@Dimension(unit = DP) int paddingTopBottom) {
|
||||
this.mPaddingTopBottom = DimenHolder.fromDp(paddingTopBottom);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withPaddingTopBottomRes(@DimenRes int paddingTopBottom) {
|
||||
this.mPaddingTopBottom = DimenHolder.fromResource(paddingTopBottom);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withPadding(@Dimension(unit = PX) int padding) {
|
||||
this.mPaddingLeftRight = DimenHolder.fromPixel(padding);
|
||||
this.mPaddingTopBottom = DimenHolder.fromPixel(padding);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withPadding(DimenHolder padding) {
|
||||
this.mPaddingLeftRight = padding;
|
||||
this.mPaddingTopBottom = padding;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimenHolder getMinWidth() {
|
||||
return mMinWidth;
|
||||
}
|
||||
|
||||
public BadgeStyle withMinWidth(@Dimension(unit = PX) int minWidth) {
|
||||
this.mMinWidth = DimenHolder.fromPixel(minWidth);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle withMinWidth(DimenHolder minWidth) {
|
||||
this.mMinWidth = minWidth;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BadgeStyle() {
|
||||
}
|
||||
|
||||
public BadgeStyle(@ColorInt int color, @ColorInt int colorPressed) {
|
||||
this.mColor = ColorHolder.fromColor(color);
|
||||
this.mColorPressed = ColorHolder.fromColor(colorPressed);
|
||||
}
|
||||
|
||||
public BadgeStyle(@DrawableRes int gradientDrawable, @ColorInt int color, @ColorInt int colorPressed, @ColorInt int textColor) {
|
||||
this.mGradientDrawable = gradientDrawable;
|
||||
this.mColor = ColorHolder.fromColor(color);
|
||||
this.mColorPressed = ColorHolder.fromColor(colorPressed);
|
||||
this.mTextColor = ColorHolder.fromColor(textColor);
|
||||
}
|
||||
|
||||
public void style(TextView badgeTextView) {
|
||||
style(badgeTextView, null);
|
||||
}
|
||||
|
||||
public void style(TextView badgeTextView, ColorStateList colorStateList) {
|
||||
Context ctx = badgeTextView.getContext();
|
||||
//set background for badge
|
||||
if (mBadgeBackground == null) {
|
||||
ViewCompat.setBackground(badgeTextView, new BadgeDrawableBuilder(this).build(ctx));
|
||||
} else {
|
||||
ViewCompat.setBackground(badgeTextView, mBadgeBackground);
|
||||
}
|
||||
|
||||
//set the badge text color
|
||||
if (mTextColor != null) {
|
||||
ColorHolder.applyToOr(mTextColor, badgeTextView, null);
|
||||
} else if (mTextColorStateList != null) {
|
||||
badgeTextView.setTextColor(mTextColorStateList);
|
||||
} else if (colorStateList != null) {
|
||||
badgeTextView.setTextColor(colorStateList);
|
||||
}
|
||||
|
||||
//set the padding
|
||||
int paddingLeftRight = mPaddingLeftRight.asPixel(ctx);
|
||||
int paddingTopBottom = mPaddingTopBottom.asPixel(ctx);
|
||||
badgeTextView.setPadding(paddingLeftRight, paddingTopBottom, paddingLeftRight, paddingTopBottom);
|
||||
|
||||
//set the min width
|
||||
badgeTextView.setMinWidth(mMinWidth.asPixel(ctx));
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.holder;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 13.07.15.
|
||||
*/
|
||||
public class ColorHolder extends com.mikepenz.materialize.holder.ColorHolder {
|
||||
public ColorHolder() {
|
||||
}
|
||||
|
||||
public static ColorHolder fromColorRes(@ColorRes int colorRes) {
|
||||
ColorHolder colorHolder = new ColorHolder();
|
||||
colorHolder.setColorRes(colorRes);
|
||||
return colorHolder;
|
||||
}
|
||||
|
||||
public static ColorHolder fromColor(@ColorInt int colorInt) {
|
||||
ColorHolder colorHolder = new ColorHolder();
|
||||
colorHolder.setColorInt(colorInt);
|
||||
return colorHolder;
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.holder;
|
||||
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.annotation.Dimension;
|
||||
|
||||
import static androidx.annotation.Dimension.DP;
|
||||
import static androidx.annotation.Dimension.PX;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 13.07.15.
|
||||
*/
|
||||
public class DimenHolder extends com.mikepenz.materialize.holder.DimenHolder {
|
||||
public DimenHolder() {
|
||||
|
||||
}
|
||||
|
||||
public static DimenHolder fromPixel(@Dimension(unit = PX) int pixel) {
|
||||
DimenHolder dimenHolder = new DimenHolder();
|
||||
dimenHolder.setPixel(pixel);
|
||||
return dimenHolder;
|
||||
}
|
||||
|
||||
public static DimenHolder fromDp(@Dimension(unit = DP) int dp) {
|
||||
DimenHolder dimenHolder = new DimenHolder();
|
||||
dimenHolder.setDp(dp);
|
||||
return dimenHolder;
|
||||
}
|
||||
|
||||
public static DimenHolder fromResource(@DimenRes int resource) {
|
||||
DimenHolder dimenHolder = new DimenHolder();
|
||||
dimenHolder.setResource(resource);
|
||||
return dimenHolder;
|
||||
}
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.holder;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mikepenz.iconics.IconicsDrawable;
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 13.07.15.
|
||||
*/
|
||||
|
||||
public class ImageHolder extends com.mikepenz.materialize.holder.ImageHolder {
|
||||
private IIcon mIIcon;
|
||||
|
||||
public ImageHolder(String url) {
|
||||
super(url);
|
||||
}
|
||||
|
||||
public ImageHolder(Uri uri) {
|
||||
super(uri);
|
||||
}
|
||||
|
||||
public ImageHolder(Drawable icon) {
|
||||
super(icon);
|
||||
}
|
||||
|
||||
public ImageHolder(Bitmap bitmap) {
|
||||
super(bitmap);
|
||||
}
|
||||
|
||||
public ImageHolder(@DrawableRes int iconRes) {
|
||||
super(iconRes);
|
||||
}
|
||||
|
||||
public ImageHolder(IIcon iicon) {
|
||||
super((Bitmap) null);
|
||||
this.mIIcon = iicon;
|
||||
}
|
||||
|
||||
public IIcon getIIcon() {
|
||||
return mIIcon;
|
||||
}
|
||||
|
||||
public void setIIcon(IIcon mIIcon) {
|
||||
this.mIIcon = mIIcon;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets an existing image to the imageView
|
||||
*
|
||||
* @param imageView
|
||||
* @param tag used to identify imageViews and define different placeholders
|
||||
* @return true if an image was set
|
||||
*/
|
||||
@Override
|
||||
public boolean applyTo(ImageView imageView, String tag) {
|
||||
if (getUri() != null) {
|
||||
boolean consumed = DrawerImageLoader.getInstance().setImage(imageView, getUri(), tag);
|
||||
if (!consumed) {
|
||||
imageView.setImageURI(getUri());
|
||||
}
|
||||
} else if (getIcon() != null) {
|
||||
imageView.setImageDrawable(getIcon());
|
||||
} else if (getBitmap() != null) {
|
||||
imageView.setImageBitmap(getBitmap());
|
||||
} else if (getIconRes() != -1) {
|
||||
imageView.setImageResource(getIconRes());
|
||||
} else if (mIIcon != null) {
|
||||
imageView.setImageDrawable(new IconicsDrawable(imageView.getContext(), mIIcon).actionBar());
|
||||
} else {
|
||||
imageView.setImageBitmap(null);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* this only handles Drawables
|
||||
*
|
||||
* @param ctx
|
||||
* @param iconColor
|
||||
* @param tint
|
||||
* @return
|
||||
*/
|
||||
public Drawable decideIcon(Context ctx, int iconColor, boolean tint, int paddingDp) {
|
||||
Drawable icon = getIcon();
|
||||
|
||||
if (mIIcon != null) {
|
||||
icon = new IconicsDrawable(ctx, mIIcon).color(iconColor).sizeDp(24).paddingDp(paddingDp);
|
||||
} else if (getIconRes() != -1) {
|
||||
icon = AppCompatResources.getDrawable(ctx, getIconRes());
|
||||
} else if (getUri() != null) {
|
||||
try {
|
||||
InputStream inputStream = ctx.getContentResolver().openInputStream(getUri());
|
||||
icon = Drawable.createFromStream(inputStream, getUri().toString());
|
||||
} catch (FileNotFoundException e) {
|
||||
//no need to handle this
|
||||
}
|
||||
}
|
||||
|
||||
//if we got an icon AND we have auto tinting enabled AND it is no IIcon, tint it ;)
|
||||
if (icon != null && tint && mIIcon == null) {
|
||||
icon = icon.mutate();
|
||||
icon.setColorFilter(iconColor, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* a small static helper which catches nulls for us
|
||||
*
|
||||
* @param imageHolder
|
||||
* @param ctx
|
||||
* @param iconColor
|
||||
* @param tint
|
||||
* @return
|
||||
*/
|
||||
public static Drawable decideIcon(ImageHolder imageHolder, Context ctx, int iconColor, boolean tint, int paddingDp) {
|
||||
if (imageHolder == null) {
|
||||
return null;
|
||||
} else {
|
||||
return imageHolder.decideIcon(ctx, iconColor, tint, paddingDp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* decides which icon to apply or hide this view
|
||||
*
|
||||
* @param imageHolder
|
||||
* @param imageView
|
||||
* @param iconColor
|
||||
* @param tint
|
||||
* @param paddingDp
|
||||
*/
|
||||
public static void applyDecidedIconOrSetGone(ImageHolder imageHolder, ImageView imageView, int iconColor, boolean tint, int paddingDp) {
|
||||
if (imageHolder != null && imageView != null) {
|
||||
Drawable drawable = ImageHolder.decideIcon(imageHolder, imageView.getContext(), iconColor, tint, paddingDp);
|
||||
if (drawable != null) {
|
||||
imageView.setImageDrawable(drawable);
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
} else if (imageHolder.getBitmap() != null) {
|
||||
imageView.setImageBitmap(imageHolder.getBitmap());
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
imageView.setVisibility(View.GONE);
|
||||
}
|
||||
} else if (imageView != null) {
|
||||
imageView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.holder;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 13.07.15.
|
||||
*/
|
||||
public class StringHolder extends com.mikepenz.materialize.holder.StringHolder {
|
||||
public StringHolder(CharSequence text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
public StringHolder(@StringRes int textRes) {
|
||||
super(textRes);
|
||||
}
|
||||
}
|
@ -1,145 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.icons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.iconics.typeface.ITypeface;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 01.11.14.
|
||||
*/
|
||||
public class MaterialDrawerFont implements ITypeface {
|
||||
private static final String TTF_FILE = "materialdrawerfont-font-v5.0.0.ttf";
|
||||
|
||||
private static Typeface typeface = null;
|
||||
|
||||
private static HashMap<String, Character> mChars;
|
||||
|
||||
@Override
|
||||
public IIcon getIcon(String key) {
|
||||
return Icon.valueOf(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<String, Character> getCharacters() {
|
||||
if (mChars == null) {
|
||||
HashMap<String, Character> aChars = new HashMap<String, Character>();
|
||||
for (Icon v : Icon.values()) {
|
||||
aChars.put(v.name(), v.character);
|
||||
}
|
||||
mChars = aChars;
|
||||
}
|
||||
|
||||
return mChars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMappingPrefix() {
|
||||
return "mdf";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFontName() {
|
||||
return "MaterialDrawerFont";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return "5.0.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconCount() {
|
||||
return mChars.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getIcons() {
|
||||
Collection<String> icons = new LinkedList<String>();
|
||||
|
||||
for (Icon value : Icon.values()) {
|
||||
icons.add(value.name());
|
||||
}
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAuthor() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUrl() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLicense() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLicenseUrl() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Typeface getTypeface(Context context) {
|
||||
if (typeface == null) {
|
||||
try {
|
||||
typeface = Typeface.createFromAsset(context.getAssets(), "fonts/" + TTF_FILE);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return typeface;
|
||||
}
|
||||
|
||||
public enum Icon implements IIcon {
|
||||
mdf_arrow_drop_down('\ue5c5'),
|
||||
mdf_arrow_drop_up('\ue5c7'),
|
||||
mdf_expand_less('\ue5ce'),
|
||||
mdf_expand_more('\ue5cf'),
|
||||
mdf_person('\ue7fd');
|
||||
|
||||
char character;
|
||||
|
||||
Icon(char character) {
|
||||
this.character = character;
|
||||
}
|
||||
|
||||
public String getFormattedName() {
|
||||
return "{" + name() + "}";
|
||||
}
|
||||
|
||||
public char getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
|
||||
// remember the typeface so we can use it later
|
||||
private static ITypeface typeface;
|
||||
|
||||
public ITypeface getTypeface() {
|
||||
if (typeface == null) {
|
||||
typeface = new MaterialDrawerFont();
|
||||
}
|
||||
return typeface;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.interfaces;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 18.07.15.
|
||||
*/
|
||||
public interface ICrossfader {
|
||||
void crossfade();
|
||||
|
||||
boolean isCrossfaded();
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.interfaces;
|
||||
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the checked state
|
||||
* of a compound button changed.
|
||||
*/
|
||||
public interface OnCheckedChangeListener {
|
||||
/**
|
||||
* Called when the checked state of a compound button has changed.
|
||||
*
|
||||
* @param buttonView The compound button view whose state has changed.
|
||||
* @param isChecked The new checked state of buttonView.
|
||||
*/
|
||||
void onCheckedChanged(IDrawerItem drawerItem, CompoundButton buttonView, boolean isChecked);
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.BadgeStyle;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public abstract class AbstractBadgeableDrawerItem<Item extends AbstractBadgeableDrawerItem> extends BaseDescribeableDrawerItem<Item, AbstractBadgeableDrawerItem.ViewHolder> implements ColorfulBadgeable<Item> {
|
||||
protected StringHolder mBadge;
|
||||
protected BadgeStyle mBadgeStyle = new BadgeStyle();
|
||||
|
||||
@Override
|
||||
public Item withBadge(StringHolder badge) {
|
||||
this.mBadge = badge;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item withBadge(String badge) {
|
||||
this.mBadge = new StringHolder(badge);
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item withBadge(@StringRes int badgeRes) {
|
||||
this.mBadge = new StringHolder(badgeRes);
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item withBadgeStyle(BadgeStyle badgeStyle) {
|
||||
this.mBadgeStyle = badgeStyle;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public StringHolder getBadge() {
|
||||
return mBadge;
|
||||
}
|
||||
|
||||
public BadgeStyle getBadgeStyle() {
|
||||
return mBadgeStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_primary;/*"PRIMARY_ITEM"*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_primary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
//bind the basic view parts
|
||||
bindViewHelper(viewHolder);
|
||||
|
||||
//set the text for the badge or hide
|
||||
boolean badgeVisible = StringHolder.applyToOrHide(mBadge, viewHolder.badge);
|
||||
//style the badge if it is visible
|
||||
if (badgeVisible) {
|
||||
mBadgeStyle.style(viewHolder.badge, getTextColorStateList(getColor(ctx), getSelectedTextColor(ctx)));
|
||||
viewHolder.badgeContainer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
viewHolder.badgeContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//define the typeface for our textViews
|
||||
if (getTypeface() != null) {
|
||||
viewHolder.badge.setTypeface(getTypeface());
|
||||
}
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends BaseViewHolder {
|
||||
private View badgeContainer;
|
||||
private TextView badge;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
this.badgeContainer = view.findViewById(R.id.material_drawer_badge_container);
|
||||
this.badge = (TextView) view.findViewById(R.id.material_drawer_badge);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,449 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.OnPostBindViewListener;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Selectable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Tagable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 14.07.15.
|
||||
*/
|
||||
public abstract class AbstractDrawerItem<T, VH extends RecyclerView.ViewHolder> implements IDrawerItem<T, VH>, Selectable<T>, Tagable<T> {
|
||||
|
||||
protected boolean mExcludeFromMiniDrawer = false;
|
||||
|
||||
@Override
|
||||
public boolean isExcludeFromMiniDrawer() {
|
||||
return mExcludeFromMiniDrawer;
|
||||
}
|
||||
|
||||
// the identifier for this item
|
||||
protected long mIdentifier = -1;
|
||||
|
||||
/**
|
||||
* set the identifier of this item
|
||||
*
|
||||
* @param identifier
|
||||
* @return
|
||||
*/
|
||||
public T withIdentifier(long identifier) {
|
||||
this.mIdentifier = identifier;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the identifier of this item
|
||||
* -1 is the default not set state
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public long getIdentifier() {
|
||||
return mIdentifier;
|
||||
}
|
||||
|
||||
// the tag for this item
|
||||
protected Object mTag;
|
||||
|
||||
/**
|
||||
* set the tag of this item
|
||||
*
|
||||
* @param object
|
||||
* @return
|
||||
*/
|
||||
public T withTag(Object object) {
|
||||
this.mTag = object;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tag of this item
|
||||
*/
|
||||
@Override
|
||||
public Object getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
// defines if this item is enabled
|
||||
protected boolean mEnabled = true;
|
||||
|
||||
/**
|
||||
* set if this item is enabled
|
||||
*
|
||||
* @param enabled true if this item is enabled
|
||||
* @return
|
||||
*/
|
||||
public T withEnabled(boolean enabled) {
|
||||
this.mEnabled = enabled;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this item is enabled
|
||||
*/
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return mEnabled;
|
||||
}
|
||||
|
||||
// defines if the item is selected
|
||||
protected boolean mSelected = false;
|
||||
|
||||
/**
|
||||
* set if this item is selected
|
||||
*
|
||||
* @param selected true if this item is selected
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public T withSetSelected(boolean selected) {
|
||||
this.mSelected = selected;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this item is selected
|
||||
*/
|
||||
@Override
|
||||
public boolean isSelected() {
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
// defines if this item is selectable
|
||||
protected boolean mSelectable = true;
|
||||
|
||||
/**
|
||||
* set if this item is selectable
|
||||
*
|
||||
* @param selectable true if this item is selectable
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public T withSelectable(boolean selectable) {
|
||||
this.mSelectable = selectable;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this item is selectable
|
||||
*/
|
||||
@Override
|
||||
public boolean isSelectable() {
|
||||
return mSelectable;
|
||||
}
|
||||
|
||||
// defines if the item's background' change should be animated when it is (de)selected
|
||||
protected boolean mSelectedBackgroundAnimated = true;
|
||||
|
||||
/**
|
||||
* set if this item is selectable
|
||||
*
|
||||
* @param selectedBackgroundAnimated true if this item's background should fade when it is (de) selected
|
||||
* @return
|
||||
*/
|
||||
public T withSelectedBackgroundAnimated(boolean selectedBackgroundAnimated) {
|
||||
this.mSelectedBackgroundAnimated = selectedBackgroundAnimated;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this item is selectable
|
||||
*/
|
||||
public boolean isSelectedBackgroundAnimated() {
|
||||
return mSelectedBackgroundAnimated;
|
||||
}
|
||||
|
||||
public Drawer.OnDrawerItemClickListener mOnDrawerItemClickListener = null;
|
||||
|
||||
public Drawer.OnDrawerItemClickListener getOnDrawerItemClickListener() {
|
||||
return mOnDrawerItemClickListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* this listener is called when an item is clicked in the drawer.
|
||||
* WARNING: don't overwrite this in the Switch / Toggle drawerItems if you want the toggle / switch to be selected
|
||||
* if the item is clicked and the item is not selectable.
|
||||
*
|
||||
* @param onDrawerItemClickListener
|
||||
* @return
|
||||
*/
|
||||
public T withOnDrawerItemClickListener(Drawer.OnDrawerItemClickListener onDrawerItemClickListener) {
|
||||
this.mOnDrawerItemClickListener = onDrawerItemClickListener;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
protected OnPostBindViewListener mOnPostBindViewListener = null;
|
||||
|
||||
public OnPostBindViewListener getOnPostBindViewListener() {
|
||||
return mOnPostBindViewListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* add this listener and hook in if you want to modify a drawerItems view without creating a custom drawer item
|
||||
*
|
||||
* @param onPostBindViewListener
|
||||
* @return
|
||||
*/
|
||||
public T withPostOnBindViewListener(OnPostBindViewListener onPostBindViewListener) {
|
||||
this.mOnPostBindViewListener = onPostBindViewListener;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* is called after bindView to allow some post creation setps
|
||||
*
|
||||
* @param drawerItem the drawerItem which is bound to the view
|
||||
* @param view the currently view which will be bound
|
||||
*/
|
||||
public void onPostBindView(IDrawerItem drawerItem, View view) {
|
||||
if (mOnPostBindViewListener != null) {
|
||||
mOnPostBindViewListener.onBindView(drawerItem, view);
|
||||
}
|
||||
}
|
||||
|
||||
// the parent of this item
|
||||
private IDrawerItem mParent;
|
||||
|
||||
/**
|
||||
* @return the parent of this item
|
||||
*/
|
||||
@Override
|
||||
public IDrawerItem getParent() {
|
||||
return mParent;
|
||||
}
|
||||
|
||||
/**
|
||||
* the parent for this item
|
||||
*
|
||||
* @param parent it's parent
|
||||
* @return this
|
||||
*/
|
||||
@Override
|
||||
public IDrawerItem withParent(IDrawerItem parent) {
|
||||
this.mParent = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
// the subItems to expand for this item
|
||||
protected List<IDrawerItem> mSubItems;
|
||||
|
||||
/**
|
||||
* a list of subItems
|
||||
* **WARNING** Make sure the subItems provided already have identifiers
|
||||
*
|
||||
* @param subItems
|
||||
* @return
|
||||
*/
|
||||
public T withSubItems(List<IDrawerItem> subItems) {
|
||||
this.mSubItems = subItems;
|
||||
for (IDrawerItem subItem : subItems) {
|
||||
subItem.withParent(this);
|
||||
}
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* an array of subItems
|
||||
* **WARNING** Make sure the subItems provided already have identifiers
|
||||
*
|
||||
* @param subItems
|
||||
* @return
|
||||
*/
|
||||
public T withSubItems(IDrawerItem... subItems) {
|
||||
if (mSubItems == null) {
|
||||
mSubItems = new ArrayList<>();
|
||||
}
|
||||
for (IDrawerItem subItem : subItems) {
|
||||
subItem.withParent(this);
|
||||
}
|
||||
Collections.addAll(mSubItems, subItems);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the subItems for this item
|
||||
*/
|
||||
@Override
|
||||
public List<IDrawerItem> getSubItems() {
|
||||
return mSubItems;
|
||||
}
|
||||
|
||||
//if the this item is currently expanded
|
||||
private boolean mExpanded = false;
|
||||
|
||||
/**
|
||||
* @param expanded defines if this item is now expanded or not
|
||||
* @return this
|
||||
*/
|
||||
@Override
|
||||
public T withIsExpanded(boolean expanded) {
|
||||
mExpanded = expanded;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if this item is currently expaneded
|
||||
*/
|
||||
@Override
|
||||
public boolean isExpanded() {
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* overwrite this method and return true if the item should auto expand on click, false if you want to disable this
|
||||
*
|
||||
* @return true if this item should auto expand in the adapter
|
||||
*/
|
||||
@Override
|
||||
public boolean isAutoExpanding() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* generates a view by the defined LayoutRes
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public View generateView(Context ctx) {
|
||||
VH viewHolder = getViewHolder(LayoutInflater.from(ctx).inflate(getLayoutRes(), null, false));
|
||||
bindView(viewHolder, Collections.emptyList());
|
||||
return viewHolder.itemView;
|
||||
}
|
||||
|
||||
/**
|
||||
* generates a view by the defined LayoutRes and pass the LayoutParams from the parent
|
||||
*
|
||||
* @param ctx
|
||||
* @param parent
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public View generateView(Context ctx, ViewGroup parent) {
|
||||
VH viewHolder = getViewHolder(LayoutInflater.from(ctx).inflate(getLayoutRes(), parent, false));
|
||||
bindView(viewHolder, Collections.emptyList());
|
||||
return viewHolder.itemView;
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
@Override
|
||||
public void bindView(VH holder, List<Object> payloads) {
|
||||
holder.itemView.setTag(R.id.material_drawer_item, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* called when the view is unbound
|
||||
*
|
||||
* @param holder
|
||||
*/
|
||||
@Override
|
||||
public void unbindView(VH holder) {
|
||||
holder.itemView.clearAnimation();
|
||||
}
|
||||
|
||||
/**
|
||||
* View got attached to the window
|
||||
*
|
||||
* @param holder
|
||||
*/
|
||||
@Override
|
||||
public void attachToWindow(VH holder) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* View got detached from the window
|
||||
*
|
||||
* @param holder
|
||||
*/
|
||||
@Override
|
||||
public void detachFromWindow(VH holder) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* is called when the ViewHolder is in a transient state. return true if you want to reuse
|
||||
* that view anyways
|
||||
*
|
||||
* @param holder the viewHolder for the view which failed to recycle
|
||||
* @return true if we want to recycle anyways (false - it get's destroyed)
|
||||
*/
|
||||
@Override
|
||||
public boolean failedToRecycle(VH holder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ViewHolder for our item, using the provided View.
|
||||
*
|
||||
* @param parent
|
||||
* @return the ViewHolder for this Item
|
||||
*/
|
||||
@Override
|
||||
public VH getViewHolder(ViewGroup parent) {
|
||||
return getViewHolder(LayoutInflater.from(parent.getContext()).inflate(getLayoutRes(), parent, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ViewHolder for our item, using the provided View.
|
||||
*
|
||||
* @param v
|
||||
* @return the ViewHolder for this Item
|
||||
*/
|
||||
public abstract VH getViewHolder(View v);
|
||||
|
||||
/**
|
||||
* If this item equals to the given identifier
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(long id) {
|
||||
return id == mIdentifier;
|
||||
}
|
||||
|
||||
public boolean equals(int id) {
|
||||
return id == mIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this item equals to the given object
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
AbstractDrawerItem<?, ?> that = (AbstractDrawerItem<?, ?>) o;
|
||||
return mIdentifier == that.mIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* the hashCode implementation
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Long.valueOf(mIdentifier).hashCode();
|
||||
}
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.interfaces.OnCheckedChangeListener;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public abstract class AbstractSwitchableDrawerItem<Item extends AbstractSwitchableDrawerItem> extends BaseDescribeableDrawerItem<Item, AbstractSwitchableDrawerItem.ViewHolder> {
|
||||
|
||||
private boolean switchEnabled = true;
|
||||
|
||||
private boolean checked = false;
|
||||
private OnCheckedChangeListener onCheckedChangeListener = null;
|
||||
|
||||
public Item withChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public Item withSwitchEnabled(boolean switchEnabled) {
|
||||
this.switchEnabled = switchEnabled;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public Item withOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
|
||||
this.onCheckedChangeListener = onCheckedChangeListener;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public Item withCheckable(boolean checkable) {
|
||||
return withSelectable(checkable);
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
public boolean isSwitchEnabled() {
|
||||
return switchEnabled;
|
||||
}
|
||||
|
||||
public OnCheckedChangeListener getOnCheckedChangeListener() {
|
||||
return onCheckedChangeListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_primary_switch;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_switch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(final ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
//bind the basic view parts
|
||||
bindViewHelper(viewHolder);
|
||||
|
||||
//handle the switch
|
||||
viewHolder.switchView.setOnCheckedChangeListener(null);
|
||||
viewHolder.switchView.setChecked(checked);
|
||||
viewHolder.switchView.setOnCheckedChangeListener(checkedChangeListener);
|
||||
viewHolder.switchView.setEnabled(switchEnabled);
|
||||
|
||||
//add a onDrawerItemClickListener here to be able to check / uncheck if the drawerItem can't be selected
|
||||
withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
|
||||
@Override
|
||||
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
|
||||
if (!isSelectable()) {
|
||||
checked = !checked;
|
||||
viewHolder.switchView.setChecked(checked);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends BaseViewHolder {
|
||||
private SwitchCompat switchView;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.switchView = (SwitchCompat) view.findViewById(R.id.material_drawer_switch);
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundButton.OnCheckedChangeListener checkedChangeListener = new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (isEnabled()) {
|
||||
checked = isChecked;
|
||||
if (getOnCheckedChangeListener() != null) {
|
||||
getOnCheckedChangeListener().onCheckedChanged(AbstractSwitchableDrawerItem.this, buttonView, isChecked);
|
||||
}
|
||||
} else {
|
||||
buttonView.setOnCheckedChangeListener(null);
|
||||
buttonView.setChecked(!isChecked);
|
||||
buttonView.setOnCheckedChangeListener(checkedChangeListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import android.view.View;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.ToggleButton;
|
||||
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.interfaces.OnCheckedChangeListener;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class AbstractToggleableDrawerItem<Item extends AbstractToggleableDrawerItem> extends BaseDescribeableDrawerItem<Item, AbstractToggleableDrawerItem.ViewHolder> {
|
||||
private boolean toggleEnabled = true;
|
||||
|
||||
private boolean checked = false;
|
||||
private OnCheckedChangeListener onCheckedChangeListener = null;
|
||||
|
||||
public Item withChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public Item withToggleEnabled(boolean toggleEnabled) {
|
||||
this.toggleEnabled = toggleEnabled;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public Item withOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
|
||||
this.onCheckedChangeListener = onCheckedChangeListener;
|
||||
return (Item) this;
|
||||
}
|
||||
|
||||
public boolean isChecked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
this.checked = checked;
|
||||
}
|
||||
|
||||
public boolean isToggleEnabled() {
|
||||
return toggleEnabled;
|
||||
}
|
||||
|
||||
public void setToggleEnabled(boolean toggleEnabled) {
|
||||
this.toggleEnabled = toggleEnabled;
|
||||
}
|
||||
|
||||
public OnCheckedChangeListener getOnCheckedChangeListener() {
|
||||
return onCheckedChangeListener;
|
||||
}
|
||||
|
||||
public void setOnCheckedChangeListener(OnCheckedChangeListener onCheckedChangeListener) {
|
||||
this.onCheckedChangeListener = onCheckedChangeListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_primary_toggle;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_toggle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(final ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
//bind the basic view parts
|
||||
bindViewHelper(viewHolder);
|
||||
|
||||
//handle the toggle
|
||||
viewHolder.toggle.setOnCheckedChangeListener(null);
|
||||
viewHolder.toggle.setChecked(checked);
|
||||
viewHolder.toggle.setOnCheckedChangeListener(checkedChangeListener);
|
||||
viewHolder.toggle.setEnabled(toggleEnabled);
|
||||
|
||||
//add a onDrawerItemClickListener here to be able to check / uncheck if the drawerItem can't be selected
|
||||
withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
|
||||
@Override
|
||||
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
|
||||
if (!isSelectable()) {
|
||||
checked = !checked;
|
||||
viewHolder.toggle.setChecked(checked);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends BaseViewHolder {
|
||||
private ToggleButton toggle;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.toggle = (ToggleButton) view.findViewById(R.id.material_drawer_toggle);
|
||||
}
|
||||
}
|
||||
|
||||
private CompoundButton.OnCheckedChangeListener checkedChangeListener = new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
if (isEnabled()) {
|
||||
checked = isChecked;
|
||||
if (getOnCheckedChangeListener() != null) {
|
||||
getOnCheckedChangeListener().onCheckedChanged(AbstractToggleableDrawerItem.this, buttonView, isChecked);
|
||||
}
|
||||
} else {
|
||||
buttonView.setOnCheckedChangeListener(null);
|
||||
buttonView.setChecked(!isChecked);
|
||||
buttonView.setOnCheckedChangeListener(checkedChangeListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import static com.mikepenz.materialdrawer.util.DrawerUIUtils.themeDrawerItem;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public abstract class BaseDescribeableDrawerItem<T, VH extends BaseViewHolder> extends BaseDrawerItem<T, VH> {
|
||||
private StringHolder description;
|
||||
private ColorHolder descriptionTextColor;
|
||||
|
||||
@Override
|
||||
public boolean isExcludeFromMiniDrawer() {
|
||||
return this.excludeFromMiniDrawer;
|
||||
}
|
||||
|
||||
public T withDescription(String description) {
|
||||
this.description = new StringHolder(description);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDescription(@StringRes int descriptionRes) {
|
||||
this.description = new StringHolder(descriptionRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDescriptionTextColor(@ColorInt int color) {
|
||||
this.descriptionTextColor = ColorHolder.fromColor(color);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDescriptionTextColorRes(@ColorRes int colorRes) {
|
||||
this.descriptionTextColor = ColorHolder.fromColorRes(colorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public StringHolder getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public ColorHolder getDescriptionTextColor() {
|
||||
return descriptionTextColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* a helper method to have the logic for all secondaryDrawerItems only once
|
||||
*
|
||||
* @param viewHolder
|
||||
*/
|
||||
protected void bindViewHelper(BaseViewHolder viewHolder) {
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//set the item selected if it is
|
||||
viewHolder.itemView.setSelected(isSelected());
|
||||
|
||||
//set the item enabled if it is
|
||||
viewHolder.itemView.setEnabled(isEnabled());
|
||||
|
||||
//get the correct color for the background
|
||||
int selectedColor = getSelectedColor(ctx);
|
||||
//get the correct color for the text
|
||||
int color = getColor(ctx);
|
||||
ColorStateList selectedTextColor = getTextColorStateList(color, getSelectedTextColor(ctx));
|
||||
//get the correct color for the icon
|
||||
int iconColor = getIconColor(ctx);
|
||||
int selectedIconColor = getSelectedIconColor(ctx);
|
||||
|
||||
//set the background for the item
|
||||
themeDrawerItem(ctx, viewHolder.view, selectedColor, isSelectedBackgroundAnimated());
|
||||
//set the text for the name
|
||||
StringHolder.applyTo(this.getName(), viewHolder.name);
|
||||
//set the text for the description or hide
|
||||
StringHolder.applyToOrHide(this.getDescription(), viewHolder.description);
|
||||
|
||||
//set the colors for textViews
|
||||
viewHolder.name.setTextColor(selectedTextColor);
|
||||
//set the description text color
|
||||
ColorHolder.applyToOr(getDescriptionTextColor(), viewHolder.description, selectedTextColor);
|
||||
|
||||
//define the typeface for our textViews
|
||||
if (getTypeface() != null) {
|
||||
viewHolder.name.setTypeface(getTypeface());
|
||||
viewHolder.description.setTypeface(getTypeface());
|
||||
}
|
||||
|
||||
//get the drawables for our icon and set it
|
||||
Drawable icon = ImageHolder.decideIcon(getIcon(), ctx, iconColor, isIconTinted(), 1);
|
||||
if (icon != null) {
|
||||
Drawable selectedIcon = ImageHolder.decideIcon(getSelectedIcon(), ctx, selectedIconColor, isIconTinted(), 1);
|
||||
ImageHolder.applyMultiIconTo(icon, iconColor, selectedIcon, selectedIconColor, isIconTinted(), viewHolder.icon);
|
||||
} else {
|
||||
ImageHolder.applyDecidedIconOrSetGone(getIcon(), viewHolder.icon, iconColor, isIconTinted(), 1);
|
||||
}
|
||||
|
||||
//for android API 17 --> Padding not applied via xml
|
||||
DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view, level);
|
||||
}
|
||||
}
|
@ -1,356 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Iconable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Nameable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Tagable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Typefaceable;
|
||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import static com.mikepenz.materialdrawer.util.DrawerUIUtils.getBooleanStyleable;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public abstract class BaseDrawerItem<T, VH extends RecyclerView.ViewHolder> extends AbstractDrawerItem<T, VH> implements Nameable<T>, Iconable<T>, Tagable<T>, Typefaceable<T> {
|
||||
protected ImageHolder icon;
|
||||
protected ImageHolder selectedIcon;
|
||||
protected StringHolder name;
|
||||
|
||||
protected boolean iconTinted = false;
|
||||
|
||||
protected ColorHolder selectedColor;
|
||||
protected ColorHolder textColor;
|
||||
protected ColorHolder selectedTextColor;
|
||||
protected ColorHolder disabledTextColor;
|
||||
|
||||
protected ColorHolder iconColor;
|
||||
protected ColorHolder selectedIconColor;
|
||||
protected ColorHolder disabledIconColor;
|
||||
|
||||
protected Typeface typeface = null;
|
||||
|
||||
protected Pair<Integer, ColorStateList> colorStateList;
|
||||
|
||||
protected int level = 1;
|
||||
|
||||
protected boolean excludeFromMiniDrawer = false;
|
||||
|
||||
public T withIcon(ImageHolder icon) {
|
||||
this.icon = icon;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withIcon(Drawable icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withIcon(@DrawableRes int iconRes) {
|
||||
this.icon = new ImageHolder(iconRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedIcon(Drawable selectedIcon) {
|
||||
this.selectedIcon = new ImageHolder(selectedIcon);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedIcon(@DrawableRes int selectedIconRes) {
|
||||
this.selectedIcon = new ImageHolder(selectedIconRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withIcon(IIcon iicon) {
|
||||
this.icon = new ImageHolder(iicon);
|
||||
//if we are on api 21 or higher we use the IconicsDrawable for selection too and color it with the correct color
|
||||
//else we use just the one drawable and enable tinting on press
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
this.selectedIcon = new ImageHolder(iicon);
|
||||
} else {
|
||||
this.withIconTintingEnabled(true);
|
||||
}
|
||||
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withName(StringHolder name) {
|
||||
this.name = name;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withName(String name) {
|
||||
this.name = new StringHolder(name);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withName(@StringRes int nameRes) {
|
||||
this.name = new StringHolder(nameRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedColor(@ColorInt int selectedColor) {
|
||||
this.selectedColor = ColorHolder.fromColor(selectedColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedColorRes(@ColorRes int selectedColorRes) {
|
||||
this.selectedColor = ColorHolder.fromColorRes(selectedColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withTextColor(@ColorInt int textColor) {
|
||||
this.textColor = ColorHolder.fromColor(textColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withTextColorRes(@ColorRes int textColorRes) {
|
||||
this.textColor = ColorHolder.fromColorRes(textColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedTextColor(@ColorInt int selectedTextColor) {
|
||||
this.selectedTextColor = ColorHolder.fromColor(selectedTextColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedTextColorRes(@ColorRes int selectedColorRes) {
|
||||
this.selectedTextColor = ColorHolder.fromColorRes(selectedColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDisabledTextColor(@ColorInt int disabledTextColor) {
|
||||
this.disabledTextColor = ColorHolder.fromColor(disabledTextColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDisabledTextColorRes(@ColorRes int disabledTextColorRes) {
|
||||
this.disabledTextColor = ColorHolder.fromColorRes(disabledTextColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withIconColor(@ColorInt int iconColor) {
|
||||
this.iconColor = ColorHolder.fromColor(iconColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withIconColorRes(@ColorRes int iconColorRes) {
|
||||
this.iconColor = ColorHolder.fromColorRes(iconColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedIconColor(@ColorInt int selectedIconColor) {
|
||||
this.selectedIconColor = ColorHolder.fromColor(selectedIconColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withSelectedIconColorRes(@ColorRes int selectedColorRes) {
|
||||
this.selectedIconColor = ColorHolder.fromColorRes(selectedColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDisabledIconColor(@ColorInt int disabledIconColor) {
|
||||
this.disabledIconColor = ColorHolder.fromColor(disabledIconColor);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withDisabledIconColorRes(@ColorRes int disabledIconColorRes) {
|
||||
this.disabledIconColor = ColorHolder.fromColorRes(disabledIconColorRes);
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* will tint the icon with the default (or set) colors
|
||||
* (default and selected state)
|
||||
*
|
||||
* @param iconTintingEnabled
|
||||
* @return
|
||||
*/
|
||||
public T withIconTintingEnabled(boolean iconTintingEnabled) {
|
||||
this.iconTinted = iconTintingEnabled;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public T withIconTinted(boolean iconTinted) {
|
||||
this.iconTinted = iconTinted;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* for backwards compatibility - withIconTinted..
|
||||
*
|
||||
* @param iconTinted
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public T withTintSelectedIcon(boolean iconTinted) {
|
||||
return withIconTintingEnabled(iconTinted);
|
||||
}
|
||||
|
||||
public T withTypeface(Typeface typeface) {
|
||||
this.typeface = typeface;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withLevel(int level) {
|
||||
this.level = level;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
public T withExcludeFromMiniDrawer(boolean excludeFromMiniDrawer) {
|
||||
this.excludeFromMiniDrawer = excludeFromMiniDrawer;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
public ColorHolder getSelectedColor() {
|
||||
return selectedColor;
|
||||
}
|
||||
|
||||
public ColorHolder getTextColor() {
|
||||
return textColor;
|
||||
}
|
||||
|
||||
public ColorHolder getSelectedTextColor() {
|
||||
return selectedTextColor;
|
||||
}
|
||||
|
||||
public ColorHolder getDisabledTextColor() {
|
||||
return disabledTextColor;
|
||||
}
|
||||
|
||||
public boolean isIconTinted() {
|
||||
return iconTinted;
|
||||
}
|
||||
|
||||
public ImageHolder getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public ImageHolder getSelectedIcon() {
|
||||
return selectedIcon;
|
||||
}
|
||||
|
||||
public StringHolder getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ColorHolder getDisabledIconColor() {
|
||||
return disabledIconColor;
|
||||
}
|
||||
|
||||
public ColorHolder getSelectedIconColor() {
|
||||
return selectedIconColor;
|
||||
}
|
||||
|
||||
public ColorHolder getIconColor() {
|
||||
return iconColor;
|
||||
}
|
||||
|
||||
public Typeface getTypeface() {
|
||||
return typeface;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getSelectedColor(Context ctx) {
|
||||
if (getBooleanStyleable(ctx, R.styleable.MaterialDrawer_material_drawer_legacy_style, false)) {
|
||||
return ColorHolder.color(getSelectedColor(), ctx, R.attr.material_drawer_selected_legacy, R.color.material_drawer_selected_legacy);
|
||||
} else {
|
||||
return ColorHolder.color(getSelectedColor(), ctx, R.attr.material_drawer_selected, R.color.material_drawer_selected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getColor(Context ctx) {
|
||||
int color;
|
||||
if (this.isEnabled()) {
|
||||
color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_primary_text, R.color.material_drawer_primary_text);
|
||||
} else {
|
||||
color = ColorHolder.color(getDisabledTextColor(), ctx, R.attr.material_drawer_hint_text, R.color.material_drawer_hint_text);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getSelectedTextColor(Context ctx) {
|
||||
return ColorHolder.color(getSelectedTextColor(), ctx, R.attr.material_drawer_selected_text, R.color.material_drawer_selected_text);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
public int getIconColor(Context ctx) {
|
||||
int iconColor;
|
||||
if (this.isEnabled()) {
|
||||
iconColor = ColorHolder.color(getIconColor(), ctx, R.attr.material_drawer_primary_icon, R.color.material_drawer_primary_icon);
|
||||
} else {
|
||||
iconColor = ColorHolder.color(getDisabledIconColor(), ctx, R.attr.material_drawer_hint_icon, R.color.material_drawer_hint_icon);
|
||||
}
|
||||
return iconColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getSelectedIconColor(Context ctx) {
|
||||
return ColorHolder.color(getSelectedIconColor(), ctx, R.attr.material_drawer_selected_text, R.color.material_drawer_selected_text);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time
|
||||
*
|
||||
* @param color
|
||||
* @param selectedTextColor
|
||||
* @return
|
||||
*/
|
||||
protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) {
|
||||
if (colorStateList == null || color + selectedTextColor != colorStateList.first) {
|
||||
colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor));
|
||||
}
|
||||
|
||||
return colorStateList.second;
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class BaseViewHolder extends RecyclerView.ViewHolder {
|
||||
protected View view;
|
||||
protected ImageView icon;
|
||||
protected TextView name;
|
||||
protected TextView description;
|
||||
|
||||
public BaseViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
this.view = view;
|
||||
this.icon = view.findViewById(R.id.material_drawer_icon);
|
||||
this.name = view.findViewById(R.id.material_drawer_name);
|
||||
this.description = view.findViewById(R.id.material_drawer_description);
|
||||
}
|
||||
}
|
@ -1,149 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.DimenHolder;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class ContainerDrawerItem extends AbstractDrawerItem<ContainerDrawerItem, ContainerDrawerItem.ViewHolder> {
|
||||
|
||||
private DimenHolder mHeight;
|
||||
|
||||
public ContainerDrawerItem withHeight(DimenHolder height) {
|
||||
mHeight = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimenHolder getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
private View mView;
|
||||
|
||||
public ContainerDrawerItem withView(View view) {
|
||||
this.mView = view;
|
||||
return this;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
public enum Position {
|
||||
TOP,
|
||||
BOTTOM,
|
||||
NONE;
|
||||
}
|
||||
|
||||
private Position mViewPosition = Position.TOP;
|
||||
|
||||
public ContainerDrawerItem withViewPosition(Position position) {
|
||||
this.mViewPosition = position;
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mDivider = true;
|
||||
|
||||
public ContainerDrawerItem withDivider(boolean divider) {
|
||||
this.mDivider = divider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Position getViewPosition() {
|
||||
return mViewPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_container;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//define how the divider should look like
|
||||
viewHolder.view.setEnabled(false);
|
||||
|
||||
//make sure our view is not used in another parent
|
||||
if (mView.getParent() != null) {
|
||||
((ViewGroup) mView.getParent()).removeView(mView);
|
||||
}
|
||||
|
||||
//set the height
|
||||
int height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
if (mHeight != null) {
|
||||
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) viewHolder.view.getLayoutParams();
|
||||
height = mHeight.asPixel(ctx);
|
||||
lp.height = height;
|
||||
viewHolder.view.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
//make sure the header view is empty
|
||||
((ViewGroup) viewHolder.view).removeAllViews();
|
||||
|
||||
int dividerHeight = 0;
|
||||
if (mDivider) {
|
||||
dividerHeight = 1;
|
||||
}
|
||||
|
||||
View divider = new View(ctx);
|
||||
divider.setMinimumHeight(dividerHeight);
|
||||
divider.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(ctx, R.attr.material_drawer_divider, R.color.material_drawer_divider));
|
||||
|
||||
LinearLayout.LayoutParams dividerParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) UIUtils.convertDpToPixel(dividerHeight, ctx));
|
||||
LinearLayout.LayoutParams viewParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mHeight != null ? height - (int) UIUtils.convertDpToPixel(dividerHeight, ctx) : height);
|
||||
|
||||
//depending on the position we add the view
|
||||
if (mViewPosition == Position.TOP) {
|
||||
((ViewGroup) viewHolder.view).addView(mView, viewParams);
|
||||
dividerParams.bottomMargin = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_padding);
|
||||
((ViewGroup) viewHolder.view).addView(divider, dividerParams);
|
||||
} else if (mViewPosition == Position.BOTTOM) {
|
||||
dividerParams.topMargin = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_padding);
|
||||
((ViewGroup) viewHolder.view).addView(divider, dividerParams);
|
||||
((ViewGroup) viewHolder.view).addView(mView, viewParams);
|
||||
} else {
|
||||
((ViewGroup) viewHolder.view).addView(mView, viewParams);
|
||||
}
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View view;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.view = view;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class DividerDrawerItem extends AbstractDrawerItem<DividerDrawerItem, DividerDrawerItem.ViewHolder> {
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_divider;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_divider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//define how the divider should look like
|
||||
viewHolder.view.setClickable(false);
|
||||
viewHolder.view.setEnabled(false);
|
||||
viewHolder.view.setMinimumHeight(1);
|
||||
ViewCompat.setImportantForAccessibility(viewHolder.view,
|
||||
ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
|
||||
|
||||
//set the color for the divider
|
||||
viewHolder.divider.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(ctx, R.attr.material_drawer_divider, R.color.material_drawer_divider));
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View view;
|
||||
private View divider;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.view = view;
|
||||
this.divider = view.findViewById(R.id.material_drawer_divider);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.iconics.IconicsDrawable;
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.BadgeStyle;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.icons.MaterialDrawerFont;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.ColorfulBadgeable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
* NOTE: The arrow will just animate (and rotate) on APIs higher than 11 as the ViewCompat will skip this on API 10
|
||||
*/
|
||||
public class ExpandableBadgeDrawerItem extends BaseDescribeableDrawerItem<ExpandableBadgeDrawerItem, ExpandableBadgeDrawerItem.ViewHolder>
|
||||
implements ColorfulBadgeable<ExpandableBadgeDrawerItem> {
|
||||
|
||||
private Drawer.OnDrawerItemClickListener mOnDrawerItemClickListener;
|
||||
|
||||
protected ColorHolder arrowColor;
|
||||
|
||||
protected int arrowRotationAngleStart = 0;
|
||||
|
||||
protected int arrowRotationAngleEnd = 180;
|
||||
|
||||
protected StringHolder mBadge;
|
||||
protected BadgeStyle mBadgeStyle = new BadgeStyle();
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_expandable_badge;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_expandable_badge;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ExpandableBadgeDrawerItem.ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
//bind the basic view parts
|
||||
bindViewHelper(viewHolder);
|
||||
|
||||
//set the text for the badge or hide
|
||||
boolean badgeVisible = StringHolder.applyToOrHide(mBadge, viewHolder.badge);
|
||||
//style the badge if it is visible
|
||||
if (true) {
|
||||
mBadgeStyle.style(viewHolder.badge, getTextColorStateList(getColor(ctx), getSelectedTextColor(ctx)));
|
||||
viewHolder.badgeContainer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
viewHolder.badgeContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//define the typeface for our textViews
|
||||
if (getTypeface() != null) {
|
||||
viewHolder.badge.setTypeface(getTypeface());
|
||||
}
|
||||
|
||||
//make sure all animations are stopped
|
||||
if (viewHolder.arrow.getDrawable() instanceof IconicsDrawable) {
|
||||
((IconicsDrawable) viewHolder.arrow.getDrawable()).color(this.arrowColor != null ? this.arrowColor.color(ctx) : getIconColor(ctx));
|
||||
}
|
||||
viewHolder.arrow.clearAnimation();
|
||||
if (!isExpanded()) {
|
||||
viewHolder.arrow.setRotation(this.arrowRotationAngleStart);
|
||||
} else {
|
||||
viewHolder.arrow.setRotation(this.arrowRotationAngleEnd);
|
||||
}
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableBadgeDrawerItem withOnDrawerItemClickListener(Drawer.OnDrawerItemClickListener onDrawerItemClickListener) {
|
||||
mOnDrawerItemClickListener = onDrawerItemClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawer.OnDrawerItemClickListener getOnDrawerItemClickListener() {
|
||||
return mOnArrowDrawerItemClickListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* our internal onDrawerItemClickListener which will handle the arrow animation
|
||||
*/
|
||||
private Drawer.OnDrawerItemClickListener mOnArrowDrawerItemClickListener = new Drawer.OnDrawerItemClickListener() {
|
||||
@Override
|
||||
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
|
||||
if (drawerItem instanceof AbstractDrawerItem && drawerItem.isEnabled()) {
|
||||
if (((AbstractDrawerItem) drawerItem).getSubItems() != null) {
|
||||
if (((AbstractDrawerItem) drawerItem).isExpanded()) {
|
||||
ViewCompat.animate(view.findViewById(R.id.material_drawer_arrow)).rotation(ExpandableBadgeDrawerItem.this.arrowRotationAngleEnd).start();
|
||||
} else {
|
||||
ViewCompat.animate(view.findViewById(R.id.material_drawer_arrow))
|
||||
.rotation(ExpandableBadgeDrawerItem.this.arrowRotationAngleStart)
|
||||
.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mOnDrawerItemClickListener != null && mOnDrawerItemClickListener.onItemClick(view, position, drawerItem);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ExpandableBadgeDrawerItem withBadge(StringHolder badge) {
|
||||
this.mBadge = badge;
|
||||
return (ExpandableBadgeDrawerItem) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableBadgeDrawerItem withBadge(String badge) {
|
||||
this.mBadge = new StringHolder(badge);
|
||||
return (ExpandableBadgeDrawerItem) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableBadgeDrawerItem withBadge(@StringRes int badgeRes) {
|
||||
this.mBadge = new StringHolder(badgeRes);
|
||||
return (ExpandableBadgeDrawerItem) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableBadgeDrawerItem withBadgeStyle(BadgeStyle badgeStyle) {
|
||||
this.mBadgeStyle = badgeStyle;
|
||||
return (ExpandableBadgeDrawerItem) this;
|
||||
}
|
||||
|
||||
public StringHolder getBadge() {
|
||||
return mBadge;
|
||||
}
|
||||
|
||||
public BadgeStyle getBadgeStyle() {
|
||||
return mBadgeStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends BaseViewHolder {
|
||||
public ImageView arrow;
|
||||
public View badgeContainer;
|
||||
public TextView badge;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
badgeContainer = view.findViewById(R.id.material_drawer_badge_container);
|
||||
badge = view.findViewById(R.id.material_drawer_badge);
|
||||
arrow = view.findViewById(R.id.material_drawer_arrow);
|
||||
arrow.setImageDrawable(new IconicsDrawable(view.getContext(), MaterialDrawerFont.Icon.mdf_expand_more).sizeDp(16).paddingDp(2).color(Color.BLACK));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mikepenz.iconics.IconicsDrawable;
|
||||
import com.mikepenz.materialdrawer.Drawer;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.icons.MaterialDrawerFont;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
* NOTE: The arrow will just animate (and rotate) on APIs higher than 11 as the ViewCompat will skip this on API 10
|
||||
*/
|
||||
public class ExpandableDrawerItem extends BaseDescribeableDrawerItem<ExpandableDrawerItem, ExpandableDrawerItem.ViewHolder> {
|
||||
|
||||
private Drawer.OnDrawerItemClickListener mOnDrawerItemClickListener;
|
||||
|
||||
protected ColorHolder arrowColor;
|
||||
|
||||
protected int arrowRotationAngleStart = 0;
|
||||
|
||||
protected int arrowRotationAngleEnd = 180;
|
||||
|
||||
public ExpandableDrawerItem withArrowColor(@ColorInt int arrowColor) {
|
||||
this.arrowColor = ColorHolder.fromColor(arrowColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpandableDrawerItem withArrowColorRes(@ColorRes int arrowColorRes) {
|
||||
this.arrowColor = ColorHolder.fromColorRes(arrowColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpandableDrawerItem withArrowRotationAngleStart(int angle) {
|
||||
this.arrowRotationAngleStart = angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExpandableDrawerItem withArrowRotationAngleEnd(int angle) {
|
||||
this.arrowRotationAngleEnd = angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_expandable;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_expandable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpandableDrawerItem withOnDrawerItemClickListener(Drawer.OnDrawerItemClickListener onDrawerItemClickListener) {
|
||||
mOnDrawerItemClickListener = onDrawerItemClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawer.OnDrawerItemClickListener getOnDrawerItemClickListener() {
|
||||
return mOnArrowDrawerItemClickListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* our internal onDrawerItemClickListener which will handle the arrow animation
|
||||
*/
|
||||
private Drawer.OnDrawerItemClickListener mOnArrowDrawerItemClickListener = new Drawer.OnDrawerItemClickListener() {
|
||||
@Override
|
||||
public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
|
||||
if (drawerItem instanceof AbstractDrawerItem && drawerItem.isEnabled()) {
|
||||
if (((AbstractDrawerItem) drawerItem).getSubItems() != null) {
|
||||
if (((AbstractDrawerItem) drawerItem).isExpanded()) {
|
||||
ViewCompat.animate(view.findViewById(R.id.material_drawer_arrow)).rotation(ExpandableDrawerItem.this.arrowRotationAngleEnd).start();
|
||||
} else {
|
||||
ViewCompat.animate(view.findViewById(R.id.material_drawer_arrow)).rotation(ExpandableDrawerItem.this.arrowRotationAngleStart).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mOnDrawerItemClickListener != null && mOnDrawerItemClickListener.onItemClick(view, position, drawerItem);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
//bind the basic view parts
|
||||
bindViewHelper(viewHolder);
|
||||
|
||||
//make sure all animations are stopped
|
||||
if (viewHolder.arrow.getDrawable() instanceof IconicsDrawable) {
|
||||
((IconicsDrawable) viewHolder.arrow.getDrawable()).color(this.arrowColor != null ? this.arrowColor.color(ctx) : getIconColor(ctx));
|
||||
}
|
||||
viewHolder.arrow.clearAnimation();
|
||||
if (!isExpanded()) {
|
||||
viewHolder.arrow.setRotation(this.arrowRotationAngleStart);
|
||||
} else {
|
||||
viewHolder.arrow.setRotation(this.arrowRotationAngleEnd);
|
||||
}
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends BaseViewHolder {
|
||||
public ImageView arrow;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
arrow = view.findViewById(R.id.material_drawer_arrow);
|
||||
arrow.setImageDrawable(new IconicsDrawable(view.getContext(), MaterialDrawerFont.Icon.mdf_expand_more).sizeDp(16).paddingDp(2).color(Color.BLACK));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.BadgeStyle;
|
||||
import com.mikepenz.materialdrawer.holder.DimenHolder;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import static com.mikepenz.materialdrawer.util.DrawerUIUtils.themeDrawerItem;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class MiniDrawerItem extends BaseDrawerItem<MiniDrawerItem, MiniDrawerItem.ViewHolder> {
|
||||
private StringHolder mBadge;
|
||||
private BadgeStyle mBadgeStyle = new BadgeStyle();
|
||||
|
||||
private boolean mEnableSelectedBackground = false;
|
||||
protected DimenHolder mCustomHeight;
|
||||
|
||||
public MiniDrawerItem() {
|
||||
|
||||
}
|
||||
|
||||
public MiniDrawerItem(PrimaryDrawerItem primaryDrawerItem) {
|
||||
this.mIdentifier = primaryDrawerItem.mIdentifier;
|
||||
this.mTag = primaryDrawerItem.mTag;
|
||||
|
||||
this.mBadge = primaryDrawerItem.mBadge;
|
||||
this.mBadgeStyle = primaryDrawerItem.mBadgeStyle;
|
||||
|
||||
this.mEnabled = primaryDrawerItem.mEnabled;
|
||||
this.mSelectable = primaryDrawerItem.mSelectable;
|
||||
this.mSelected = primaryDrawerItem.mSelected;
|
||||
|
||||
this.icon = primaryDrawerItem.icon;
|
||||
this.selectedIcon = primaryDrawerItem.selectedIcon;
|
||||
|
||||
this.iconTinted = primaryDrawerItem.iconTinted;
|
||||
this.selectedColor = primaryDrawerItem.selectedColor;
|
||||
|
||||
this.iconColor = primaryDrawerItem.iconColor;
|
||||
this.selectedIconColor = primaryDrawerItem.selectedIconColor;
|
||||
this.disabledIconColor = primaryDrawerItem.disabledIconColor;
|
||||
}
|
||||
|
||||
public MiniDrawerItem(SecondaryDrawerItem secondaryDrawerItem) {
|
||||
this.mIdentifier = secondaryDrawerItem.mIdentifier;
|
||||
this.mTag = secondaryDrawerItem.mTag;
|
||||
|
||||
this.mBadge = secondaryDrawerItem.mBadge;
|
||||
this.mBadgeStyle = secondaryDrawerItem.mBadgeStyle;
|
||||
|
||||
this.mEnabled = secondaryDrawerItem.mEnabled;
|
||||
this.mSelectable = secondaryDrawerItem.mSelectable;
|
||||
this.mSelected = secondaryDrawerItem.mSelected;
|
||||
|
||||
this.icon = secondaryDrawerItem.icon;
|
||||
this.selectedIcon = secondaryDrawerItem.selectedIcon;
|
||||
|
||||
this.iconTinted = secondaryDrawerItem.iconTinted;
|
||||
this.selectedColor = secondaryDrawerItem.selectedColor;
|
||||
|
||||
this.iconColor = secondaryDrawerItem.iconColor;
|
||||
this.selectedIconColor = secondaryDrawerItem.selectedIconColor;
|
||||
this.disabledIconColor = secondaryDrawerItem.disabledIconColor;
|
||||
}
|
||||
|
||||
|
||||
public MiniDrawerItem withCustomHeightRes(@DimenRes int customHeightRes) {
|
||||
this.mCustomHeight = DimenHolder.fromResource(customHeightRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniDrawerItem withCustomHeightDp(int customHeightDp) {
|
||||
this.mCustomHeight = DimenHolder.fromDp(customHeightDp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniDrawerItem withCustomHeightPx(int customHeightPx) {
|
||||
this.mCustomHeight = DimenHolder.fromPixel(customHeightPx);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniDrawerItem withCustomHeight(DimenHolder customHeight) {
|
||||
this.mCustomHeight = customHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniDrawerItem withEnableSelectedBackground(boolean enableSelectedBackground) {
|
||||
this.mEnableSelectedBackground = enableSelectedBackground;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_mini;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_mini;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set a different height for this item
|
||||
if (mCustomHeight != null) {
|
||||
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) viewHolder.itemView.getLayoutParams();
|
||||
lp.height = mCustomHeight.asPixel(ctx);
|
||||
viewHolder.itemView.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//set the item enabled if it is
|
||||
viewHolder.itemView.setEnabled(isEnabled());
|
||||
|
||||
//set the item selected if it is
|
||||
viewHolder.itemView.setSelected(isSelected());
|
||||
|
||||
//
|
||||
viewHolder.itemView.setTag(this);
|
||||
|
||||
//get the correct color for the icon
|
||||
int iconColor = getIconColor(ctx);
|
||||
int selectedIconColor = getSelectedIconColor(ctx);
|
||||
|
||||
if (mEnableSelectedBackground) {
|
||||
//get the correct color for the background
|
||||
int selectedColor = getSelectedColor(ctx);
|
||||
//set the background for the item
|
||||
themeDrawerItem(ctx, viewHolder.view, selectedColor, isSelectedBackgroundAnimated());
|
||||
}
|
||||
|
||||
//set the text for the badge or hide
|
||||
boolean badgeVisible = StringHolder.applyToOrHide(mBadge, viewHolder.badge);
|
||||
//style the badge if it is visible
|
||||
if (badgeVisible) {
|
||||
mBadgeStyle.style(viewHolder.badge);
|
||||
}
|
||||
|
||||
//get the drawables for our icon and set it
|
||||
Drawable icon = ImageHolder.decideIcon(getIcon(), ctx, iconColor, isIconTinted(), 1);
|
||||
Drawable selectedIcon = ImageHolder.decideIcon(getSelectedIcon(), ctx, selectedIconColor, isIconTinted(), 1);
|
||||
ImageHolder.applyMultiIconTo(icon, iconColor, selectedIcon, selectedIconColor, isIconTinted(), viewHolder.icon);
|
||||
|
||||
//for android API 17 --> Padding not applied via xml
|
||||
int verticalPadding = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_padding);
|
||||
int topBottomPadding = ctx.getResources().getDimensionPixelSize(R.dimen.material_mini_drawer_item_padding);
|
||||
viewHolder.itemView.setPadding(verticalPadding, topBottomPadding, verticalPadding, topBottomPadding);
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View view;
|
||||
private ImageView icon;
|
||||
private TextView badge;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
|
||||
this.view = view;
|
||||
this.icon = (ImageView) view.findViewById(R.id.material_drawer_icon);
|
||||
this.badge = (TextView) view.findViewById(R.id.material_drawer_badge);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.DimenRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.DimenHolder;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class MiniProfileDrawerItem extends AbstractDrawerItem<MiniProfileDrawerItem, MiniProfileDrawerItem.ViewHolder> implements IProfile<MiniProfileDrawerItem> {
|
||||
protected ImageHolder icon;
|
||||
|
||||
protected DimenHolder customHeight;
|
||||
|
||||
public MiniProfileDrawerItem() {
|
||||
withSelectable(false);
|
||||
}
|
||||
|
||||
public MiniProfileDrawerItem(ProfileDrawerItem profile) {
|
||||
this.icon = profile.icon;
|
||||
this.mEnabled = profile.mEnabled;
|
||||
withSelectable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withName(CharSequence name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringHolder getName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withEmail(String email) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringHolder getEmail() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withIcon(Drawable icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withIcon(@DrawableRes int iconRes) {
|
||||
this.icon = new ImageHolder(iconRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withIcon(Bitmap iconBitmap) {
|
||||
this.icon = new ImageHolder(iconBitmap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withIcon(String url) {
|
||||
this.icon = new ImageHolder(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withIcon(Uri uri) {
|
||||
this.icon = new ImageHolder(uri);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MiniProfileDrawerItem withIcon(IIcon icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniProfileDrawerItem withCustomHeightRes(@DimenRes int customHeightRes) {
|
||||
this.customHeight = DimenHolder.fromResource(customHeightRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniProfileDrawerItem withCustomHeightDp(int customHeightDp) {
|
||||
this.customHeight = DimenHolder.fromDp(customHeightDp);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniProfileDrawerItem withCustomHeightPx(int customHeightPx) {
|
||||
this.customHeight = DimenHolder.fromPixel(customHeightPx);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiniProfileDrawerItem withCustomHeight(DimenHolder customHeight) {
|
||||
this.customHeight = customHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageHolder getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_mini_profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_mini_profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
if (customHeight != null) {
|
||||
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) viewHolder.itemView.getLayoutParams();
|
||||
lp.height = customHeight.asPixel(viewHolder.itemView.getContext());
|
||||
viewHolder.itemView.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//set the item enabled if it is
|
||||
viewHolder.itemView.setEnabled(isEnabled());
|
||||
|
||||
//set the icon
|
||||
ImageHolder.applyToOrSetInvisible(getIcon(), viewHolder.icon);
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private ImageView icon;
|
||||
|
||||
public ViewHolder(View view) {
|
||||
super(view);
|
||||
this.icon = (ImageView) view.findViewById(R.id.material_drawer_icon);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class PrimaryDrawerItem extends AbstractBadgeableDrawerItem<PrimaryDrawerItem> {
|
||||
|
||||
}
|
@ -1,365 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Pair;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Tagable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Typefaceable;
|
||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
|
||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import static com.mikepenz.materialdrawer.util.DrawerUIUtils.getBooleanStyleable;
|
||||
import static com.mikepenz.materialdrawer.util.DrawerUIUtils.themeDrawerItem;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class ProfileDrawerItem extends AbstractDrawerItem<ProfileDrawerItem, ProfileDrawerItem.ViewHolder> implements IProfile<ProfileDrawerItem>, Tagable<ProfileDrawerItem>, Typefaceable<ProfileDrawerItem> {
|
||||
protected boolean nameShown = false;
|
||||
|
||||
protected ImageHolder icon;
|
||||
|
||||
protected StringHolder name;
|
||||
protected StringHolder email;
|
||||
|
||||
protected ColorHolder selectedColor;
|
||||
protected ColorHolder textColor;
|
||||
protected ColorHolder selectedTextColor;
|
||||
protected ColorHolder disabledTextColor;
|
||||
|
||||
protected Typeface typeface = null;
|
||||
|
||||
@Override
|
||||
public ProfileDrawerItem withIcon(Drawable icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileDrawerItem withIcon(@DrawableRes int iconRes) {
|
||||
this.icon = new ImageHolder(iconRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileDrawerItem withIcon(Bitmap iconBitmap) {
|
||||
this.icon = new ImageHolder(iconBitmap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileDrawerItem withIcon(IIcon icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileDrawerItem withIcon(String url) {
|
||||
this.icon = new ImageHolder(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileDrawerItem withIcon(Uri uri) {
|
||||
this.icon = new ImageHolder(uri);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withName(CharSequence name) {
|
||||
this.name = new StringHolder(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withName(@StringRes int nameRes) {
|
||||
this.name = new StringHolder(nameRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withEmail(String email) {
|
||||
this.email = new StringHolder(email);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withEmail(@StringRes int emailRes) {
|
||||
this.email = new StringHolder(emailRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the profile name in the account switcher.
|
||||
*
|
||||
* @param nameShown show name in switcher
|
||||
* @return the {@link ProfileDrawerItem}
|
||||
*/
|
||||
public ProfileDrawerItem withNameShown(boolean nameShown) {
|
||||
this.nameShown = nameShown;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withSelectedColor(@ColorInt int selectedColor) {
|
||||
this.selectedColor = ColorHolder.fromColor(selectedColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withSelectedColorRes(@ColorRes int selectedColorRes) {
|
||||
this.selectedColor = ColorHolder.fromColorRes(selectedColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withTextColor(@ColorInt int textColor) {
|
||||
this.textColor = ColorHolder.fromColor(textColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withTextColorRes(@ColorRes int textColorRes) {
|
||||
this.textColor = ColorHolder.fromColorRes(textColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withSelectedTextColor(@ColorInt int selectedTextColor) {
|
||||
this.selectedTextColor = ColorHolder.fromColor(selectedTextColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withSelectedTextColorRes(@ColorRes int selectedColorRes) {
|
||||
this.selectedTextColor = ColorHolder.fromColorRes(selectedColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withDisabledTextColor(@ColorInt int disabledTextColor) {
|
||||
this.disabledTextColor = ColorHolder.fromColor(disabledTextColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withDisabledTextColorRes(@ColorRes int disabledTextColorRes) {
|
||||
this.disabledTextColor = ColorHolder.fromColorRes(disabledTextColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileDrawerItem withTypeface(Typeface typeface) {
|
||||
this.typeface = typeface;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isNameShown() {
|
||||
return nameShown;
|
||||
}
|
||||
|
||||
public ColorHolder getSelectedColor() {
|
||||
return selectedColor;
|
||||
}
|
||||
|
||||
public ColorHolder getTextColor() {
|
||||
return textColor;
|
||||
}
|
||||
|
||||
public ColorHolder getSelectedTextColor() {
|
||||
return selectedTextColor;
|
||||
}
|
||||
|
||||
public ColorHolder getDisabledTextColor() {
|
||||
return disabledTextColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Typeface getTypeface() {
|
||||
return typeface;
|
||||
}
|
||||
|
||||
public ImageHolder getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringHolder getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public StringHolder getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_profile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//set the item enabled if it is
|
||||
viewHolder.itemView.setEnabled(isEnabled());
|
||||
|
||||
//set the item selected if it is
|
||||
viewHolder.itemView.setSelected(isSelected());
|
||||
|
||||
//get the correct color for the background
|
||||
int selectedColor = getSelectedColor(ctx);
|
||||
//get the correct color for the text
|
||||
int color = getColor(ctx);
|
||||
int secondaryColor = getSecondaryColor(ctx);
|
||||
int selectedTextColor = getSelectedTextColor(ctx);
|
||||
|
||||
//set the background for the item
|
||||
themeDrawerItem(ctx, viewHolder.view, selectedColor, isSelectedBackgroundAnimated());
|
||||
|
||||
if (nameShown) {
|
||||
viewHolder.name.setVisibility(View.VISIBLE);
|
||||
StringHolder.applyTo(this.getName(), viewHolder.name);
|
||||
} else {
|
||||
viewHolder.name.setVisibility(View.GONE);
|
||||
}
|
||||
//the MaterialDrawer follows the Google Apps. those only show the e-mail
|
||||
//within the profile switcher. The problem this causes some confusion for
|
||||
//some developers. And if you only set the name, the item would be empty
|
||||
//so here's a small fallback which will prevent this issue of empty items ;)
|
||||
if (!nameShown && this.getEmail() == null && this.getName() != null) {
|
||||
StringHolder.applyTo(this.getName(), viewHolder.email);
|
||||
} else {
|
||||
StringHolder.applyTo(this.getEmail(), viewHolder.email);
|
||||
}
|
||||
|
||||
if (getTypeface() != null) {
|
||||
viewHolder.name.setTypeface(getTypeface());
|
||||
viewHolder.email.setTypeface(getTypeface());
|
||||
}
|
||||
|
||||
if (nameShown) {
|
||||
viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor));
|
||||
}
|
||||
viewHolder.email.setTextColor(getTextColorStateList(secondaryColor, selectedTextColor));
|
||||
|
||||
//cancel previous started image loading processes
|
||||
DrawerImageLoader.getInstance().cancelImage(viewHolder.profileIcon);
|
||||
//set the icon
|
||||
ImageHolder.applyToOrSetInvisible(getIcon(), viewHolder.profileIcon, DrawerImageLoader.Tags.PROFILE_DRAWER_ITEM.name());
|
||||
|
||||
//for android API 17 --> Padding not applied via xml
|
||||
DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view);
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View view;
|
||||
private ImageView profileIcon;
|
||||
private TextView name;
|
||||
private TextView email;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.view = view;
|
||||
this.profileIcon = view.findViewById(R.id.material_drawer_profileIcon);
|
||||
this.name = view.findViewById(R.id.material_drawer_name);
|
||||
this.email = view.findViewById(R.id.material_drawer_email);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getSelectedColor(Context ctx) {
|
||||
if (getBooleanStyleable(ctx, R.styleable.MaterialDrawer_material_drawer_legacy_style, false)) {
|
||||
return ColorHolder.color(getSelectedColor(), ctx, R.attr.material_drawer_selected_legacy, R.color.material_drawer_selected_legacy);
|
||||
} else {
|
||||
return ColorHolder.color(getSelectedColor(), ctx, R.attr.material_drawer_selected, R.color.material_drawer_selected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getColor(Context ctx) {
|
||||
int color;
|
||||
if (this.isEnabled()) {
|
||||
color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_primary_text, R.color.material_drawer_primary_text);
|
||||
} else {
|
||||
color = ColorHolder.color(getDisabledTextColor(), ctx, R.attr.material_drawer_hint_text, R.color.material_drawer_hint_text);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
protected int getSecondaryColor(Context ctx) {
|
||||
int color;
|
||||
if (this.isEnabled()) {
|
||||
color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_secondary_text, R.color.material_drawer_secondary_text);
|
||||
} else {
|
||||
color = ColorHolder.color(getDisabledTextColor(), ctx, R.attr.material_drawer_hint_text, R.color.material_drawer_hint_text);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getSelectedTextColor(Context ctx) {
|
||||
return ColorHolder.color(getSelectedTextColor(), ctx, R.attr.material_drawer_selected_text, R.color.material_drawer_selected_text);
|
||||
}
|
||||
|
||||
protected Pair<Integer, ColorStateList> colorStateList;
|
||||
|
||||
/**
|
||||
* helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time
|
||||
*
|
||||
* @param color
|
||||
* @param selectedTextColor
|
||||
* @return
|
||||
*/
|
||||
protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) {
|
||||
if (colorStateList == null || color + selectedTextColor != colorStateList.first) {
|
||||
colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor));
|
||||
}
|
||||
|
||||
return colorStateList.second;
|
||||
}
|
||||
}
|
@ -1,318 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Tagable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Typefaceable;
|
||||
import com.mikepenz.materialdrawer.util.DrawerUIUtils;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import static com.mikepenz.materialdrawer.util.DrawerUIUtils.getBooleanStyleable;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class ProfileSettingDrawerItem extends AbstractDrawerItem<ProfileSettingDrawerItem, ProfileSettingDrawerItem.ViewHolder> implements IProfile<ProfileSettingDrawerItem>, Tagable<ProfileSettingDrawerItem>, Typefaceable<ProfileSettingDrawerItem> {
|
||||
private ImageHolder icon;
|
||||
|
||||
private StringHolder name;
|
||||
private StringHolder description;
|
||||
|
||||
private boolean iconTinted = false;
|
||||
|
||||
private ColorHolder selectedColor;
|
||||
private ColorHolder textColor;
|
||||
private ColorHolder iconColor;
|
||||
private ColorHolder descriptionTextColor;
|
||||
|
||||
private Typeface typeface = null;
|
||||
|
||||
private boolean selectable = false;
|
||||
|
||||
@Override
|
||||
public ProfileSettingDrawerItem withIcon(Drawable icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileSettingDrawerItem withIcon(@DrawableRes int iconRes) {
|
||||
this.icon = new ImageHolder(iconRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileSettingDrawerItem withIcon(Bitmap icon) {
|
||||
this.icon = new ImageHolder(icon);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileSettingDrawerItem withIcon(IIcon iicon) {
|
||||
this.icon = new ImageHolder(iicon);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileSettingDrawerItem withIcon(String url) {
|
||||
this.icon = new ImageHolder(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileSettingDrawerItem withIcon(Uri uri) {
|
||||
this.icon = new ImageHolder(uri);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withName(CharSequence name) {
|
||||
this.name = new StringHolder(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withName(@StringRes int nameRes) {
|
||||
this.name = new StringHolder(nameRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withDescription(String description) {
|
||||
this.description = new StringHolder(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withDescription(@StringRes int descriptionRes) {
|
||||
this.description = new StringHolder(descriptionRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
//NOTE we reuse the IProfile here to allow custom items within the AccountSwitcher. There is an alias method withDescription for this
|
||||
public ProfileSettingDrawerItem withEmail(String email) {
|
||||
this.description = new StringHolder(email);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withSelectedColor(@ColorInt int selectedColor) {
|
||||
this.selectedColor = ColorHolder.fromColor(selectedColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withSelectedColorRes(@ColorRes int selectedColorRes) {
|
||||
this.selectedColor = ColorHolder.fromColorRes(selectedColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withTextColor(@ColorInt int textColor) {
|
||||
this.textColor = ColorHolder.fromColor(textColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withTextColorRes(@ColorRes int textColorRes) {
|
||||
this.textColor = ColorHolder.fromColorRes(textColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withDescriptionTextColor(@ColorInt int descriptionColor) {
|
||||
this.descriptionTextColor = ColorHolder.fromColor(descriptionColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withDescriptionTextColorRes(@ColorRes int descriptionColorRes) {
|
||||
this.descriptionTextColor = ColorHolder.fromColorRes(descriptionColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withIconColor(@ColorInt int iconColor) {
|
||||
this.iconColor = ColorHolder.fromColor(iconColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withIconColorRes(@ColorRes int iconColorRes) {
|
||||
this.iconColor = ColorHolder.fromColorRes(iconColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withTypeface(Typeface typeface) {
|
||||
this.typeface = typeface;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withIconTinted(boolean iconTinted) {
|
||||
this.iconTinted = iconTinted;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorHolder getSelectedColor() {
|
||||
return selectedColor;
|
||||
}
|
||||
|
||||
public ColorHolder getTextColor() {
|
||||
return textColor;
|
||||
}
|
||||
|
||||
public ColorHolder getDescriptionTextColor() {
|
||||
return descriptionTextColor;
|
||||
}
|
||||
|
||||
public ColorHolder getIconColor() {
|
||||
return iconColor;
|
||||
}
|
||||
|
||||
|
||||
public ImageHolder getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public boolean isIconTinted() {
|
||||
return iconTinted;
|
||||
}
|
||||
|
||||
public void setIconTinted(boolean iconTinted) {
|
||||
this.iconTinted = iconTinted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Typeface getTypeface() {
|
||||
return typeface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringHolder getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public StringHolder getEmail() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public StringHolder getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = new StringHolder(description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelectable() {
|
||||
return selectable;
|
||||
}
|
||||
|
||||
public ProfileSettingDrawerItem withSelectable(boolean selectable) {
|
||||
this.selectable = selectable;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_profile_setting;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_profile_setting;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
//get the context
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//set the item enabled if it is
|
||||
viewHolder.itemView.setEnabled(isEnabled());
|
||||
|
||||
//set the item selected if it is
|
||||
viewHolder.itemView.setSelected(isSelected());
|
||||
|
||||
//get the correct color for the background
|
||||
int selectedColor = getSelectedColor(ctx);
|
||||
//get the correct color for the text
|
||||
int color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_primary_text, R.color.material_drawer_primary_text);
|
||||
int iconColor = ColorHolder.color(getIconColor(), ctx, R.attr.material_drawer_primary_icon, R.color.material_drawer_primary_icon);
|
||||
int descriptionColor = ColorHolder.color(getDescriptionTextColor(), ctx, R.attr.material_drawer_primary_text, R.color.material_drawer_primary_text);
|
||||
|
||||
ViewCompat.setBackground(viewHolder.view, UIUtils.getSelectableBackground(ctx, selectedColor, isSelectedBackgroundAnimated()));
|
||||
|
||||
StringHolder.applyTo(this.getName(), viewHolder.name);
|
||||
viewHolder.name.setTextColor(color);
|
||||
|
||||
StringHolder.applyToOrHide(this.getDescription(), viewHolder.description);
|
||||
viewHolder.description.setTextColor(descriptionColor);
|
||||
|
||||
if (getTypeface() != null) {
|
||||
viewHolder.name.setTypeface(getTypeface());
|
||||
viewHolder.description.setTypeface(getTypeface());
|
||||
}
|
||||
|
||||
//set the correct icon
|
||||
ImageHolder.applyDecidedIconOrSetGone(icon, viewHolder.icon, iconColor, isIconTinted(), 2);
|
||||
|
||||
//for android API 17 --> Padding not applied via xml
|
||||
DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view);
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
protected int getSelectedColor(Context ctx) {
|
||||
if (getBooleanStyleable(ctx, R.styleable.MaterialDrawer_material_drawer_legacy_style, false)) {
|
||||
return ColorHolder.color(getSelectedColor(), ctx, R.attr.material_drawer_selected_legacy, R.color.material_drawer_selected_legacy);
|
||||
} else {
|
||||
return ColorHolder.color(getSelectedColor(), ctx, R.attr.material_drawer_selected, R.color.material_drawer_selected);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View view;
|
||||
private ImageView icon;
|
||||
private TextView name;
|
||||
private TextView description;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.view = view;
|
||||
this.icon = (ImageView) view.findViewById(R.id.material_drawer_icon);
|
||||
this.name = (TextView) view.findViewById(R.id.material_drawer_name);
|
||||
this.description = (TextView) view.findViewById(R.id.material_drawer_description);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.LayoutRes;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class SecondaryDrawerItem extends AbstractBadgeableDrawerItem<SecondaryDrawerItem> {
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_secondary;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_secondary;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
* OVERWRITE to get the correct secondary color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getColor(Context ctx) {
|
||||
int color;
|
||||
if (this.isEnabled()) {
|
||||
color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_secondary_text, R.color.material_drawer_secondary_text);
|
||||
} else {
|
||||
color = ColorHolder.color(getDisabledTextColor(), ctx, R.attr.material_drawer_hint_text, R.color.material_drawer_hint_text);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.LayoutRes;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class SecondarySwitchDrawerItem extends AbstractSwitchableDrawerItem<SecondarySwitchDrawerItem> {
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_secondary_switch;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_secondary_switch;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
* OVERWRITE to get the correct secondary color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getColor(Context ctx) {
|
||||
int color;
|
||||
if (this.isEnabled()) {
|
||||
color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_secondary_text, R.color.material_drawer_secondary_text);
|
||||
} else {
|
||||
color = ColorHolder.color(getDisabledTextColor(), ctx, R.attr.material_drawer_hint_text, R.color.material_drawer_hint_text);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.LayoutRes;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class SecondaryToggleDrawerItem extends AbstractToggleableDrawerItem<SecondaryToggleDrawerItem> {
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_secondary_toggle;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_secondary_toggle;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper method to decide for the correct color
|
||||
* OVERWRITE to get the correct secondary color
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
protected int getColor(Context ctx) {
|
||||
int color;
|
||||
if (this.isEnabled()) {
|
||||
color = ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_secondary_text, R.color.material_drawer_secondary_text);
|
||||
} else {
|
||||
color = ColorHolder.color(getDisabledTextColor(), ctx, R.attr.material_drawer_hint_text, R.color.material_drawer_hint_text);
|
||||
}
|
||||
return color;
|
||||
}
|
||||
}
|
@ -1,160 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Nameable;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.Typefaceable;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class SectionDrawerItem extends AbstractDrawerItem<SectionDrawerItem, SectionDrawerItem.ViewHolder> implements Nameable<SectionDrawerItem>, Typefaceable<SectionDrawerItem> {
|
||||
|
||||
private StringHolder name;
|
||||
private boolean divider = true;
|
||||
|
||||
private ColorHolder textColor;
|
||||
|
||||
private Typeface typeface = null;
|
||||
|
||||
public SectionDrawerItem withName(StringHolder name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SectionDrawerItem withName(String name) {
|
||||
this.name = new StringHolder(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SectionDrawerItem withName(@StringRes int nameRes) {
|
||||
this.name = new StringHolder(nameRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SectionDrawerItem withDivider(boolean divider) {
|
||||
this.divider = divider;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SectionDrawerItem withTextColor(int textColor) {
|
||||
this.textColor = ColorHolder.fromColor(textColor);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SectionDrawerItem withTextColorRes(int textColorRes) {
|
||||
this.textColor = ColorHolder.fromColorRes(textColorRes);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SectionDrawerItem withTypeface(Typeface typeface) {
|
||||
this.typeface = typeface;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasDivider() {
|
||||
return divider;
|
||||
}
|
||||
|
||||
public ColorHolder getTextColor() {
|
||||
return textColor;
|
||||
}
|
||||
|
||||
public StringHolder getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return R.id.material_drawer_item_section;
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
public int getLayoutRes() {
|
||||
return R.layout.material_drawer_item_section;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Typeface getTypeface() {
|
||||
return typeface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(ViewHolder viewHolder, List payloads) {
|
||||
super.bindView(viewHolder, payloads);
|
||||
|
||||
Context ctx = viewHolder.itemView.getContext();
|
||||
|
||||
//set the identifier from the drawerItem here. It can be used to run tests
|
||||
viewHolder.itemView.setId(hashCode());
|
||||
|
||||
//define this item to be not clickable nor enabled
|
||||
viewHolder.view.setClickable(false);
|
||||
viewHolder.view.setEnabled(false);
|
||||
|
||||
//define the text color
|
||||
viewHolder.name.setTextColor(ColorHolder.color(getTextColor(), ctx, R.attr.material_drawer_secondary_text, R.color.material_drawer_secondary_text));
|
||||
|
||||
//set the text for the name
|
||||
StringHolder.applyTo(this.getName(), viewHolder.name);
|
||||
|
||||
//define the typeface for our textViews
|
||||
if (getTypeface() != null) {
|
||||
viewHolder.name.setTypeface(getTypeface());
|
||||
}
|
||||
|
||||
//hide the divider if we do not need one
|
||||
if (this.hasDivider()) {
|
||||
viewHolder.divider.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
viewHolder.divider.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//set the color for the divider
|
||||
viewHolder.divider.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(ctx, R.attr.material_drawer_divider, R.color.material_drawer_divider));
|
||||
|
||||
//call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
|
||||
onPostBindView(this, viewHolder.itemView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
private View view;
|
||||
private View divider;
|
||||
private TextView name;
|
||||
|
||||
private ViewHolder(View view) {
|
||||
super(view);
|
||||
this.view = view;
|
||||
this.divider = view.findViewById(R.id.material_drawer_divider);
|
||||
this.name = (TextView) view.findViewById(R.id.material_drawer_name);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class SwitchDrawerItem extends AbstractSwitchableDrawerItem<SwitchDrawerItem> {
|
||||
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public class ToggleDrawerItem extends AbstractToggleableDrawerItem<ToggleDrawerItem> {
|
||||
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface Badgeable<T> {
|
||||
T withBadge(String badge);
|
||||
|
||||
T withBadge(int badgeRes);
|
||||
|
||||
T withBadge(StringHolder badgeRes);
|
||||
|
||||
StringHolder getBadge();
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import com.mikepenz.materialdrawer.holder.BadgeStyle;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface ColorfulBadgeable<T> extends Badgeable<T> {
|
||||
T withBadgeStyle(BadgeStyle badgeStyle);
|
||||
|
||||
BadgeStyle getBadgeStyle();
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.mikepenz.fastadapter.IExpandable;
|
||||
import com.mikepenz.fastadapter.IItem;
|
||||
import com.mikepenz.fastadapter.ISubItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface IDrawerItem<T, VH extends RecyclerView.ViewHolder> extends IItem<T, VH>, IExpandable<T, IDrawerItem>, ISubItem<IDrawerItem, IDrawerItem> {
|
||||
|
||||
Object getTag();
|
||||
|
||||
boolean isEnabled();
|
||||
|
||||
boolean isSelected();
|
||||
|
||||
T withSetSelected(boolean selected);
|
||||
|
||||
boolean isSelectable();
|
||||
|
||||
boolean isExcludeFromMiniDrawer();
|
||||
|
||||
T withSelectable(boolean selectable);
|
||||
|
||||
int getType();
|
||||
|
||||
int getLayoutRes();
|
||||
|
||||
View generateView(Context ctx);
|
||||
|
||||
View generateView(Context ctx, ViewGroup parent);
|
||||
|
||||
VH getViewHolder(ViewGroup parent);
|
||||
|
||||
void unbindView(VH holder);
|
||||
|
||||
void bindView(VH holder, List<Object> payloads);
|
||||
|
||||
boolean equals(long id);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.DrawableRes;
|
||||
|
||||
import com.mikepenz.fastadapter.IIdentifyable;
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface IProfile<T> extends IIdentifyable<T> {
|
||||
T withName(CharSequence name);
|
||||
|
||||
StringHolder getName();
|
||||
|
||||
T withEmail(String email);
|
||||
|
||||
StringHolder getEmail();
|
||||
|
||||
T withIcon(Drawable icon);
|
||||
|
||||
T withIcon(Bitmap bitmap);
|
||||
|
||||
T withIcon(@DrawableRes int iconRes);
|
||||
|
||||
T withIcon(String url);
|
||||
|
||||
T withIcon(Uri uri);
|
||||
|
||||
T withIcon(IIcon icon);
|
||||
|
||||
ImageHolder getIcon();
|
||||
|
||||
T withSelectable(boolean selectable);
|
||||
|
||||
boolean isSelectable();
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import com.mikepenz.iconics.typeface.IIcon;
|
||||
import com.mikepenz.materialdrawer.holder.ImageHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface Iconable<T> {
|
||||
T withIcon(Drawable icon);
|
||||
|
||||
T withIcon(IIcon iicon);
|
||||
|
||||
T withIcon(ImageHolder icon);
|
||||
|
||||
ImageHolder getIcon();
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface Nameable<T> {
|
||||
T withName(String name);
|
||||
|
||||
T withName(int nameRes);
|
||||
|
||||
T withName(StringHolder name);
|
||||
|
||||
StringHolder getName();
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 21.08.15.
|
||||
*/
|
||||
public interface OnPostBindViewListener {
|
||||
/**
|
||||
* allows you to hook in the BindView method and modify the view after binding
|
||||
*
|
||||
* @param drawerItem the drawerItem used for this view
|
||||
* @param view the view which will be set
|
||||
*/
|
||||
void onBindView(IDrawerItem drawerItem, View view);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface Selectable<T> {
|
||||
T withSelectable(boolean selectable);
|
||||
|
||||
boolean isSelectable();
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface Tagable<T> {
|
||||
T withTag(Object tag);
|
||||
|
||||
Object getTag();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.interfaces;
|
||||
|
||||
import android.graphics.Typeface;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 03.02.15.
|
||||
*/
|
||||
public interface Typefaceable<T> {
|
||||
T withTypeface(Typeface typeface);
|
||||
|
||||
Typeface getTypeface();
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.model.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import android.util.StateSet;
|
||||
|
||||
import com.mikepenz.materialdrawer.holder.BadgeStyle;
|
||||
import com.mikepenz.materialdrawer.holder.ColorHolder;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 02.07.15.
|
||||
*/
|
||||
public class BadgeDrawableBuilder {
|
||||
private BadgeStyle mStyle;
|
||||
|
||||
public BadgeDrawableBuilder(BadgeStyle style) {
|
||||
this.mStyle = style;
|
||||
}
|
||||
|
||||
public StateListDrawable build(Context ctx) {
|
||||
StateListDrawable stateListDrawable = new StateListDrawable();
|
||||
GradientDrawable normal = (GradientDrawable) AppCompatResources.getDrawable(ctx, mStyle.getGradientDrawable());
|
||||
GradientDrawable selected = (GradientDrawable) normal.getConstantState().newDrawable().mutate();
|
||||
|
||||
ColorHolder.applyToOrTransparent(mStyle.getColor(), ctx, normal);
|
||||
if (mStyle.getColorPressed() == null) {
|
||||
ColorHolder.applyToOrTransparent(mStyle.getColor(), ctx, selected);
|
||||
} else {
|
||||
ColorHolder.applyToOrTransparent(mStyle.getColorPressed(), ctx, selected);
|
||||
}
|
||||
|
||||
if (mStyle.getCorners() != null) {
|
||||
normal.setCornerRadius(mStyle.getCorners().asPixel(ctx));
|
||||
selected.setCornerRadius(mStyle.getCorners().asPixel(ctx));
|
||||
}
|
||||
|
||||
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, selected);
|
||||
stateListDrawable.addState(StateSet.WILD_CARD, normal);
|
||||
|
||||
return stateListDrawable;
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public abstract class AbstractDrawerImageLoader implements DrawerImageLoader.IDrawerImageLoader {
|
||||
@Override
|
||||
public void set(ImageView imageView, Uri uri, Drawable placeholder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(ImageView imageView, Uri uri, Drawable placeholder, String tag) {
|
||||
//for backwards compatibility call the method without tag too
|
||||
set(imageView, uri, placeholder);
|
||||
//this won't do anything
|
||||
Log.i("MaterialDrawer", "You have not specified a ImageLoader implementation through the DrawerImageLoader.init() method, or you are still overriding the deprecated method set(ImageView iv, Uri u, Drawable d) instead of set(ImageView iv, Uri u, Drawable d, String tag)");
|
||||
}
|
||||
@Override
|
||||
public void cancel(ImageView imageView) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable placeholder(Context ctx) {
|
||||
return DrawerUIUtils.getPlaceHolder(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable placeholder(Context ctx, String tag) {
|
||||
return placeholder(ctx);
|
||||
}
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 24.03.15.
|
||||
*/
|
||||
public class DrawerImageLoader {
|
||||
public enum Tags {
|
||||
PROFILE,
|
||||
PROFILE_DRAWER_ITEM,
|
||||
ACCOUNT_HEADER
|
||||
}
|
||||
|
||||
private static DrawerImageLoader SINGLETON = null;
|
||||
|
||||
private IDrawerImageLoader imageLoader;
|
||||
private boolean mHandleAllUris = false;
|
||||
|
||||
private DrawerImageLoader(IDrawerImageLoader loaderImpl) {
|
||||
imageLoader = loaderImpl;
|
||||
}
|
||||
|
||||
public static DrawerImageLoader init(IDrawerImageLoader loaderImpl) {
|
||||
SINGLETON = new DrawerImageLoader(loaderImpl);
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
public static DrawerImageLoader getInstance() {
|
||||
if (SINGLETON == null) {
|
||||
SINGLETON = new DrawerImageLoader(new AbstractDrawerImageLoader() {
|
||||
});
|
||||
}
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
public DrawerImageLoader withHandleAllUris(boolean handleAllUris) {
|
||||
this.mHandleAllUris = handleAllUris;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageView
|
||||
* @param uri
|
||||
* @param tag
|
||||
* @return false if not consumed
|
||||
*/
|
||||
public boolean setImage(ImageView imageView, Uri uri, String tag) {
|
||||
//if we do not handle all uris and are not http or https we keep the original behavior
|
||||
if (mHandleAllUris || "http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) {
|
||||
if (imageLoader != null) {
|
||||
Drawable placeHolder = imageLoader.placeholder(imageView.getContext(), tag);
|
||||
imageLoader.set(imageView, uri, placeHolder, tag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void cancelImage(ImageView imageView) {
|
||||
if (imageLoader != null) {
|
||||
imageLoader.cancel(imageView);
|
||||
}
|
||||
}
|
||||
|
||||
public IDrawerImageLoader getImageLoader() {
|
||||
return imageLoader;
|
||||
}
|
||||
|
||||
public void setImageLoader(IDrawerImageLoader imageLoader) {
|
||||
this.imageLoader = imageLoader;
|
||||
}
|
||||
|
||||
public interface IDrawerImageLoader {
|
||||
@Deprecated
|
||||
void set(ImageView imageView, Uri uri, Drawable placeholder);
|
||||
|
||||
void set(ImageView imageView, Uri uri, Drawable placeholder, String tag);
|
||||
|
||||
void cancel(ImageView imageView);
|
||||
|
||||
Drawable placeholder(Context ctx);
|
||||
|
||||
/**
|
||||
* @param ctx
|
||||
* @param tag current possible tags: "profile", "profileDrawerItem", "accountHeader"
|
||||
* @return
|
||||
*/
|
||||
Drawable placeholder(Context ctx, String tag);
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 27.03.15.
|
||||
*/
|
||||
public class DrawerItemViewHelper {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
public DrawerItemViewHelper(Context context) {
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
private ArrayList<IDrawerItem> mDrawerItems = new ArrayList<>();
|
||||
|
||||
public DrawerItemViewHelper withDrawerItems(ArrayList<IDrawerItem> drawerItems) {
|
||||
this.mDrawerItems = drawerItems;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DrawerItemViewHelper withDrawerItems(IDrawerItem... drawerItems) {
|
||||
Collections.addAll(this.mDrawerItems, drawerItems);
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean mDivider = true;
|
||||
|
||||
public DrawerItemViewHelper withDivider(boolean divider) {
|
||||
this.mDivider = divider;
|
||||
return this;
|
||||
}
|
||||
|
||||
private OnDrawerItemClickListener mOnDrawerItemClickListener = null;
|
||||
|
||||
public DrawerItemViewHelper withOnDrawerItemClickListener(OnDrawerItemClickListener onDrawerItemClickListener) {
|
||||
mOnDrawerItemClickListener = onDrawerItemClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public View build() {
|
||||
//create the container view
|
||||
LinearLayout linearLayout = new LinearLayout(mContext);
|
||||
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
//create the divider
|
||||
if (mDivider) {
|
||||
LinearLayout divider = new LinearLayout(mContext);
|
||||
divider.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
divider.setMinimumHeight((int) UIUtils.convertDpToPixel(1, mContext));
|
||||
divider.setOrientation(LinearLayout.VERTICAL);
|
||||
divider.setBackgroundColor(UIUtils.getThemeColorFromAttrOrRes(mContext, R.attr.material_drawer_divider, R.color.material_drawer_divider));
|
||||
linearLayout.addView(divider);
|
||||
}
|
||||
|
||||
//add all drawer items
|
||||
for (IDrawerItem drawerItem : mDrawerItems) {
|
||||
View view = drawerItem.generateView(mContext);
|
||||
view.setTag(drawerItem);
|
||||
|
||||
if (drawerItem.isEnabled()) {
|
||||
view.setBackgroundResource(UIUtils.getSelectableBackgroundRes(mContext));
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mOnDrawerItemClickListener != null) {
|
||||
mOnDrawerItemClickListener.onItemClick(v, (IDrawerItem) v.getTag(R.id.material_drawer_item));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
linearLayout.addView(view);
|
||||
}
|
||||
|
||||
return linearLayout;
|
||||
}
|
||||
|
||||
|
||||
public interface OnDrawerItemClickListener {
|
||||
public void onItemClick(View view, IDrawerItem drawerItem);
|
||||
}
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.graphics.drawable.RippleDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.os.Build;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.StyleableRes;
|
||||
import androidx.core.view.ViewCompat;
|
||||
|
||||
import com.mikepenz.iconics.IconicsDrawable;
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.icons.MaterialDrawerFont;
|
||||
import com.mikepenz.materialize.util.UIUtils;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 15.03.14.
|
||||
*/
|
||||
@SuppressLint("InlinedApi")
|
||||
public class DrawerUIUtils {
|
||||
|
||||
/**
|
||||
* Get the boolean value of a given styleable.
|
||||
*
|
||||
* @param ctx
|
||||
* @param styleable
|
||||
* @param def
|
||||
* @return
|
||||
*/
|
||||
public static boolean getBooleanStyleable(Context ctx, @StyleableRes int styleable, boolean def) {
|
||||
TypedArray ta = ctx.getTheme().obtainStyledAttributes(R.styleable.MaterialDrawer);
|
||||
return ta.getBoolean(styleable, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* Util method to theme the drawer item view's background (and foreground if possible)
|
||||
*
|
||||
* @param ctx the context to use
|
||||
* @param view the view to theme
|
||||
* @param selected_color the selected color to use
|
||||
* @param animate true if we want to animate the StateListDrawable
|
||||
*/
|
||||
public static void themeDrawerItem(Context ctx, View view, int selected_color, boolean animate) {
|
||||
boolean legacyStyle = getBooleanStyleable(ctx, R.styleable.MaterialDrawer_material_drawer_legacy_style, false);
|
||||
|
||||
Drawable selected;
|
||||
Drawable unselected;
|
||||
|
||||
if (legacyStyle) {
|
||||
// Material 1.0 styling
|
||||
selected = new ColorDrawable(selected_color);
|
||||
unselected = UIUtils.getSelectableBackground(ctx);
|
||||
} else {
|
||||
// Material 2.0 styling
|
||||
int cornerRadius = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_item_corner_radius);
|
||||
int paddingTopBottom = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_item_background_padding_top_bottom);
|
||||
int paddingStartEnd = ctx.getResources().getDimensionPixelSize(R.dimen.material_drawer_item_background_padding_start_end);
|
||||
|
||||
// define normal selected background
|
||||
GradientDrawable gradientDrawable = new GradientDrawable();
|
||||
gradientDrawable.setColor(selected_color);
|
||||
gradientDrawable.setCornerRadius(cornerRadius);
|
||||
selected = new InsetDrawable(gradientDrawable, paddingStartEnd, paddingTopBottom, paddingStartEnd, paddingTopBottom);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// define mask for ripple
|
||||
GradientDrawable gradientMask = new GradientDrawable();
|
||||
gradientMask.setColor(Color.BLACK);
|
||||
gradientMask.setCornerRadius(cornerRadius);
|
||||
Drawable mask = new InsetDrawable(gradientMask, paddingStartEnd, paddingTopBottom, paddingStartEnd, paddingTopBottom);
|
||||
|
||||
unselected = new RippleDrawable(new ColorStateList(new int[][]{new int[]{}}, new int[]{UIUtils.getThemeColor(ctx, R.attr.colorControlHighlight)}), null, mask);
|
||||
} else {
|
||||
// define touch drawable
|
||||
GradientDrawable touchDrawable = new GradientDrawable();
|
||||
touchDrawable.setColor(UIUtils.getThemeColor(ctx, R.attr.colorControlHighlight));
|
||||
touchDrawable.setCornerRadius(cornerRadius);
|
||||
Drawable touchInsetDrawable = new InsetDrawable(touchDrawable, paddingStartEnd, paddingTopBottom, paddingStartEnd, paddingTopBottom);
|
||||
|
||||
StateListDrawable unselectedStates = new StateListDrawable();
|
||||
//if possible and wanted we enable animating across states
|
||||
if (animate) {
|
||||
int duration = ctx.getResources().getInteger(android.R.integer.config_shortAnimTime);
|
||||
unselectedStates.setEnterFadeDuration(duration);
|
||||
unselectedStates.setExitFadeDuration(duration);
|
||||
}
|
||||
unselectedStates.addState(new int[]{android.R.attr.state_pressed}, touchInsetDrawable);
|
||||
unselectedStates.addState(new int[]{}, new ColorDrawable(Color.TRANSPARENT));
|
||||
unselected = unselectedStates;
|
||||
}
|
||||
}
|
||||
|
||||
StateListDrawable states = new StateListDrawable();
|
||||
|
||||
//if possible and wanted we enable animating across states
|
||||
if (animate) {
|
||||
int duration = ctx.getResources().getInteger(android.R.integer.config_shortAnimTime);
|
||||
states.setEnterFadeDuration(duration);
|
||||
states.setExitFadeDuration(duration);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
states.addState(new int[]{android.R.attr.state_selected}, selected);
|
||||
states.addState(new int[]{}, new ColorDrawable(Color.TRANSPARENT));
|
||||
|
||||
ViewCompat.setBackground(view, states);
|
||||
view.setForeground(unselected);
|
||||
} else {
|
||||
states.addState(new int[]{android.R.attr.state_selected}, selected);
|
||||
states.addState(new int[]{}, unselected);
|
||||
|
||||
ViewCompat.setBackground(view, states);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to create a colorStateList for the text
|
||||
*
|
||||
* @param text_color
|
||||
* @param selected_text_color
|
||||
* @return
|
||||
*/
|
||||
public static ColorStateList getTextColorStateList(int text_color, int selected_text_color) {
|
||||
return new ColorStateList(
|
||||
new int[][]{
|
||||
new int[]{android.R.attr.state_selected},
|
||||
new int[]{}
|
||||
},
|
||||
new int[]{
|
||||
selected_text_color,
|
||||
text_color
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to create a stateListDrawable for the icon
|
||||
*
|
||||
* @param icon
|
||||
* @param selectedIcon
|
||||
* @return
|
||||
*/
|
||||
public static StateListDrawable getIconStateList(Drawable icon, Drawable selectedIcon) {
|
||||
StateListDrawable iconStateListDrawable = new StateListDrawable();
|
||||
iconStateListDrawable.addState(new int[]{android.R.attr.state_selected}, selectedIcon);
|
||||
iconStateListDrawable.addState(new int[]{}, icon);
|
||||
return iconStateListDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to create a StateListDrawable for the drawer item background
|
||||
*
|
||||
* @param selected_color
|
||||
* @return
|
||||
*/
|
||||
public static StateListDrawable getDrawerItemBackground(int selected_color) {
|
||||
ColorDrawable clrActive = new ColorDrawable(selected_color);
|
||||
StateListDrawable states = new StateListDrawable();
|
||||
states.addState(new int[]{android.R.attr.state_selected}, clrActive);
|
||||
return states;
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to calculate the optimal drawer width
|
||||
*
|
||||
* @param context
|
||||
* @return
|
||||
*/
|
||||
public static int getOptimalDrawerWidth(Context context) {
|
||||
int possibleMinDrawerWidth = UIUtils.getScreenWidth(context) - UIUtils.getActionBarHeight(context);
|
||||
int maxDrawerWidth = context.getResources().getDimensionPixelSize(R.dimen.material_drawer_width);
|
||||
return Math.min(possibleMinDrawerWidth, maxDrawerWidth);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* helper method to get a person placeHolder drawable
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
public static Drawable getPlaceHolder(Context ctx) {
|
||||
return new IconicsDrawable(ctx, MaterialDrawerFont.Icon.mdf_person).colorRes(R.color.accent).backgroundColorRes(R.color.primary).sizeDp(56).paddingDp(16);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to set the vertical padding to the DrawerItems
|
||||
* this is required because on API Level 17 the padding is ignored which is set via the XML
|
||||
*
|
||||
* @param v
|
||||
*/
|
||||
public static void setDrawerVerticalPadding(View v) {
|
||||
int verticalPadding = v.getContext().getResources().getDimensionPixelSize(R.dimen.material_drawer_vertical_padding);
|
||||
v.setPadding(verticalPadding, 0, verticalPadding, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to set the vertical padding including the extra padding for deeper item hirachy level to the DrawerItems
|
||||
* this is required because on API Level 17 the padding is ignored which is set via the XML
|
||||
*
|
||||
* @param v
|
||||
* @param level
|
||||
*/
|
||||
public static void setDrawerVerticalPadding(View v, int level) {
|
||||
int verticalPadding = v.getContext().getResources().getDimensionPixelSize(R.dimen.material_drawer_vertical_padding);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
v.setPaddingRelative(verticalPadding * level, 0, verticalPadding, 0);
|
||||
} else {
|
||||
v.setPadding(verticalPadding * level, 0, verticalPadding, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper to check if the system bar is on the bottom of the screen
|
||||
*
|
||||
* @param ctx
|
||||
* @return
|
||||
*/
|
||||
public static boolean isSystemBarOnBottom(Context ctx) {
|
||||
WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
|
||||
DisplayMetrics metrics = new DisplayMetrics();
|
||||
wm.getDefaultDisplay().getMetrics(metrics);
|
||||
Configuration cfg = ctx.getResources().getConfiguration();
|
||||
boolean canMove = (metrics.widthPixels != metrics.heightPixels &&
|
||||
cfg.smallestScreenWidthDp < 600);
|
||||
|
||||
return (!canMove || metrics.widthPixels < metrics.heightPixels);
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Mike Penz All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.mikepenz.materialdrawer.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
/**
|
||||
* Created by mikepenz on 14.03.15.
|
||||
* This class implements a hack to change the layout padding on bottom if the keyboard is shown
|
||||
* to allow long lists with editTextViews
|
||||
* Basic idea for this solution found here: http://stackoverflow.com/a/9108219/325479
|
||||
* @deprecated Do not use this anymore, the MaterialDrawer uses the `fitsSystemWindows` now correctly so it should not be required. (it would only be required for cases with the fullscreen flag)
|
||||
*/
|
||||
@Deprecated
|
||||
public class KeyboardUtil {
|
||||
private View decorView;
|
||||
private View contentView;
|
||||
|
||||
public KeyboardUtil(Activity act, View contentView) {
|
||||
this.decorView = act.getWindow().getDecorView();
|
||||
this.contentView = contentView;
|
||||
|
||||
//only required on newer android versions. it was working on API level 19
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//a small helper to allow showing the editText focus
|
||||
ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
Rect r = new Rect();
|
||||
//r will be populated with the coordinates of your view that area still visible.
|
||||
decorView.getWindowVisibleDisplayFrame(r);
|
||||
|
||||
//get screen height and calculate the difference with the useable area from the r
|
||||
int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
|
||||
int diff = height - r.bottom;
|
||||
|
||||
//if it could be a keyboard add the padding to the view
|
||||
if (diff != 0) {
|
||||
// if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
|
||||
//check if the padding is 0 (if yes set the padding for the keyboard)
|
||||
if (contentView.getPaddingBottom() != diff) {
|
||||
//set the padding of the contentView for the keyboard
|
||||
contentView.setPadding(0, 0, 0, diff);
|
||||
}
|
||||
} else {
|
||||
//check if the padding is != 0 (if yes reset the padding)
|
||||
if (contentView.getPaddingBottom() != 0) {
|
||||
//reset the padding of the contentView
|
||||
contentView.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Helper to hide the keyboard
|
||||
*
|
||||
* @param act
|
||||
*/
|
||||
public static void hideKeyboard(Activity act) {
|
||||
if (act != null && act.getCurrentFocus() != null) {
|
||||
InputMethodManager inputMethodManager = (InputMethodManager) act.getSystemService(Activity.INPUT_METHOD_SERVICE);
|
||||
inputMethodManager.hideSoftInputFromWindow(act.getCurrentFocus().getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.mikepenz.materialdrawer.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
|
||||
/**
|
||||
* http://stackoverflow.com/questions/7979440/android-cloning-a-drawable-in-order-to-make-a-statelistdrawable-with-filters
|
||||
* http://stackoverflow.com/users/2075875/malachiasz
|
||||
*/
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
public class PressedEffectStateListDrawable extends StateListDrawable {
|
||||
|
||||
private int color;
|
||||
private int selectionColor;
|
||||
|
||||
public PressedEffectStateListDrawable(Drawable drawable, int color, int selectionColor) {
|
||||
super();
|
||||
|
||||
drawable = drawable.mutate();
|
||||
|
||||
addState(new int[]{android.R.attr.state_selected}, drawable);
|
||||
addState(new int[]{}, drawable);
|
||||
|
||||
this.color = color;
|
||||
this.selectionColor = selectionColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onStateChange(int[] states) {
|
||||
boolean isStatePressedInArray = false;
|
||||
for (int state : states) {
|
||||
if (state == android.R.attr.state_selected) {
|
||||
isStatePressedInArray = true;
|
||||
}
|
||||
}
|
||||
if (isStatePressedInArray) {
|
||||
super.setColorFilter(selectionColor, PorterDuff.Mode.SRC_IN);
|
||||
} else {
|
||||
super.setColorFilter(color, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
return super.onStateChange(states);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateful() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,349 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* The original is from Google you can find here:
|
||||
* https://github.com/google/iosched/blob/master/android/src/main/java/com/google/samples/apps/iosched/ui/widget/BezelImageView.java
|
||||
*
|
||||
* Modified and improved with additional functionality by Mike Penz
|
||||
*/
|
||||
|
||||
package com.mikepenz.materialdrawer.view;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.mikepenz.materialdrawer.R;
|
||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
|
||||
|
||||
|
||||
/**
|
||||
* An {@link android.widget.ImageView} that draws its contents inside a mask and draws a border
|
||||
* drawable on top. This is useful for applying a beveled look to image contents, but is also
|
||||
* flexible enough for use with other desired aesthetics.
|
||||
*/
|
||||
public class BezelImageView extends AppCompatImageView {
|
||||
private Paint mBlackPaint;
|
||||
private Paint mMaskedPaint;
|
||||
|
||||
private Rect mBounds;
|
||||
private RectF mBoundsF;
|
||||
|
||||
private Drawable mMaskDrawable;
|
||||
private boolean mDrawCircularShadow = true;
|
||||
|
||||
private ColorMatrixColorFilter mDesaturateColorFilter;
|
||||
|
||||
private int mSelectorAlpha = 150;
|
||||
private int mSelectorColor;
|
||||
private ColorFilter mSelectorFilter;
|
||||
|
||||
private boolean mCacheValid = false;
|
||||
private Bitmap mCacheBitmap;
|
||||
private int mCachedWidth;
|
||||
private int mCachedHeight;
|
||||
|
||||
private boolean isPressed = false;
|
||||
private boolean isSelected;
|
||||
|
||||
public BezelImageView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public BezelImageView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public BezelImageView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
// Attribute initialization
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BezelImageView, defStyle, R.style.BezelImageView);
|
||||
|
||||
mMaskDrawable = a.getDrawable(R.styleable.BezelImageView_biv_maskDrawable);
|
||||
if (mMaskDrawable != null) {
|
||||
mMaskDrawable.setCallback(this);
|
||||
}
|
||||
|
||||
mDrawCircularShadow = a.getBoolean(R.styleable.BezelImageView_biv_drawCircularShadow, true);
|
||||
|
||||
mSelectorColor = a.getColor(R.styleable.BezelImageView_biv_selectorOnPress, 0);
|
||||
|
||||
a.recycle();
|
||||
|
||||
// Other initialization
|
||||
mBlackPaint = new Paint();
|
||||
mBlackPaint.setColor(0xff000000);
|
||||
|
||||
mMaskedPaint = new Paint();
|
||||
mMaskedPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||
|
||||
// Always want a cache allocated.
|
||||
mCacheBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
|
||||
|
||||
// Create a desaturate color filter for pressed state.
|
||||
ColorMatrix cm = new ColorMatrix();
|
||||
cm.setSaturation(0);
|
||||
mDesaturateColorFilter = new ColorMatrixColorFilter(cm);
|
||||
|
||||
//create a selectorFilter if we already have a color
|
||||
if (mSelectorColor != 0) {
|
||||
this.mSelectorFilter = new PorterDuffColorFilter(Color.argb(mSelectorAlpha, Color.red(mSelectorColor), Color.green(mSelectorColor), Color.blue(mSelectorColor)), PorterDuff.Mode.SRC_ATOP);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int old_w, int old_h) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (mDrawCircularShadow) {
|
||||
setOutlineProvider(new CustomOutline(w, h));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(21)
|
||||
private class CustomOutline extends ViewOutlineProvider {
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
CustomOutline(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setOval(0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setFrame(int l, int t, int r, int b) {
|
||||
final boolean changed = super.setFrame(l, t, r, b);
|
||||
mBounds = new Rect(0, 0, r - l, b - t);
|
||||
mBoundsF = new RectF(mBounds);
|
||||
|
||||
if (mMaskDrawable != null) {
|
||||
mMaskDrawable.setBounds(mBounds);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
mCacheValid = false;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mBounds == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int width = mBounds.width();
|
||||
int height = mBounds.height();
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mCacheValid || width != mCachedWidth || height != mCachedHeight || isSelected != isPressed) {
|
||||
// Need to redraw the cache
|
||||
if (width == mCachedWidth && height == mCachedHeight) {
|
||||
// Have a correct-sized bitmap cache already allocated. Just erase it.
|
||||
mCacheBitmap.eraseColor(0);
|
||||
} else {
|
||||
// Allocate a new bitmap with the correct dimensions.
|
||||
mCacheBitmap.recycle();
|
||||
//noinspection AndroidLintDrawAllocation
|
||||
mCacheBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||
mCachedWidth = width;
|
||||
mCachedHeight = height;
|
||||
}
|
||||
|
||||
Canvas cacheCanvas = new Canvas(mCacheBitmap);
|
||||
if (mMaskDrawable != null) {
|
||||
int sc = cacheCanvas.save();
|
||||
mMaskDrawable.draw(cacheCanvas);
|
||||
if (isSelected) {
|
||||
if (mSelectorFilter != null) {
|
||||
mMaskedPaint.setColorFilter(mSelectorFilter);
|
||||
} else {
|
||||
mMaskedPaint.setColorFilter(mDesaturateColorFilter);
|
||||
|
||||
}
|
||||
} else {
|
||||
mMaskedPaint.setColorFilter(null);
|
||||
}
|
||||
cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, Canvas.ALL_SAVE_FLAG);
|
||||
super.onDraw(cacheCanvas);
|
||||
cacheCanvas.restoreToCount(sc);
|
||||
} else if (isSelected) {
|
||||
int sc = cacheCanvas.save();
|
||||
cacheCanvas.drawRect(0, 0, mCachedWidth, mCachedHeight, mBlackPaint);
|
||||
if (mSelectorFilter != null) {
|
||||
mMaskedPaint.setColorFilter(mSelectorFilter);
|
||||
} else {
|
||||
mMaskedPaint.setColorFilter(mDesaturateColorFilter);
|
||||
}
|
||||
cacheCanvas.saveLayer(mBoundsF, mMaskedPaint, Canvas.ALL_SAVE_FLAG);
|
||||
super.onDraw(cacheCanvas);
|
||||
cacheCanvas.restoreToCount(sc);
|
||||
} else {
|
||||
super.onDraw(cacheCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw from cache
|
||||
canvas.drawBitmap(mCacheBitmap, mBounds.left, mBounds.top, null);
|
||||
|
||||
//remember the previous press state
|
||||
isPressed = isPressed();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
// Check for clickable state and do nothing if disabled
|
||||
if (!this.isClickable()) {
|
||||
this.isSelected = false;
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
// Set selected state based on Motion Event
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
this.isSelected = true;
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_SCROLL:
|
||||
case MotionEvent.ACTION_OUTSIDE:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
this.isSelected = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Redraw image and return super type
|
||||
this.invalidate();
|
||||
return super.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawableStateChanged() {
|
||||
super.drawableStateChanged();
|
||||
if (mMaskDrawable != null && mMaskDrawable.isStateful()) {
|
||||
mMaskDrawable.setState(getDrawableState());
|
||||
}
|
||||
if (isDuplicateParentStateEnabled()) {
|
||||
ViewCompat.postInvalidateOnAnimation(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(Drawable who) {
|
||||
if (who == mMaskDrawable) {
|
||||
invalidate();
|
||||
} else {
|
||||
super.invalidateDrawable(who);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean verifyDrawable(Drawable who) {
|
||||
return who == mMaskDrawable || super.verifyDrawable(who);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the color of the selector to be draw over the
|
||||
* CircularImageView. Be sure to provide some opacity.
|
||||
*
|
||||
* @param selectorColor The color (including alpha) to set for the selector overlay.
|
||||
*/
|
||||
public void setSelectorColor(int selectorColor) {
|
||||
this.mSelectorColor = selectorColor;
|
||||
this.mSelectorFilter = new PorterDuffColorFilter(Color.argb(mSelectorAlpha, Color.red(mSelectorColor), Color.green(mSelectorColor), Color.blue(mSelectorColor)), PorterDuff.Mode.SRC_ATOP);
|
||||
this.invalidate();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(Drawable drawable) {
|
||||
super.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageResource(int resId) {
|
||||
super.setImageResource(resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageBitmap(Bitmap bm) {
|
||||
super.setImageBitmap(bm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageURI(Uri uri) {
|
||||
if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme())) {
|
||||
DrawerImageLoader.getInstance().setImage(this, uri, null);
|
||||
} else {
|
||||
super.setImageURI(uri);
|
||||
}
|
||||
}
|
||||
|
||||
private ColorMatrixColorFilter mTempDesaturateColorFilter;
|
||||
private ColorFilter mTempSelectorFilter;
|
||||
|
||||
public void disableTouchFeedback(boolean disable) {
|
||||
if (disable) {
|
||||
mTempDesaturateColorFilter = this.mDesaturateColorFilter;
|
||||
mTempSelectorFilter = this.mSelectorFilter;
|
||||
this.mSelectorFilter = null;
|
||||
this.mDesaturateColorFilter = null;
|
||||
} else {
|
||||
if (mTempDesaturateColorFilter != null) {
|
||||
this.mDesaturateColorFilter = mTempDesaturateColorFilter;
|
||||
}
|
||||
if (mTempSelectorFilter != null) {
|
||||
this.mSelectorFilter = mTempSelectorFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<!--
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#000" />
|
||||
</shape>
|
@ -1,7 +0,0 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="#40000000"
|
||||
android:startColor="@android:color/transparent" />
|
||||
</shape>
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
Before Width: | Height: | Size: 171 B |
@ -1,7 +0,0 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="270"
|
||||
android:endColor="#40000000"
|
||||
android:startColor="@android:color/transparent" />
|
||||
</shape>
|
@ -1,114 +0,0 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/material_drawer_account_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_drawer_account_header_height_compact"
|
||||
android:clickable="true"
|
||||
android:fitsSystemWindows="false"
|
||||
android:focusable="true"
|
||||
app:layout_dodgeInsetEdges="top">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/material_drawer_account_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_drawer_account_header_height_compact"
|
||||
android:scaleType="fitXY"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/material_drawer_statusbar_guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_begin="0dp" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_first"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="1dp"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_second"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="1dp"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_third"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="1dp"
|
||||
android:visibility="gone"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_current"
|
||||
android:layout_width="@dimen/material_drawer_account_header_compact"
|
||||
android:layout_height="@dimen/material_drawer_account_header_compact"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingRight="@dimen/material_drawer_vertical_padding"
|
||||
android:textSize="@dimen/material_drawer_account_header_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/material_drawer_account_header_email"
|
||||
app:layout_constraintEnd_toStartOf="@+id/material_drawer_account_header_text_switcher"
|
||||
app:layout_constraintStart_toEndOf="@id/material_drawer_account_header_current"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_goneMarginStart="0dp" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_email"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingRight="@dimen/material_drawer_vertical_padding"
|
||||
android:textSize="@dimen/material_drawer_account_header_subtext"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/material_drawer_account_header_text_switcher"
|
||||
app:layout_constraintStart_toEndOf="@id/material_drawer_account_header_current"
|
||||
app:layout_constraintTop_toBottomOf="@id/material_drawer_account_header_name"
|
||||
app:layout_goneMarginStart="0dp" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/material_drawer_account_header_text_switcher"
|
||||
android:layout_width="@dimen/material_drawer_account_header_dropdown"
|
||||
android:layout_height="@dimen/material_drawer_account_header_dropdown"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginBottom="@dimen/material_drawer_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:focusable="true" />
|
@ -1,128 +0,0 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/material_drawer_account_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_drawer_account_header_height"
|
||||
android:clickable="true">
|
||||
|
||||
<pl.droidsonroids.gif.GifImageView
|
||||
android:id="@+id/material_drawer_account_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_drawer_account_header_height"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/material_drawer_statusbar_guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_begin="0dp" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_current"
|
||||
android:layout_width="@dimen/material_drawer_account_header_selected"
|
||||
android:layout_height="@dimen/material_drawer_account_header_selected"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:clickable="true"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_first"
|
||||
android:layout_width="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_height="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_second"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_second"
|
||||
android:layout_width="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_height="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_small_third"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<com.mikepenz.materialdrawer.view.BezelImageView
|
||||
android:id="@+id/material_drawer_account_header_small_third"
|
||||
android:layout_width="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_height="@dimen/material_drawer_account_header_secondary"
|
||||
android:layout_marginTop="@dimen/material_drawer_account_header_horizontal_top"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:clickable="true"
|
||||
android:elevation="2dp"
|
||||
android:focusable="true"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/material_drawer_statusbar_guideline" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/material_drawer_text_guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_end="@dimen/material_drawer_account_header_dropdown_guideline" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/material_drawer_account_header_title"
|
||||
app:layout_constraintBottom_toTopOf="@id/material_drawer_account_header_email"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_text_switcher"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/material_drawer_text_guideline"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_account_header_email"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginBottom="@dimen/material_drawer_padding"
|
||||
android:fontFamily="sans-serif"
|
||||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:textSize="@dimen/material_drawer_account_header_subtext"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/material_drawer_account_header_text_switcher"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/material_drawer_account_header_name" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/material_drawer_account_header_text_switcher"
|
||||
android:layout_width="@dimen/material_drawer_account_header_dropdown"
|
||||
android:layout_height="@dimen/material_drawer_account_header_dropdown"
|
||||
android:layout_marginEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginRight="@dimen/material_drawer_vertical_padding"
|
||||
android:layout_marginBottom="@dimen/material_drawer_account_header_dropdown_margin_bottom"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/material_drawer_padding"
|
||||
android:paddingBottom="@dimen/material_drawer_padding">
|
||||
|
||||
<View
|
||||
android:id="@+id/material_drawer_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp" />
|
||||
</RelativeLayout>
|
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/material_drawer_item_primary"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingLeft="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingEnd="@dimen/material_drawer_vertical_padding"
|
||||
android:paddingRight="@dimen/material_drawer_vertical_padding">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/material_drawer_icon"
|
||||
android:layout_width="@dimen/material_drawer_item_primary_icon"
|
||||
android:layout_height="@dimen/material_drawer_item_primary"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingLeft="0dp"
|
||||
android:paddingTop="@dimen/material_drawer_item_primary_icon_padding"
|
||||
android:paddingEnd="@dimen/material_drawer_item_primary_icon_padding_right"
|
||||
android:paddingRight="@dimen/material_drawer_item_primary_icon_padding_right"
|
||||
android:paddingBottom="@dimen/material_drawer_item_primary_icon_padding"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:gravity="center_vertical|start"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:textDirection="anyRtl"
|
||||
android:textSize="@dimen/material_drawer_item_primary_text"
|
||||
app:layout_constraintBottom_toTopOf="@id/material_drawer_description"
|
||||
app:layout_constraintEnd_toStartOf="@+id/material_drawer_arrow_container"
|
||||
app:layout_constraintStart_toEndOf="@id/material_drawer_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Some drawer text" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/material_drawer_description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:fontFamily="sans-serif"
|
||||
android:gravity="center_vertical|start"
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:textDirection="anyRtl"
|
||||
android:textSize="@dimen/material_drawer_item_primary_description"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/material_drawer_arrow_container"
|
||||
app:layout_constraintStart_toEndOf="@id/material_drawer_icon"
|
||||
app:layout_constraintTop_toBottomOf="@id/material_drawer_name"
|
||||
tools:text="Some drawer text" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/material_drawer_arrow_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:paddingStart="@dimen/material_drawer_padding"
|
||||
android:paddingLeft="@dimen/material_drawer_padding"
|
||||
android:paddingEnd="0dp"
|
||||
android:paddingRight="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/material_drawer_arrow"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp" />
|
||||
</LinearLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user