From 490ade8b8de1b8bcb0dbf7219260457405f6ee2f Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Sat, 12 Mar 2022 19:57:54 +0100 Subject: [PATCH] [android] Use new Menu Bottom Sheet component Signed-off-by: Arnaud Vergnet --- .../res/drawable-hdpi/ic_24_px_settings.webp | Bin 344 -> 0 bytes android/res/drawable-hdpi/ic_edit.webp | Bin 164 -> 0 bytes android/res/drawable-hdpi/ic_hide.webp | Bin 504 -> 0 bytes .../res/drawable-mdpi/ic_24_px_settings.webp | Bin 238 -> 0 bytes android/res/drawable-mdpi/ic_edit.webp | Bin 148 -> 0 bytes android/res/drawable-mdpi/ic_hide.webp | Bin 344 -> 0 bytes .../res/drawable-xhdpi/ic_24_px_settings.webp | Bin 434 -> 0 bytes android/res/drawable-xhdpi/ic_edit.webp | Bin 166 -> 0 bytes android/res/drawable-xhdpi/ic_hide.webp | Bin 654 -> 0 bytes .../drawable-xxhdpi/ic_24_px_settings.webp | Bin 614 -> 0 bytes android/res/drawable-xxhdpi/ic_edit.webp | Bin 244 -> 0 bytes android/res/drawable-xxhdpi/ic_hide.webp | Bin 936 -> 0 bytes .../drawable-xxxhdpi/ic_24_px_settings.webp | Bin 756 -> 0 bytes android/res/drawable-xxxhdpi/ic_edit.webp | Bin 288 -> 0 bytes android/res/drawable-xxxhdpi/ic_hide.webp | Bin 1222 -> 0 bytes android/res/drawable/ic_edit.xml | 5 + android/res/drawable/ic_hide.xml | 5 + android/res/drawable/ic_settings.xml | 5 + android/res/layout/bottom_sheet.xml | 25 ++ android/res/layout/bottom_sheet_menu_item.xml | 39 +++ android/res/menu/menu_bookmark_categories.xml | 13 - android/res/menu/menu_bookmarks.xml | 15 - android/res/menu/menu_bookmarks_list.xml | 19 -- .../bookmarks/BookmarkCategoriesFragment.java | 185 ++--------- .../maps/bookmarks/BookmarksListFragment.java | 193 +++++------ .../maps/downloader/DownloaderAdapter.java | 306 ++++++++---------- .../maps/editor/ProfileFragment.java | 73 +---- .../widget/placepage/PlacePageButtons.java | 28 +- .../util/bottomsheet/MenuAdapter.java | 106 ++++++ .../bottomsheet/MenuBottomSheetFragment.java | 79 +++++ .../util/bottomsheet/MenuBottomSheetItem.java | 30 ++ 31 files changed, 583 insertions(+), 543 deletions(-) delete mode 100644 android/res/drawable-hdpi/ic_24_px_settings.webp delete mode 100644 android/res/drawable-hdpi/ic_edit.webp delete mode 100644 android/res/drawable-hdpi/ic_hide.webp delete mode 100644 android/res/drawable-mdpi/ic_24_px_settings.webp delete mode 100644 android/res/drawable-mdpi/ic_edit.webp delete mode 100644 android/res/drawable-mdpi/ic_hide.webp delete mode 100644 android/res/drawable-xhdpi/ic_24_px_settings.webp delete mode 100644 android/res/drawable-xhdpi/ic_edit.webp delete mode 100644 android/res/drawable-xhdpi/ic_hide.webp delete mode 100644 android/res/drawable-xxhdpi/ic_24_px_settings.webp delete mode 100644 android/res/drawable-xxhdpi/ic_edit.webp delete mode 100644 android/res/drawable-xxhdpi/ic_hide.webp delete mode 100644 android/res/drawable-xxxhdpi/ic_24_px_settings.webp delete mode 100644 android/res/drawable-xxxhdpi/ic_edit.webp delete mode 100644 android/res/drawable-xxxhdpi/ic_hide.webp create mode 100644 android/res/drawable/ic_edit.xml create mode 100644 android/res/drawable/ic_hide.xml create mode 100644 android/res/drawable/ic_settings.xml create mode 100644 android/res/layout/bottom_sheet.xml create mode 100644 android/res/layout/bottom_sheet_menu_item.xml delete mode 100644 android/res/menu/menu_bookmark_categories.xml delete mode 100644 android/res/menu/menu_bookmarks.xml delete mode 100644 android/res/menu/menu_bookmarks_list.xml create mode 100644 android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java create mode 100644 android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java create mode 100644 android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java diff --git a/android/res/drawable-hdpi/ic_24_px_settings.webp b/android/res/drawable-hdpi/ic_24_px_settings.webp deleted file mode 100644 index e287c8a654f365031fb6a4dffb81320a2bcca331..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 344 zcmV-e0jK^_Nk&Fc0RRA3MM6+kP&iCO0RR9mBftm{&tf2LoA@_lJt z&W8J)+O};NcuVCSShoNWDAiFA=@QZdXbJ#<;O5Xo&>)yDf%pLkg|mS80;LEr9RfFp zn*cK=nBdLZ%RBp%Ujs;vBq@?&mU)($nFp4cnR)&HPpRz6>eE~!`p>{^BSrBs!!J}L zP5c3rbGAZok+Z7lQ>lt0lIqV)3`pu2_s7Bw*GqHvSl=7d2fzPAZi}Qi^~Tn>q*!n& zk@0i9x&KPWb5p!0tjloymTGnwjn{Qf@ZK)th~RV1SyAIIz?!UHfV)1qrT`|D@eXYJ zqoxzu@yDjUgq4SWZ!BJ>9Wv|mf@Ln$9J$bNyb6~0?;acDwSADp{V&T&yZZ>8aCU^pa@Df0I3F^IkfCK{NB@Du%fMe)OgxMW_bCJaW&O` zPFvWx9&ay2y~4@Z*xD!X-r!(|;4TNL4sL@a@75<^IrvN2x713G>#*n`Ddrfs&9=>R z1bB;)BA=ntS5ovnz=)>}2?rSKB~=3-{f<(df&BzCrss=ck_S% diff --git a/android/res/drawable-mdpi/ic_24_px_settings.webp b/android/res/drawable-mdpi/ic_24_px_settings.webp deleted file mode 100644 index 5340cee7250d8dca580c829b78a3674427ce9d51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmVt)zLsVk3Z$Uj$@>U*0mf6o}}*!lVtDl(J4i zk1FR6Z2YnVe1LsO)CA&=HcTj5mu?S&V7ROYkZJG%BufggJ){geB7&g+4i^T&pSL}{ZI>oA@%W_8w?Y=*u1*l8h7<&+mq!(vo~*%>97{iQ4j^$LNi~SSN^>+M=^z1TGDEA$AFG~Z1VS*OZ~}u5639ysczFM; zRP22K9L2o{q8GrGF07jYSpe8nO>oz_pmS%=+?6@b+}-p42Wa}z-nd2dpMl#(ijrH# z<3B(>V&WTX{`F~N97Wf(u|X(kqfB@MRh@2OCi6Q1gTg)>9&WJYKb9f@kt|ZLlK}0r zFSp!d0IOCuQSRY!ZQKMecps7PS2K$#RB@XVT7HzkIDdRd%bZnq2Dp<7bPHW c#{;Tfknjw;+##H5W0J6}jU@SxbVFSt0L$LS4gdfE diff --git a/android/res/drawable-xhdpi/ic_edit.webp b/android/res/drawable-xhdpi/ic_edit.webp deleted file mode 100644 index 7430088b38c2f26b2d11a3132bbeaaffd3f3d0cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166 zcmV;X09pT1Nk&GV00012MM6+kP&iDI0000lFTe{BuQ31fKmUp&NlJrfxI26az!?t& z1mYp#qXV(gL8w3^Y#0m(EZ9bp?8VqmySylNZD+= z14}k+gAF&Ct~}2TG}Y%V?|)<4=a-GIWwX5&lB$C_C0sUVh;!vMB#?6wXDf%%`f6T|7the*)x= zANg`PrXbG&HUw%O@UuBcSxk1}XC~a3M(QNdgOlq^-cm@*pMd z11E!|&fmb21&1y_czET|qUr!>6W+-)L+Oj(^8${Rrc3QVr@`y7bZNb@q^W6m)pY~* zWTveBcDy zS+39}`@Cls*lKnd7 z`nEJAXY)PBmog7keFC1h{&w7JmTzLml!d)Mnh)>+>(q{fraAJ$!Wfx+ZX3Mc)|V+|NzzGUol+m$lEnVu1B)e`j~h5nyU4NChu}#~A_A7{Hn!=^$`6P?pz!I=b`F2#na8u zAWZQ2jIO(Vlu2<+6 z&gTR$C4C{)O|)@Si>~v&VDs1fFL-U96n?8t>VSk1b!4B5N#E2-*^scLj%;u->7_cU z3=)<_QVt2@A~$j&AmEiclJ%4x{xzh0Cl&9F7X7%bJRuG4?|(e&n&*(@-{XEECu?ND zJwDu4FtSS~+~d_4BfaFpR=@N3c}Zqh$&C2^BS}NxsFLh%AS>7uOdWVKZ^io2gBeUq z^*#q&Va@~ko7&XErkXQN|Aga#54I~b A)&Kwi diff --git a/android/res/drawable-xxhdpi/ic_edit.webp b/android/res/drawable-xxhdpi/ic_edit.webp deleted file mode 100644 index 68f9937bea9eadd560f026d2d8c7c5f05cc02303..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 244 zcmWIYbaQ*dz`zjh>J$(bVBvEg$kum1ASm$O;Qwd)|6RA;f{M47_}DLN*u}=MU?L-f ziUEUs19Lx@gR2|kBIXMW3N8#R4DNXVtH)cPjkplRCL~-nbjg7FRM;VvAZ|Xp)7ngEhm1 zPfmri-a0QARCw5SsOHbN>zof(w?ASxW7jPJ@P&fT=O%U`k=yQpCtnWpn3pmQr)x&=5@d?f})Jz`UnV> z9S~nO=(cI}6QC{0wrSgH3)^d3$F^G)3bmrUg zvl)nkBOH=<0&(CZ-OJ*@8KJ73eG>)Vun$)S&b6;qsZdg29cBr`0CoNQk~k?=Fq zI!qUM*gl*SIMTk{Kf>o!>o7^+9{X@oa0b|y^~1&2iD_fD9J}`9$@P<4#-&?<2?9Sh zQM2XIf)opISTHWzp60)dZ=R6fXZQ}IJtD8<`3(oX;;*rOi+q;0O&c_5+VT@6Dn|Du z`J`ue0mGugb%>$iHx%Tno_+|dsDF_tV86hn0)P=O6s%tnh*_(fBzH)uAB5U&3Z$G< zkT+Y!XkrmbI>Q7Ec3gZGRsdU6ESeaL)I*fNWeV6OaH|H6tH?tsp7ni8^=T>jjnHy_ zMWG_;u?FAv@g}&ok(y4SfB`Kok_`va1oU<^*tjO>LEAgjJ_+S^1^KR%fRj4powi2P z%c$R7mH0}<_qjr6J(f+^iyWijQ)u>WR`HC0mwM!}h(`BMG~K9!O&ZbO!e$eG>aHmK zO5?Fw3C~sBDU31VmqO_@&D&|ASEK5M(8G+Ur6La^dRVV27P37kl4?9iF$g_X)C!3n z)JP9K=wyKI4bnTIl?M-{G0kQ}Ot41!5pnf1YaSzEanxvuQSgz#qpqb!(Zx`Y`eAb2 z2wm$0P6cqmu87_XXa-N@~|Egn8$uS|yoA z=u{(c?O&~@UEpPSo1?+KW>_X^JKMtWc<5IR&NK_$Hu^dg-e;cGsOxWp_EiRFGZE7{ zl?ql*F~TCP$~lO2hX)EqHzk?irpAK~h<#{7vqXNK8#HKBAvqgD@a4dd3i9W{ad`nC zP!MoozQpnHY2=v7-T3uu6ITnkDt$@w2{64>M{MXRv?>+2&o^ju*@Q0>U6?I7{e1(B z|6ssf0xk)B8TJoCQ*TAJoZ&)#k-&960?=XMiI0u0`VYtEwH7d4s_)_}F{4w*2(-@& zyc_VHdG2q4i>$*Wsl1hSI3@6+eOW&QPPPscq&N2Ah`>VoGQPR$QtiX=29moG4~Ja7 Kw<;JH{(l8KI>9;s diff --git a/android/res/drawable-xxxhdpi/ic_24_px_settings.webp b/android/res/drawable-xxxhdpi/ic_24_px_settings.webp deleted file mode 100644 index 00bc942a173d35529ef17d955b5f73f973cb140b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 756 zcmVr0maI2+Xv9v?uG-Fv`j67EaFAP=7FP#}TCAn+uK zBL{&&q{J;?Lopyvz|VkeNwQ7b8ppP6+qP}nwr$(zn){sbpZBgg#~o|E-iV0)PXPQc zG2;$}zqD%45lX(hXpON>1{1Z$2c^rjCPl7CYbxayw5DI~P-~Xte&}n=nH;*Q%`Z$( z$ow}!vY2-SyG$LP*E=ehRox=t_kI@z)BH8WK4w;Th={+Y6Z8Ne`woeJwiyF}Z|@5t z;(HXYPE z)r0Xo22jQO1{?x(bdMwHzBcAw3Ek&(Sk7SqsbA|%K~XQ~ob1Vj!4=hp69}7(QK377 z;y0RE6Oe5p8V8QaFBIEmAU{O$)~Lq4Y& zn>7vWNDP?(>+ox#c_3~O`c(|vr-VwVf`lG{{fbaLmAQ~kkKK`wFBNl#lwK4Zf=sHLGLf|+;$8k%Kh0`Y$MFG!R^-KU$<1@8RZ3 zYH0?(%j&o=W#s=`61=jUATT m)|v*nNv+9}Yt@<%xdN@Rl8e?FxRlX3XinCh*q0XgeH9`v>1%cHFT%5t~@vb@#aQ(bm_^ zHDSl{Lux{|b#}i$R3`Z0gI%TUla{X6U!EuPuX$hObntme`WepK#p`ANEVWL~D4O%G zXQ87%ua(xXN`^lBm**r-+4+TUUS5*U!>c9HeA{rvTK3nDA|@>Qh8IL8b7XXH|FV4J d-`ZW5CFEcFW$%msULSl>ycQE_mI$*k008K@f1CgS diff --git a/android/res/drawable-xxxhdpi/ic_hide.webp b/android/res/drawable-xxxhdpi/ic_hide.webp deleted file mode 100644 index 9b21cce76f40e605aa11889ce226fccb86c58601..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1222 zcmV;%1UdUsNk&G#1ONb6MM6+kP&iDn1ONapU%(d-ucn}F8!7xr-`Dg8VgBb|LD~i^ zY#w2M6%C>FWwr$(CZQHiGY$I({>|a!I&UYfd`_xYn{ht7s*4X#!*ZwMS zch!$1`KE%qb}{NXcYTh=5zhK5{4C?DLjn)Gs!6WEzK+6j=~Hn>g&zsr;V3lD7XEg2 z6c!77UC2?Pdji)x3Jo%ayq1o_Jb_QbjtbrtxYSXolP+Y{cNAs{yc=*-;I_aSjzY~e zA+5TjFh$^HSK*4laR3@jTE6x8_3J0LubSM@8P$@7gxRNlQ2qPt?6OY41i>`xXh#>| zVhl(==-`0LNikvMKzZL`Ol-*H3BJR*7?Gz-`K`jASn*4DpJ9aJ@QO+O`b}Q3>wZMX zzZ(nqA|TZD*IF5AOS$@n<{2Zi??zY$ZZmaNWUs5fWB`v z-5m{qz;b!siC!c6TiXPessXjnswq()J*{cK)kNE*TAnOvt?<%~2Xp^MuVhjuIvr@u*@Tt=oAk{91QJ z=wro!(q*%n-q1c@^-^eRc3JvmR>A-qR6m6>X1}Biv%(eyUuZIff@T@gOS4)QXq~5c zFH|&pDXlf@WP&w{>p~;5wNjbyRwHZ*Jd=J`h&Isbdl?Ds6O2~cpn0yqOVQRDCA5dO z_C1@2Mpz+ndXyVB_i95QUXyPTscIB{BxTeCP%hUZe{C3^JAE+V3?nqo7Wg0x%%M#vO3tF3Sr3)C$x%2a<+XBD>2Cs`gxrJy5*IlN2c(SJjw<;@;5A2~x5O5X!X9an ktBQXV7Pt!CBhi{U3#+3XhQnulWWw5z%Md6K!2eGH0Bkl>hyVZp diff --git a/android/res/drawable/ic_edit.xml b/android/res/drawable/ic_edit.xml new file mode 100644 index 0000000000..faddfce421 --- /dev/null +++ b/android/res/drawable/ic_edit.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/res/drawable/ic_hide.xml b/android/res/drawable/ic_hide.xml new file mode 100644 index 0000000000..32ab2aed69 --- /dev/null +++ b/android/res/drawable/ic_hide.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/res/drawable/ic_settings.xml b/android/res/drawable/ic_settings.xml new file mode 100644 index 0000000000..b240b83007 --- /dev/null +++ b/android/res/drawable/ic_settings.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/res/layout/bottom_sheet.xml b/android/res/layout/bottom_sheet.xml new file mode 100644 index 0000000000..e7e57b33ca --- /dev/null +++ b/android/res/layout/bottom_sheet.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/android/res/layout/bottom_sheet_menu_item.xml b/android/res/layout/bottom_sheet_menu_item.xml new file mode 100644 index 0000000000..8fd70d2438 --- /dev/null +++ b/android/res/layout/bottom_sheet_menu_item.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/android/res/menu/menu_bookmark_categories.xml b/android/res/menu/menu_bookmark_categories.xml deleted file mode 100644 index 15c36f8b3c..0000000000 --- a/android/res/menu/menu_bookmark_categories.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/android/res/menu/menu_bookmarks.xml b/android/res/menu/menu_bookmarks.xml deleted file mode 100644 index 1d3830f4d4..0000000000 --- a/android/res/menu/menu_bookmarks.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - diff --git a/android/res/menu/menu_bookmarks_list.xml b/android/res/menu/menu_bookmarks_list.xml deleted file mode 100644 index 4b56f751a4..0000000000 --- a/android/res/menu/menu_bookmarks_list.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java index c8fef0f0f9..c48c10e66e 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarkCategoriesFragment.java @@ -20,7 +20,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.maps.adapter.OnItemClickListener; @@ -33,20 +32,21 @@ import com.mapswithme.maps.dialog.DialogUtils; import com.mapswithme.maps.dialog.EditTextDialogFragment; import com.mapswithme.maps.widget.PlaceholderView; import com.mapswithme.maps.widget.recycler.ItemDecoratorFactory; -import com.mapswithme.util.BottomSheetHelper; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; import com.mapswithme.util.StorageUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import com.mapswithme.util.concurrency.ThreadPool; import com.mapswithme.util.concurrency.UiThread; import com.mapswithme.util.log.Logger; import com.mapswithme.util.log.LoggerFactory; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment - implements MenuItem.OnMenuItemClickListener, - BookmarkManager.BookmarksLoadingListener, + implements BookmarkManager.BookmarksLoadingListener, CategoryListCallback, OnItemClickListener, OnItemMoreClickListener, @@ -155,49 +155,27 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment getMenuItems(@NonNull BookmarkCategory item) { - BottomSheetHelper.Builder bs = BottomSheetHelper.create(getActivity(), item.getName()) - .sheet(getCategoryMenuResId()) - .listener(this); + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.list_settings, R.drawable.ic_settings, () -> onSettingsActionSelected(item))); + items.add(new MenuBottomSheetItem( + item.isVisible() ? R.string.hide : R.string.show, + item.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show, + () -> onShowActionSelected(item))); + items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_share, () -> onShareActionSelected(item))); + // Disallow deleting the last category + if (getAdapter().getBookmarkCategories().size() > 1) + items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, () -> onDeleteActionSelected(item))); - BottomSheet bottomSheet = bs.build(); - prepareBottomMenuItems(bottomSheet); - MenuItem menuItem = BottomSheetHelper.findItemById(bottomSheet, R.id.show_on_map); - menuItem.setIcon(item.isVisible() ? R.drawable.ic_hide : R.drawable.ic_show) - .setTitle(item.isVisible() ? R.string.hide : R.string.show); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); - } - - protected void prepareBottomMenuItems(@NonNull BottomSheet bottomSheet) - { - boolean isMultipleItems = getAdapter().getBookmarkCategories().size() > 1; - setEnableForMenuItem(R.id.delete, bottomSheet, isMultipleItems); - } - - @MenuRes - protected int getCategoryMenuResId() - { - return R.menu.menu_bookmark_categories; + return items; } @Override @@ -264,21 +242,26 @@ public class BookmarkCategoriesFragment extends BaseMwmRecyclerFragment { @Nullable diff --git a/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java b/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java index d5380d2113..710214d4fe 100644 --- a/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java +++ b/android/src/com/mapswithme/maps/bookmarks/BookmarksListFragment.java @@ -21,7 +21,6 @@ import androidx.recyclerview.widget.ConcatAdapter; import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.SimpleItemAnimator; -import com.cocosw.bottomsheet.BottomSheet; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.R; @@ -40,11 +39,13 @@ import com.mapswithme.maps.search.SearchEngine; import com.mapswithme.maps.widget.SearchToolbarController; import com.mapswithme.maps.widget.placepage.EditBookmarkFragment; import com.mapswithme.maps.widget.recycler.ItemDecoratorFactory; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.CrashlyticsUtils; import com.mapswithme.util.SharingUtils; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; +import java.util.ArrayList; import java.util.List; public class BookmarksListFragment extends BaseMwmRecyclerFragment @@ -615,24 +616,14 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment onTrackMenuItemClicked(track.getTrackId())) - .build(); - - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + new MenuBottomSheetFragment(track.getName(), getTrackMenuItems(track)) + .show(getParentFragmentManager(), "trackBottomSheet"); break; } } @@ -644,69 +635,8 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment - { - if (movedFromCategory) - resetSearchAndSort(); - else - adapter.notifyDataSetChanged(); - }); - break; - - case R.id.delete: - adapter.onDelete(mSelectedPosition); - BookmarkManager.INSTANCE.deleteBookmark(item.getBookmarkId()); - adapter.notifyDataSetChanged(); - if (mSearchMode) - mNeedUpdateSorting = true; - updateSearchVisibility(); - updateRecyclerVisibility(); - break; - } - return false; - } - - public boolean onListMoreMenuItemClick(@NonNull MenuItem menuItem) - { - switch (menuItem.getItemId()) - { - case R.id.sort: - ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), - getLastSortingType(), requireActivity(), getChildFragmentManager()); - return false; - - case R.id.share_category: - long catId = mCategoryDataSource.getData().getId(); - BookmarksSharingHelper.INSTANCE.prepareBookmarkCategoryForSharing(requireActivity(), catId); - return false; - - case R.id.settings: - BookmarkCategorySettingsActivity.startForResult(this, mCategoryDataSource.getData()); - return false; - - case R.id.delete_category: - requireActivity().setResult(Activity.RESULT_OK); - requireActivity().finish(); - return false; - } - return false; - } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) + public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.option_menu_bookmarks, menu); @@ -715,7 +645,7 @@ public class BookmarksListFragment extends BaseMwmRecyclerFragment 0 && !isEmpty()); - moreMenu.findItem(R.id.delete_category).setVisible(!isLastOwnedCategory()); - moreMenu.findItem(R.id.share_category).setVisible(!isEmpty()); - - BottomSheetHelper.tint(bs); - bs.show(); + new MenuBottomSheetFragment(mCategoryDataSource.getData().getName(), getOptionsMenuItems()) + .show(getParentFragmentManager(), "optionsBottomSheet"); return true; } return super.onOptionsItemSelected(item); } + private void onShareActionSelected() + { + BookmarkInfo info = (BookmarkInfo) getBookmarkListAdapter().getItem(mSelectedPosition); + SharingUtils.shareBookmark(requireContext(), info); + } + + private void onEditActionSelected() + { + BookmarkListAdapter adapter = getBookmarkListAdapter(); + BookmarkInfo info = (BookmarkInfo) adapter.getItem(mSelectedPosition); + EditBookmarkFragment.editBookmark( + info.getCategoryId(), info.getBookmarkId(), requireActivity(), getChildFragmentManager(), + (bookmarkId, movedFromCategory) -> + { + if (movedFromCategory) + resetSearchAndSort(); + else + adapter.notifyDataSetChanged(); + }); + } + + private void onDeleteActionSelected() + { + BookmarkListAdapter adapter = getBookmarkListAdapter(); + BookmarkInfo info = (BookmarkInfo) getBookmarkListAdapter().getItem(mSelectedPosition); + adapter.onDelete(mSelectedPosition); + BookmarkManager.INSTANCE.deleteBookmark(info.getBookmarkId()); + adapter.notifyDataSetChanged(); + if (mSearchMode) + mNeedUpdateSorting = true; + updateSearchVisibility(); + updateRecyclerVisibility(); + } + + private void onSortOptionSelected() + { + ChooseBookmarksSortingTypeFragment.chooseSortingType(getAvailableSortingTypes(), + getLastSortingType(), requireActivity(), getChildFragmentManager()); + } + + private void onShareOptionSelected() + { + long catId = mCategoryDataSource.getData().getId(); + BookmarksSharingHelper.INSTANCE.prepareBookmarkCategoryForSharing(requireActivity(), catId); + } + + private void onSettingsOptionSelected() + { + BookmarkCategorySettingsActivity.startForResult(this, mCategoryDataSource.getData()); + } + + private void onDeleteOptionSelected() + { + requireActivity().setResult(Activity.RESULT_OK); + requireActivity().finish(); + } + + private ArrayList getOptionsMenuItems() + { + @BookmarkManager.SortingType int[] types = getAvailableSortingTypes(); + ArrayList items = new ArrayList<>(); + if (!isEmpty()) + { + if (types.length > 0) + items.add(new MenuBottomSheetItem(R.string.sort, R.drawable.ic_sort, this::onSortOptionSelected)); + items.add(new MenuBottomSheetItem(R.string.export_file, R.drawable.ic_share, this::onShareOptionSelected)); + } + items.add(new MenuBottomSheetItem(R.string.list_settings, R.drawable.ic_settings, this::onSettingsOptionSelected)); + if (!isLastOwnedCategory()) + items.add(new MenuBottomSheetItem(R.string.delete_list, R.drawable.ic_delete, this::onDeleteOptionSelected)); + return items; + } + + private ArrayList getBookmarkMenuItems() + { + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.share, R.drawable.ic_share, this::onShareActionSelected)); + items.add(new MenuBottomSheetItem(R.string.edit, R.drawable.ic_edit, this::onEditActionSelected)); + items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, this::onDeleteActionSelected)); + return items; + } + + private ArrayList getTrackMenuItems(final Track track) + { + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, () -> onTrackMenuItemClicked(track.getTrackId()))); + return items; + } + @Override public void onPreparedFileForSharing(@NonNull BookmarkSharingResult result) { diff --git a/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java b/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java index b9f59a661f..3af7834645 100644 --- a/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java +++ b/android/src/com/mapswithme/maps/downloader/DownloaderAdapter.java @@ -1,7 +1,6 @@ package com.mapswithme.maps.downloader; import android.app.Activity; -import android.content.DialogInterface; import android.content.Intent; import android.graphics.Typeface; import android.location.Location; @@ -15,24 +14,22 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import androidx.annotation.DrawableRes; import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.MwmActivity; import com.mapswithme.maps.R; import com.mapswithme.maps.intent.Factory; import com.mapswithme.maps.location.LocationHelper; import com.mapswithme.maps.routing.RoutingController; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.StringUtils; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter; import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; @@ -72,124 +69,74 @@ class DownloaderAdapter extends RecyclerView.Adapter MapManager.nativeUpdate(item.id)); + } + + private void onExploreActionSelected(CountryItem item, DownloaderAdapter adapter) + { + Intent intent = new Intent(adapter.mActivity, MwmActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); + intent.putExtra(MwmActivity.EXTRA_TASK, new Factory.ShowCountryTask(item.id)); + adapter.mActivity.startActivity(intent); + + if (!(adapter.mActivity instanceof MwmActivity)) + adapter.mActivity.finish(); + } + + void onDeleteActionSelected(final CountryItem item, final DownloaderAdapter adapter) + { + if (RoutingController.get().isNavigating()) { - @Override - void invoke(final CountryItem item, DownloaderAdapter adapter) - { - MapManager.warn3gAndDownload(adapter.mActivity, item.id, null); - } - }, - - DELETE(R.drawable.ic_delete, R.string.delete) - { - private void deleteNode(CountryItem item) - { - MapManager.nativeCancel(item.id); - MapManager.nativeDelete(item.id); - OnmapDownloader.setAutodownloadLocked(true); - } - - @Override - void invoke(final CountryItem item, final DownloaderAdapter adapter) - { - if (RoutingController.get().isNavigating()) - { - new AlertDialog.Builder(adapter.mActivity) - .setTitle(R.string.downloader_delete_map) - .setMessage(R.string.downloader_delete_map_while_routing_dialog) - .setPositiveButton(android.R.string.ok, null) - .show(); - return; - } - - if (!MapManager.nativeHasUnsavedEditorChanges(item.id)) - { - deleteNode(item, adapter); - return; - } - - new AlertDialog.Builder(adapter.mActivity) - .setTitle(R.string.downloader_delete_map) - .setMessage(R.string.downloader_delete_map_dialog) - .setNegativeButton(android.R.string.no, null) - .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - deleteNode(item, adapter); - } - }).show(); - } - - private void deleteNode(CountryItem item, DownloaderAdapter adapter) - { - if (adapter.mActivity instanceof MwmActivity) - { - ((MwmActivity) adapter.mActivity).closePlacePage(); - } - deleteNode(item); - } - }, - - CANCEL(R.drawable.ic_cancel, R.string.cancel) - { - @Override - void invoke(CountryItem item, DownloaderAdapter adapter) - { - MapManager.nativeCancel(item.id); - } - }, - - EXPLORE(R.drawable.ic_explore, R.string.zoom_to_country) - { - @Override - void invoke(CountryItem item, DownloaderAdapter adapter) - { - Intent intent = new Intent(adapter.mActivity, MwmActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); - intent.putExtra(MwmActivity.EXTRA_TASK, new Factory.ShowCountryTask(item.id)); - adapter.mActivity.startActivity(intent); - - if (!(adapter.mActivity instanceof MwmActivity)) - adapter.mActivity.finish(); - } - }, - - UPDATE(R.drawable.ic_update, R.string.downloader_update_map) - { - @Override - void invoke(final CountryItem item, DownloaderAdapter adapter) - { - item.update(); - - if (item.status != CountryItem.STATUS_UPDATABLE) - return; - - MapManager.warnOn3gUpdate(adapter.mActivity, item.id, new Runnable() - { - @Override - public void run() - { - MapManager.nativeUpdate(item.id); - } - }); - } - }; - - final @DrawableRes int icon; - final @StringRes int title; - - MenuItem(@DrawableRes int icon, @StringRes int title) - { - this.icon = icon; - this.title = title; + new AlertDialog.Builder(adapter.mActivity) + .setTitle(R.string.downloader_delete_map) + .setMessage(R.string.downloader_delete_map_while_routing_dialog) + .setPositiveButton(android.R.string.ok, null) + .show(); + return; } - abstract void invoke(CountryItem item, DownloaderAdapter adapter); + if (!MapManager.nativeHasUnsavedEditorChanges(item.id)) + { + deleteNode(item, adapter); + return; + } + + new AlertDialog.Builder(adapter.mActivity) + .setTitle(R.string.downloader_delete_map) + .setMessage(R.string.downloader_delete_map_dialog) + .setNegativeButton(android.R.string.no, null) + .setPositiveButton(android.R.string.yes, (dialog, which) -> deleteNode(item, adapter)).show(); + } + + private void onCancelActionSelected(CountryItem item, DownloaderAdapter adapter) + { + MapManager.nativeCancel(item.id); + } + + private void deleteNode(CountryItem item) + { + MapManager.nativeCancel(item.id); + MapManager.nativeDelete(item.id); + OnmapDownloader.setAutodownloadLocked(true); + } + + private void deleteNode(CountryItem item, DownloaderAdapter adapter) + { + if (adapter.mActivity instanceof MwmActivity) + { + ((MwmActivity) adapter.mActivity).closePlacePage(); + } + deleteNode(item); } private static class PathEntry @@ -335,7 +282,7 @@ class DownloaderAdapter extends RecyclerView.Adapter items = new ArrayList<>(); + ArrayList items = getMenuItems(); + new MenuBottomSheetFragment(mItem.name, items) + .show(mFragment.getParentFragmentManager(), "downloaderBottomSheet"); + } + private MenuBottomSheetItem getDownloadMenuItem() + { + return new MenuBottomSheetItem(R.string.downloader_download_map, R.drawable.ic_download, + () -> onDownloadActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getUpdateMenuItem() + { + return new MenuBottomSheetItem(R.string.downloader_update_map, R.drawable.ic_update, + () -> onUpdateActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getExploreMenuItem() + { + return new MenuBottomSheetItem(R.string.zoom_to_country, R.drawable.ic_explore, + () -> onExploreActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getDeleteMenuItem() + { + return new MenuBottomSheetItem(R.string.delete, R.drawable.ic_delete, + () -> onDeleteActionSelected(mItem, DownloaderAdapter.this)); + } + + private MenuBottomSheetItem getCancelMenuItem() + { + return new MenuBottomSheetItem(R.string.cancel, R.drawable.ic_cancel, + () -> onCancelActionSelected(mItem, DownloaderAdapter.this)); + } + + private ArrayList getMenuItems() + { + ArrayList items = new ArrayList<>(); switch (mItem.status) { - case CountryItem.STATUS_DOWNLOADABLE: - items.add(MenuItem.DOWNLOAD); - break; + case CountryItem.STATUS_DOWNLOADABLE: + items.add(getDownloadMenuItem()); + break; - case CountryItem.STATUS_UPDATABLE: - items.add(MenuItem.UPDATE); - // No break + case CountryItem.STATUS_UPDATABLE: + items.add(getUpdateMenuItem()); + // Fallthrough - case CountryItem.STATUS_DONE: - if (!mItem.isExpandable()) - items.add(MenuItem.EXPLORE); + case CountryItem.STATUS_DONE: + if (!mItem.isExpandable()) + items.add(getExploreMenuItem()); + items.add(getDeleteMenuItem()); + break; - items.add(MenuItem.DELETE); - break; + case CountryItem.STATUS_FAILED: + items.add(getCancelMenuItem()); - case CountryItem.STATUS_FAILED: - items.add(MenuItem.CANCEL); + if (mItem.present) + { + items.add(getDeleteMenuItem()); + items.add(getExploreMenuItem()); + } + break; - if (mItem.present) - { - items.add(MenuItem.DELETE); - items.add(MenuItem.EXPLORE); - } - break; + case CountryItem.STATUS_PROGRESS: + case CountryItem.STATUS_APPLYING: + case CountryItem.STATUS_ENQUEUED: + items.add(getCancelMenuItem()); - case CountryItem.STATUS_PROGRESS: - case CountryItem.STATUS_APPLYING: - case CountryItem.STATUS_ENQUEUED: - items.add(MenuItem.CANCEL); + if (mItem.present) + items.add(getExploreMenuItem()); + break; - if (mItem.present) - items.add(MenuItem.EXPLORE); - break; - - case CountryItem.STATUS_PARTLY: - items.add(MenuItem.DOWNLOAD); - items.add(MenuItem.DELETE); - break; + case CountryItem.STATUS_PARTLY: + items.add(getDownloadMenuItem()); + items.add(getDeleteMenuItem()); + break; } - - if (items.isEmpty()) - return; - - BottomSheetHelper.Builder bs = BottomSheetHelper.create(mActivity, mItem.name); - for (MenuItem item: items) - bs.sheet(item.ordinal(), item.icon, item.title); - - BottomSheet bottomSheet = bs.listener(new android.view.MenuItem.OnMenuItemClickListener() - { - @Override - public boolean onMenuItemClick(android.view.MenuItem item) - { - MenuItem.values()[item.getItemId()].invoke(mItem, DownloaderAdapter.this); - return false; - } - }).build(); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + return items; } ItemViewHolder(View frame) diff --git a/android/src/com/mapswithme/maps/editor/ProfileFragment.java b/android/src/com/mapswithme/maps/editor/ProfileFragment.java index 8bcb85a75e..7bad8e4283 100644 --- a/android/src/com/mapswithme/maps/editor/ProfileFragment.java +++ b/android/src/com/mapswithme/maps/editor/ProfileFragment.java @@ -1,29 +1,25 @@ package com.mapswithme.maps.editor; -import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.TextView; -import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.StringRes; import androidx.appcompat.app.AlertDialog; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.BuildConfig; import com.mapswithme.maps.R; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.Constants; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import com.mapswithme.util.concurrency.ThreadPool; import com.mapswithme.util.concurrency.UiThread; import java.util.ArrayList; -import java.util.List; public class ProfileFragment extends AuthFragment implements View.OnClickListener { @@ -33,40 +29,18 @@ public class ProfileFragment extends AuthFragment implements View.OnClickListene private View mAuthBlock; private View mRatingBlock; - private enum MenuItem + private void onLogoutActionSelected(final ProfileFragment fragment) { - LOGOUT(R.drawable.ic_logout, R.string.logout) - { - @Override - void invoke(final ProfileFragment fragment) - { - new AlertDialog.Builder(fragment.requireContext()) - .setMessage(R.string.are_you_sure) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() - { - @Override - public void onClick(DialogInterface dialog, int which) - { - OsmOAuth.clearAuthorization(fragment.requireContext()); - fragment.refreshViews(); - } - }) - .setNegativeButton(android.R.string.no, null) - .create() - .show(); - } - }; - - final @DrawableRes int icon; - final @StringRes int title; - - MenuItem(@DrawableRes int icon, @StringRes int title) - { - this.icon = icon; - this.title = title; - } - - abstract void invoke(ProfileFragment fragment); + new AlertDialog.Builder(fragment.requireContext()) + .setMessage(R.string.are_you_sure) + .setPositiveButton(android.R.string.ok, (dialog, which) -> + { + OsmOAuth.clearAuthorization(fragment.requireContext()); + fragment.refreshViews(); + }) + .setNegativeButton(android.R.string.no, null) + .create() + .show(); } @Override @@ -135,23 +109,8 @@ public class ProfileFragment extends AuthFragment implements View.OnClickListene private void showBottomSheet() { - List items = new ArrayList<>(); - items.add(MenuItem.LOGOUT); - - BottomSheetHelper.Builder bs = BottomSheetHelper.create(getActivity()); - for (MenuItem item: items) - bs.sheet(item.ordinal(), item.icon, item.title); - - BottomSheet bottomSheet = bs.listener(new android.view.MenuItem.OnMenuItemClickListener() - { - @Override - public boolean onMenuItemClick(android.view.MenuItem item) - { - MenuItem.values()[item.getItemId()].invoke(ProfileFragment.this); - return false; - } - }).build(); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + ArrayList items = new ArrayList<>(); + items.add(new MenuBottomSheetItem(R.string.logout, R.drawable.ic_logout, () -> onLogoutActionSelected(ProfileFragment.this))); + new MenuBottomSheetFragment(items).show(getParentFragmentManager(), "profileBottomSheet"); } } diff --git a/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java b/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java index 84f5058f86..21200e9eab 100644 --- a/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java +++ b/android/src/com/mapswithme/maps/widget/placepage/PlacePageButtons.java @@ -2,7 +2,6 @@ package com.mapswithme.maps.widget.placepage; import android.content.Context; import android.view.LayoutInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; @@ -12,13 +11,13 @@ import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.StringRes; -import com.cocosw.bottomsheet.BottomSheet; import com.mapswithme.maps.MwmApplication; import com.mapswithme.maps.R; import com.mapswithme.maps.routing.RoutingController; -import com.mapswithme.util.BottomSheetHelper; import com.mapswithme.util.ThemeUtils; import com.mapswithme.util.UiUtils; +import com.mapswithme.util.bottomsheet.MenuBottomSheetFragment; +import com.mapswithme.util.bottomsheet.MenuBottomSheetItem; import java.util.ArrayList; import java.util.Collections; @@ -309,27 +308,22 @@ public final class PlacePageButtons } } - private void showPopup(final List buttons) + private ArrayList getMenuItems(final List buttons) { - BottomSheetHelper.Builder bs = new BottomSheetHelper.Builder(mPlacePage.getActivity()); + ArrayList items = new ArrayList<>(); for (int i = mMaxButtons; i < buttons.size(); i++) { PlacePageButton bsItem = buttons.get(i); int iconRes = bsItem.getIcon().getEnabledStateResId(mPlacePage.getContext()); - bs.sheet(i, iconRes, bsItem.getTitle()); + items.add(new MenuBottomSheetItem(bsItem.getTitle(), iconRes, () -> mItemListener.onItemClick(bsItem))); } + return items; + } - BottomSheet bottomSheet = bs.listener(new MenuItem.OnMenuItemClickListener() - { - @Override - public boolean onMenuItemClick(MenuItem item) - { - mItemListener.onItemClick(buttons.get(item.getItemId())); - return true; - } - }).build(); - BottomSheetHelper.tint(bottomSheet); - bottomSheet.show(); + private void showPopup(final List buttons) + { + new MenuBottomSheetFragment(getMenuItems(buttons)) + .show(mPlacePage.getActivity().getSupportFragmentManager(), "moreBottomSheet"); } private View createButton(@NonNull final List items, diff --git a/android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java b/android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java new file mode 100644 index 0000000000..622d0252ab --- /dev/null +++ b/android/src/com/mapswithme/util/bottomsheet/MenuAdapter.java @@ -0,0 +1,106 @@ +package com.mapswithme.util.bottomsheet; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.mapswithme.maps.R; + +import java.util.ArrayList; + +public class MenuAdapter extends RecyclerView.Adapter +{ + private final ArrayList dataSet; + @Nullable + private final MenuBottomSheetItem.OnClickListener onClickListener; + + public MenuAdapter(ArrayList dataSet, @Nullable MenuBottomSheetItem.OnClickListener onClickListener) + { + this.dataSet = dataSet; + this.onClickListener = onClickListener; + } + + private void onMenuItemClick(MenuBottomSheetItem item) + { + if (onClickListener != null) + onClickListener.onClick(); + item.onClickListener.onClick(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) + { + View view = LayoutInflater.from(viewGroup.getContext()) + .inflate(R.layout.bottom_sheet_menu_item, viewGroup, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder viewHolder, final int position) + { + final MenuBottomSheetItem item = dataSet.get(position); + viewHolder.getContainer().setOnClickListener((v) -> onMenuItemClick(item)); + viewHolder.getIconImageView().setImageResource(item.iconRes); + viewHolder.getTitleTextView().setText(item.titleRes); + TextView badge = viewHolder.getBadgeTextView(); + if (item.badgeCount > 0) + { + badge.setText(String.valueOf(item.badgeCount)); + badge.setVisibility(View.VISIBLE); + } else { + badge.setVisibility(View.GONE); + } + } + + @Override + public int getItemCount() + { + return dataSet.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder + { + private final LinearLayout container; + private final ImageView iconImageView; + private final TextView titleTextView; + private final TextView badgeTextView; + + public ViewHolder(View view) + { + super(view); + container = view.findViewById(R.id.bottom_sheet_menu_item); + iconImageView = view.findViewById(R.id.bottom_sheet_menu_item_icon); + titleTextView = view.findViewById(R.id.bottom_sheet_menu_item_text); + badgeTextView = view.findViewById(R.id.bottom_sheet_menu_item_badge); + } + + public ImageView getIconImageView() + { + return iconImageView; + } + + public TextView getTitleTextView() + { + return titleTextView; + } + + public TextView getBadgeTextView() + { + return badgeTextView; + } + + public LinearLayout getContainer() + { + return container; + } + } + +} diff --git a/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java new file mode 100644 index 0000000000..602fa85bbb --- /dev/null +++ b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetFragment.java @@ -0,0 +1,79 @@ +package com.mapswithme.util.bottomsheet; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; +import com.mapswithme.maps.R; + +import java.util.ArrayList; + +public class MenuBottomSheetFragment extends BottomSheetDialogFragment +{ + @Nullable + private final String title; + private final ArrayList menuBottomSheetItems; + + public MenuBottomSheetFragment(@NonNull String title, ArrayList menuBottomSheetItems) + { + this.title = title; + this.menuBottomSheetItems = menuBottomSheetItems; + } + + public MenuBottomSheetFragment(ArrayList menuBottomSheetItems) + { + this.title = null; + this.menuBottomSheetItems = menuBottomSheetItems; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) + { + return inflater.inflate(R.layout.bottom_sheet, container); + } + + @Override + public void onStart() + { + super.onStart(); + BottomSheetBehavior behavior = BottomSheetBehavior.from((View) requireView().getParent()); + // By default sheets in landscape start at their peek height. + // We fix this by forcing the expanded state and disabling the collapsed one + behavior.setState(BottomSheetBehavior.STATE_EXPANDED); + behavior.setSkipCollapsed(true); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) + { + super.onViewCreated(view, savedInstanceState); + TextView titleView = view.findViewById(R.id.bottomSheetTitle); + RecyclerView recyclerView = view.findViewById(R.id.bottomSheetMenuContainer); + if (title != null) + { + titleView.setVisibility(View.VISIBLE); + titleView.setText(title); + } else + titleView.setVisibility(View.GONE); + + MenuAdapter menuAdapter = new MenuAdapter(menuBottomSheetItems, this::dismiss); + recyclerView.setAdapter(menuAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity())); + } +} diff --git a/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java new file mode 100644 index 0000000000..3d8c5e9f60 --- /dev/null +++ b/android/src/com/mapswithme/util/bottomsheet/MenuBottomSheetItem.java @@ -0,0 +1,30 @@ +package com.mapswithme.util.bottomsheet; + +public class MenuBottomSheetItem +{ + public final int titleRes; + public final int iconRes; + public final int badgeCount; + public final OnClickListener onClickListener; + + public MenuBottomSheetItem(int titleRes, int iconRes, OnClickListener onClickListener) + { + this.titleRes = titleRes; + this.iconRes = iconRes; + this.badgeCount = 0; + this.onClickListener = onClickListener; + } + + public MenuBottomSheetItem(int titleRes, int iconRes, int badgeCount, OnClickListener onClickListener) + { + this.titleRes = titleRes; + this.iconRes = iconRes; + this.badgeCount = badgeCount; + this.onClickListener = onClickListener; + } + + public interface OnClickListener + { + void onClick(); + } +}