From c64cfdd8fa18de45fc1646c8ef2449f39ef83022 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 18 May 2016 14:12:02 -0700 Subject: [PATCH] Updating the folder page indicator to be more like the framework page indicator (used in quick settings) The active page is indicated with the accent color. During scroll the active indicator expands to 2 dots corresponding to the visible pages. Change-Id: Iaf57836b642cf87e5eed98048ecca7dd8e7643a4 --- res/drawable-hdpi/ic_pageindicator_add.png | Bin 390 -> 0 bytes .../ic_pageindicator_current.png | Bin 468 -> 0 bytes .../ic_pageindicator_current_folder.png | Bin 210 -> 0 bytes res/drawable-mdpi/ic_pageindicator_add.png | Bin 236 -> 0 bytes .../ic_pageindicator_current.png | Bin 277 -> 0 bytes .../ic_pageindicator_current_folder.png | Bin 160 -> 0 bytes res/drawable-xhdpi/ic_pageindicator_add.png | Bin 565 -> 0 bytes .../ic_pageindicator_current.png | Bin 677 -> 0 bytes .../ic_pageindicator_current_folder.png | Bin 293 -> 0 bytes res/drawable-xxhdpi/ic_pageindicator_add.png | Bin 849 -> 0 bytes .../ic_pageindicator_current.png | Bin 1079 -> 0 bytes .../ic_pageindicator_current_folder.png | Bin 432 -> 0 bytes res/layout/page_indicator.xml | 21 - res/layout/page_indicator_marker.xml | 39 -- res/layout/user_folder.xml | 9 +- res/layout/user_folder_icon_normalized.xml | 9 +- res/values/attrs.xml | 5 - res/values/colors.xml | 1 + res/values/dimens.xml | 1 + src/com/android/launcher3/PagedView.java | 30 +- src/com/android/launcher3/Workspace.java | 21 +- src/com/android/launcher3/folder/Folder.java | 9 +- .../launcher3/folder/FolderPagedView.java | 52 +- .../pageindicators/PageIndicator.java | 23 +- .../pageindicators/PageIndicatorDot.java | 105 ---- .../pageindicators/PageIndicatorDots.java | 453 +++++++++++------- .../pageindicators/PageIndicatorLine.java | 41 +- 27 files changed, 341 insertions(+), 478 deletions(-) delete mode 100644 res/drawable-hdpi/ic_pageindicator_add.png delete mode 100644 res/drawable-hdpi/ic_pageindicator_current.png delete mode 100644 res/drawable-hdpi/ic_pageindicator_current_folder.png delete mode 100644 res/drawable-mdpi/ic_pageindicator_add.png delete mode 100644 res/drawable-mdpi/ic_pageindicator_current.png delete mode 100644 res/drawable-mdpi/ic_pageindicator_current_folder.png delete mode 100644 res/drawable-xhdpi/ic_pageindicator_add.png delete mode 100644 res/drawable-xhdpi/ic_pageindicator_current.png delete mode 100644 res/drawable-xhdpi/ic_pageindicator_current_folder.png delete mode 100644 res/drawable-xxhdpi/ic_pageindicator_add.png delete mode 100644 res/drawable-xxhdpi/ic_pageindicator_current.png delete mode 100644 res/drawable-xxhdpi/ic_pageindicator_current_folder.png delete mode 100644 res/layout/page_indicator.xml delete mode 100644 res/layout/page_indicator_marker.xml delete mode 100644 src/com/android/launcher3/pageindicators/PageIndicatorDot.java diff --git a/res/drawable-hdpi/ic_pageindicator_add.png b/res/drawable-hdpi/ic_pageindicator_add.png deleted file mode 100644 index 6e3f5aff68d40eb4c2d9612fc5381b1215e253a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 390 zcmV;10eSw3P)zE_g!} z`TG^c05E>Krr)PsKsq#12WF=+Qzj{ll;m6SmGl;OA=&`cJLyvQ|QcT zL5PRV)wY5Fcz__tHTt+*E5$inBJjrD2gLzS!9dVMZC7_#(|$oLhIEKWw4c}EXuAQ1 z!~ifwG5oq)X>D4ZlqOAyODfXhv?_Uaxd-epP^bsctRQ=xyi4D@MqKtTd7Hh--@S8C z=f1}$qHWZL?)0pBQP*&MESavR?@MZ;O@_Qa<7=Hf_wJ*}9OCw-~kMKKv6bsti-SqIl?r!KL`+I@|!cXnr k|6pyjHST2y|3&zTRyQ(Tgtwj$TmS$707*qoM6N<$g61l<<^TWy diff --git a/res/drawable-hdpi/ic_pageindicator_current.png b/res/drawable-hdpi/ic_pageindicator_current.png deleted file mode 100644 index 6dbc4f9640ec04996410303a6ef8ea295aa75474..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 468 zcmV;_0W1EAP)yZ(3GPyQU- zLvz(C4avR05Jom=h}VnzKikI6aLlFspI$G9;2z0@kQ;c~?@K}f+eA~*B*$E8n^55U z5^%4OSfIucXy6?qiKwY?!Zri%K;vn?!UY2U9puIo$7*xSzk|pUr!>&@$ZiPPrt2Ya zTH`2hy7xmfsP{d@F^v-%vgcznsOKXj6PGj)c|ro;TboBMlE+kYEki3HqwmI z7%9eLGA466a>nS5RPj|%_zUyY3D=g9D@Lyvy=CMH*F05Ni1i=8XFF6xxFoLt0000< KMNUMnLSTYbc;lM@ diff --git a/res/drawable-hdpi/ic_pageindicator_current_folder.png b/res/drawable-hdpi/ic_pageindicator_current_folder.png deleted file mode 100644 index c6c4228c04aaba6a9e0da3a531f03f57768cd1c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210 zcmV;@04@KCP)g07b4p5;LA_M! z6Ve5a9F$!`*Uk+Yu#~Z5tL*Y9rGLdpl}m|hD7rPq5%bGuV)qlk|7ANuW*s;opO(P?|q-HG2hI6J{&3w z0?S#~gU4;o3-|L$`}NRv9;_;Wi1k@`?|03^n47(~zAZ@1z4BDh5yDh>sQhHFGKyu!`6d&S`eD7d@-f^%kdWZy{;8L ziIrlBGTX@qod+G;$&sc+Vg<+*)NuIu)SY$ze*b=FolgyiqZ~KJAQ$8J*4@je?yZY4 zB-Q}C$#<@8x%zzVCWC^&Xb*q!I1VUyQ~cx8QLwjWf#-L?avV@uk~n`gFT$(kh*y!T z`Na8bQNi%oQ+cwYv=%K&pR9CO@)!t^B+1%0*qgW2zt!)}^9@eZiNYs?s=}a*7(tbp b0R>7Fi*Ar*|Z0Y@2`6?j<8669yB z+7|Y;viWNDQQIT79rg}RoeTjJ0;j%{l=;!Kea`G9g-6BZ_vxFy-J@5q=y9X^{pMRI zSx@Nns-Lu7E@_{9opoFHfh|{SDk8pLTRWR?%R7hJd~<3~^6zl!I}@^>uN`P5gQu&X J%Q~loCICR5JhcD- diff --git a/res/drawable-xhdpi/ic_pageindicator_add.png b/res/drawable-xhdpi/ic_pageindicator_add.png deleted file mode 100644 index 7e18c053bfc4dfda348ca262a9e413a262f6f4d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 565 zcmV-50?Pe~P)?o3e_+dgo z1FQzC!}2ju8duVBFmSMc(6j~0b-buG*gwo)Q@}7Bfuz~LwF#WB`01>?`?MD@T7ZG1 zwOHOlfSjr;zu4;01Yn34M#>5S)o_^Az2JKq$e68eP6XQfVS<5bNJ5PW3fkQ0;c4RQ z9D;XyGiQWr)4&Hr8~D3>IvSvykOT^GyE6co&VhrqKWX8?SYWyN=RZ%lU)pSH0B6fQ z=yJXN)y`+z-kvJI+Um*5qb;v?z1HDgr)yQgN^lPa`PYAi0NyN&DO(3^C0*>_e6!Vu z^*}ExFH0aS)xz^RQhj{;QP(Hw2%kQG{GeanN%eLe(8J1;PzZCFt@HFP+pa>FDuv5z z>LI_x)S1~R)~i~(3cbp9$`4C0N)s>IL;yLFFIot>H?($znFtjwf_%t@Agsh2OAG=Q z7CHUFaLHTxCKc)W{QzL<124MzoOhLc0f7%?o3DBl%gM!xW%>02U0;)GoVL zT3aCd8aN}|m<){eAkFJXK)aYA2kJ>_tJ~v&agIRJ6!LTMfq6DJ+uC|@G4S#{js6KP zi5EeQ52h23BXF$*&GP>8fqVkYNF$zb$LJr3OV;Wa4F#d8h-=-J00000NkvXXu0mjf Dze)~g diff --git a/res/drawable-xhdpi/ic_pageindicator_current.png b/res/drawable-xhdpi/ic_pageindicator_current.png deleted file mode 100644 index 866725fbb4b1f52b90d2c7841e795d00a8bc0fd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 677 zcmV;W0$TlvP)>vD^$;(1{=ddcaz4x&%1Mkp6=cN-4xNbA$na z&8XZ{y}No^B^WTmm}WvyN(vMLq5_AQY;(5Ae6})pJo+>dOax<3gU6n(oNo#?$%Y`D z5U7|r3}X<165!^f$Sp@Y?Ma!5s^!SYt(%hoH7i)|V1y|66dQQCFcEWPvNhR~Y)iJQ z*rr;oj!eW}E(8=pC?o+W_+%6G@sxPjkqRO^#1==!!;dF}Dij9=s8?_UR^-~h@Q#$o zRhXLL6=?!nZUS#ss)@Fw>?W$2H!A>zWGE9eERf$v)2Hv2pl`Saf%YsFSV&YLr5QKf-n5C zrz3@5jPqrVR4N)w=wD8!ie5S;znp?TD}8D3H3sO74Lv>U&Gn$G4RC<@1hY~7>rS_O zsP%u{hM(I$0hX6W$$>essM1YGiW+fbEP7xLO7hakh;MiqDlV;$$5S#Rx%O;K%P=Kl z@r&zFF{~^jzJk29fmLwroBQ)&N;axT%tX~n$)6AQ&V_4`3tB zXh$bto5Nkze)v(XqQAyJ!eyHsoj^x7!!6xqd2EmEvMe3Eqnr5)iai>u<4A#W00000 LNkvXXu0mjf^*=Qr diff --git a/res/drawable-xhdpi/ic_pageindicator_current_folder.png b/res/drawable-xhdpi/ic_pageindicator_current_folder.png deleted file mode 100644 index ec19b7c345c560c6f515053730507846216c01e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 293 zcmV+=0owkFP)|74qiB##~ zaP-n!rxILga?1;zAwxVb+$xV!6#d|kFN776x}H8c)Za4d=S&fnEGSt0^@0UUgem6= zVZl!sBP3=^YXqMO?{92)f7|f333SIR ro)IHFFWlt>T0ceGboNmM)-N-^Sb6~n0GC+)00000NkvXXu0mjf_MUms diff --git a/res/drawable-xxhdpi/ic_pageindicator_add.png b/res/drawable-xxhdpi/ic_pageindicator_add.png deleted file mode 100644 index d790e86b2591e061c7adbfcd9b998b614c172b23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 849 zcmV-X1FrmuP)-5XbRv_spIoGcz+Yb7G2LYPQ4o&zRW`%@8^7xb_@c)V6y%jo!jV%lh5JG(83c5)FY^&M^rm07JP` zplxQqapM+S4!&n(BX=9x@0kh!-*xjVw`>+hk=e9tp}M)^_vf|5FffEV2;djzTSvd# zkdM%W1b_v;Puf}{%A5Mr9btsIK7V@kSwEcSkF|4sc0z9E;D_6>HZwZ}MoNd#9ot(4 z$#9})W;@`UBt%OIp=rzj5TH#;!t%T&@^Vmpb6wuOA(9Nh*#6vVKZ(&dckz8)NhXUV z`|*h(_H_`m({Nf23;cyskuV&=x3_G%O43i4oqhZ3Y(x+QHHAeA1+7rZo%v}Mbvb&Q zSeWGS@Z=L)z?J~;Q?`9$r@S<5EIbA!P2T?FuaZ>M*P3df7yqIrW7uLI*^*fRfW~k9 zxpn!mMihdYhEh74Z=N|Hf`TX{9Ixt8iqt|I)r=Q4osdC;TBci3+ukx%FuY2ns7wH` z7}OiH0tG@u%XFbGWdx1}fO#9vg|e~JtPpCE-v1E*){;pmM4>@6E>wy3Y4dxb?s+O$ z5DKMDECX9E8D*2)f4cQU)2fCdTz@_ilL&tQ;aB{RKx=Y}fMJ-SZ&c^va~ZQJ(qTCZ!{W7{*$)m7Ctv#Han>HXdQ-P-#4qJ#g< z`I2)2tsVuHl2WC#R+4Slr=Vg_K?qLM!9Woy1Epho+ps1G4mA`xozgLUwYARKfUAPU-Hr9NVWNDsap9BThc%8T?X0+?lIhg zrU0AQgF(5h8wYyvJ~>h3>+^L|^#~J}{a=0YUZCB$BT-6hO%VpS+Bf@hAmuLw4UjNVR|r&zxrU(@O4>nA$clh>Dymxv#S}&2lBG354z_#t;tL?q&H9 z0}yQs#{|2Uf;NOJMx#@ZigwE|37hZzy%PtCA|yxsyxKmpwii%<&9CQKnJa#{;+g+n_!XsJ`MGaQk_bVzxD;$S{Xn z-(3|X3M~-dU1?jxoTe1Pq}7?$Zg9WK{bA8b8;Z)k{rYL`G}e@~SdA3Y-G}z?uFn-+ zMsnf1>!E#jUm?&4QZP7!TYWpLUG_a47FF0nvF~ZMOW)4iLW~+OwUl{oH|TxrRdlM5 zSJ)SdW3NDOw;S_-#!GEO@z;To4rUMNyYK0IO<1t_%buFOPeC8ngLD9<=&=hab{$!y zliM45ytA=#Zy-XvesZkHB*o%}w~qy5mYt}Fc^ zT@tzRk5uGbx}@~`udZu96neDlV{`&LenI~C$|hjz9sHgkVbJrA1)p5G?F2Lo|4^H9;5D62V@~-*YdgN@r8lKZ57__!002ovPDHLkV1nts6ZZfB diff --git a/res/drawable-xxhdpi/ic_pageindicator_current_folder.png b/res/drawable-xxhdpi/ic_pageindicator_current_folder.png deleted file mode 100644 index 987c882aea04b5518c38e284d3e371f318844142..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 432 zcmV;h0Z;ykP)c?DtGoI2yQS;@7)ho?}uL^%3o{# aE4c@Zi%#$T0q!sW0000 - - - diff --git a/res/layout/page_indicator_marker.xml b/res/layout/page_indicator_marker.xml deleted file mode 100644 index 357a76186d..0000000000 --- a/res/layout/page_indicator_marker.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml index 87a42145d8..8a1b7d0f3b 100644 --- a/res/layout/user_folder.xml +++ b/res/layout/user_folder.xml @@ -72,12 +72,13 @@ android:textColorHint="#ff808080" android:textSize="14sp" /> - + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:elevation="1dp" + /> diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml index d445a7ae38..de1316ebbf 100644 --- a/res/layout/user_folder_icon_normalized.xml +++ b/res/layout/user_folder_icon_normalized.xml @@ -73,12 +73,13 @@ android:textColorHint="#ff808080" android:textSize="14sp" /> - + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:elevation="1dp" + /> diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 2eb9b910f1..ca28ad35fb 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -31,11 +31,6 @@ - - - - - diff --git a/res/values/colors.xml b/res/values/colors.xml index dc3d4fa849..754dc0c57f 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -31,6 +31,7 @@ #FFFFFFFF #FF757575 + #FFDDDDDD #FF666666 #FFF5F5F5 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 281de08ae7..6fac31e1ca 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -149,6 +149,7 @@ 6dp + 8dp 24dp diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 02e894b7ff..86a1a397c2 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -255,14 +255,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc ViewGroup grandParent = (ViewGroup) parent.getParent(); if (mPageIndicator == null && mPageIndicatorViewId > -1) { mPageIndicator = (PageIndicator) grandParent.findViewById(mPageIndicatorViewId); - mPageIndicator.removeAllMarkers(true); - - ArrayList markers = new ArrayList<>(); - for (int i = 0; i < getChildCount(); ++i) { - markers.add(getPageIndicatorMarker(i)); - } - - mPageIndicator.addMarkers(markers, true); + mPageIndicator.setMarkersCount(getChildCount()); OnClickListener listener = getPageIndicatorClickListener(); if (listener != null) { @@ -356,10 +349,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc PageIndicator getPageIndicator() { return mPageIndicator; } - protected PageIndicator.PageMarkerResources getPageIndicatorMarker(int pageIndex) { - return new PageIndicator.PageMarkerResources(R.drawable.ic_pageindicator_current, - R.drawable.ic_pageindicator_default); - } /** * Returns the index of the currently displayed page. When in free scroll mode, this is the page @@ -962,10 +951,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // Update the page indicator, we don't update the page indicator as we // add/remove pages if (mPageIndicator != null && !isReordering(false)) { - int pageIndex = indexOfChild(child); - mPageIndicator.addMarker(pageIndex, - getPageIndicatorMarker(pageIndex), - true); + mPageIndicator.addMarker(); } // This ensures that when children are added, they get the correct transforms / alphas @@ -982,11 +968,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc invalidate(); } - private void removeMarkerForView(int index) { + private void removeMarkerForView() { // Update the page indicator, we don't update the page indicator as we // add/remove pages if (mPageIndicator != null && !isReordering(false)) { - mPageIndicator.removeMarker(index, true); + mPageIndicator.removeMarker(); } } @@ -994,21 +980,21 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc public void removeView(View v) { // XXX: We should find a better way to hook into this before the view // gets removed form its parent... - removeMarkerForView(indexOfChild(v)); + removeMarkerForView(); super.removeView(v); } @Override public void removeViewInLayout(View v) { // XXX: We should find a better way to hook into this before the view // gets removed form its parent... - removeMarkerForView(indexOfChild(v)); + removeMarkerForView(); super.removeViewInLayout(v); } @Override public void removeViewAt(int index) { // XXX: We should find a better way to hook into this before the view // gets removed form its parent... - removeMarkerForView(index); + removeMarkerForView(); super.removeViewAt(index); } @Override @@ -1016,7 +1002,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // Update the page indicator, we don't update the page indicator as we // add/remove pages if (mPageIndicator != null) { - mPageIndicator.removeAllMarkers(true); + mPageIndicator.setMarkersCount(0); } super.removeAllViewsInLayout(); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 386e01634e..f8eff6987a 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -809,11 +809,6 @@ public class Workspace extends PagedView mWorkspaceScreens.put(newId, cl); mScreenOrder.add(newId); - // Update the page indicator marker - if (getPageIndicator() != null) { - getPageIndicator().updateMarker(index, getPageIndicatorMarker(index)); - } - // Update the model for the new screen mLauncher.getModel().updateWorkspaceScreenOrder(mLauncher, mScreenOrder); @@ -1286,7 +1281,7 @@ public class Workspace extends PagedView } private void showPageIndicatorAtCurrentScroll() { - mPageIndicator.setProgress((float) getScrollX() / computeMaxScrollX()); + mPageIndicator.setScroll(getScrollX(), computeMaxScrollX()); } @Override @@ -4265,20 +4260,6 @@ public class Workspace extends PagedView exitWidgetResizeMode(); } - @Override - protected PageIndicator.PageMarkerResources getPageIndicatorMarker(int pageIndex) { - long screenId = getScreenIdForPageIndex(pageIndex); - if (screenId == EXTRA_EMPTY_SCREEN_ID) { - int count = mScreenOrder.size() - numCustomPages(); - if (count > 1) { - return new PageIndicator.PageMarkerResources(R.drawable.ic_pageindicator_current, - R.drawable.ic_pageindicator_add); - } - } - - return super.getPageIndicatorMarker(pageIndex); - } - protected String getPageIndicatorDescription() { String settings = getResources().getString(R.string.settings_button_text); return getCurrentPageDescription() + ", " + settings; diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 1ebe8fdfbc..6df296e7da 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -78,6 +78,7 @@ import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.logging.UserEventDispatcher.LaunchSourceProvider; +import com.android.launcher3.pageindicators.PageIndicatorDots; import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; import com.android.launcher3.util.Thunk; @@ -148,6 +149,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList @Thunk FolderPagedView mContent; @Thunk View mContentWrapper; public ExtendedEditText mFolderName; + private PageIndicatorDots mPageIndicator; private View mFooter; private int mFooterHeight; @@ -228,6 +230,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mContent = (FolderPagedView) findViewById(R.id.folder_content); mContent.setFolder(this); + mPageIndicator = (PageIndicatorDots) findViewById(R.id.folder_page_indicator); mFolderName = (ExtendedEditText) findViewById(R.id.folder_name); mFolderName.setOnBackKeyListener(new ExtendedEditText.OnBackKeyListener() { @Override @@ -612,7 +615,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList float textWidth = mFolderName.getPaint().measureText(mFolderName.getText().toString()); float translation = (footerWidth - textWidth) / 2; mFolderName.setTranslationX(mContent.mIsRtl ? -translation : translation); - mContent.setMarkerScale(0); + mPageIndicator.prepareEntryAnimation(); // Do not update the flag if we are in drag mode. The flag will be updated, when we // actually drop the icon. @@ -628,7 +631,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList AnimationUtils.loadInterpolator(mLauncher, android.R.interpolator.fast_out_slow_in) : new LogDecelerateInterpolator(100, 0)); - mContent.animateMarkers(); + mPageIndicator.playEntryAnimation(); if (updateAnimationFlag) { mInfo.setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, mLauncher); @@ -637,9 +640,9 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList }); } else { mFolderName.setTranslationX(0); - mContent.setMarkerScale(1); } + mPageIndicator.stopAllAnimations(); openFolderAnim.start(); // Make sure the folder picks up the last drag move even if the finger doesn't move. diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index e1a1431653..bb8ca160de 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -25,8 +25,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewDebug; import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.OvershootInterpolator; import com.android.launcher3.BubbleTextView; import com.android.launcher3.CellLayout; @@ -39,8 +37,6 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; -import com.android.launcher3.pageindicators.PageIndicatorDots; -import com.android.launcher3.pageindicators.PageIndicator.PageMarkerResources; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.ShortcutAndWidgetContainer; @@ -48,6 +44,7 @@ import com.android.launcher3.ShortcutInfo; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace.ItemOperator; import com.android.launcher3.dragndrop.DragController; +import com.android.launcher3.pageindicators.PageIndicator; import com.android.launcher3.util.Thunk; import java.util.ArrayList; @@ -65,13 +62,6 @@ public class FolderPagedView extends PagedView { private static final int START_VIEW_REORDER_DELAY = 30; private static final float VIEW_REORDER_DELAY_FACTOR = 0.9f; - private static final int PAGE_INDICATOR_ANIMATION_START_DELAY = 300; - private static final int PAGE_INDICATOR_ANIMATION_STAGGERED_DELAY = 150; - private static final int PAGE_INDICATOR_ANIMATION_DURATION = 400; - - // This value approximately overshoots to 1.5 times the original size. - private static final float PAGE_INDICATOR_OVERSHOOT_TENSION = 4.9f; - /** * Fraction of the width to scroll when showing the next page hint. */ @@ -103,7 +93,7 @@ public class FolderPagedView extends PagedView { private FocusIndicatorView mFocusIndicatorView; private PagedFolderKeyEventListener mKeyListener; - private PageIndicatorDots mPageIndicator; + private PageIndicator mPageIndicator; public FolderPagedView(Context context, AttributeSet attrs) { super(context, attrs); @@ -128,7 +118,7 @@ public class FolderPagedView extends PagedView { mFolder = folder; mFocusIndicatorView = (FocusIndicatorView) folder.findViewById(R.id.focus_indicator); mKeyListener = new PagedFolderKeyEventListener(folder); - mPageIndicator = (PageIndicatorDots) folder.findViewById(R.id.folder_page_indicator); + mPageIndicator = (PageIndicator) folder.findViewById(R.id.folder_page_indicator); } /** @@ -285,6 +275,12 @@ public class FolderPagedView extends PagedView { } } + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + mPageIndicator.setScroll(l, mMaxScrollX); + } + /** * Updates position and rank of all the children in the view. * It essentially removes all views from all the pages and then adds them again in appropriate @@ -369,7 +365,7 @@ public class FolderPagedView extends PagedView { setEnableOverscroll(getPageCount() > 1); // Update footer - mPageIndicator.setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE); + mPageIndicator.getView().setVisibility(getPageCount() > 1 ? View.VISIBLE : View.GONE); // Set the gravity as LEFT or RIGHT instead of START, as START depends on the actual text. mFolder.mFolderName.setGravity(getPageCount() > 1 ? (mIsRtl ? Gravity.RIGHT : Gravity.LEFT) : Gravity.CENTER_HORIZONTAL); @@ -409,12 +405,6 @@ public class FolderPagedView extends PagedView { pageIndex * mMaxItemsPerPage + sTempPosArray[1] * mGridCountX + sTempPosArray[0]); } - @Override - protected PageMarkerResources getPageIndicatorMarker(int pageIndex) { - return new PageMarkerResources(R.drawable.ic_pageindicator_current_folder, - R.drawable.ic_pageindicator_default_folder); - } - public boolean isFull() { return !ALLOW_FOLDER_SCROLL && getItemCount() >= mMaxItemsPerPage; } @@ -676,28 +666,6 @@ public class FolderPagedView extends PagedView { } } - public void setMarkerScale(float scale) { - int count = mPageIndicator.getChildCount(); - for (int i = 0; i < count; i++) { - View marker = mPageIndicator.getChildAt(i); - marker.animate().cancel(); - marker.setScaleX(scale); - marker.setScaleY(scale); - } - } - - public void animateMarkers() { - int count = mPageIndicator.getChildCount(); - Interpolator interpolator = new OvershootInterpolator(PAGE_INDICATOR_OVERSHOOT_TENSION); - for (int i = 0; i < count; i++) { - mPageIndicator.getChildAt(i).animate().scaleX(1).scaleY(1) - .setInterpolator(interpolator) - .setDuration(PAGE_INDICATOR_ANIMATION_DURATION) - .setStartDelay(PAGE_INDICATOR_ANIMATION_STAGGERED_DELAY * i - + PAGE_INDICATOR_ANIMATION_START_DELAY); - } - } - public int itemsPerPage() { return mMaxItemsPerPage; } diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java index 6348b123b5..77c579c93d 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicator.java +++ b/src/com/android/launcher3/pageindicators/PageIndicator.java @@ -6,26 +6,11 @@ import java.util.ArrayList; public interface PageIndicator { View getView(); - void setProgress(float progress); + void setScroll(int currentScroll, int totalScroll); - void removeAllMarkers(boolean allowAnimations); - void addMarkers(ArrayList markers, boolean allowAnimations); void setActiveMarker(int activePage); - void addMarker(int pageIndex, PageMarkerResources pageIndicatorMarker, boolean allowAnimations); - void removeMarker(int pageIndex, boolean allowAnimations); - void updateMarker(int pageIndex, PageMarkerResources pageIndicatorMarker); - /** - * Contains two resource ids for each page indicator marker (e.g. dots): - * one for when the page is active and one for when the page is inactive. - */ - class PageMarkerResources { - int activeId; - int inactiveId; - - public PageMarkerResources(int aId, int iaId) { - activeId = aId; - inactiveId = iaId; - } - } + void addMarker(); + void removeMarker(); + void setMarkersCount(int numMarkers); } diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDot.java b/src/com/android/launcher3/pageindicators/PageIndicatorDot.java deleted file mode 100644 index 5ed3426952..0000000000 --- a/src/com/android/launcher3/pageindicators/PageIndicatorDot.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * 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.android.launcher3.pageindicators; - -import android.content.Context; -import android.content.res.Resources; -import android.util.AttributeSet; -import android.widget.FrameLayout; -import android.widget.ImageView; - -import com.android.launcher3.R; - -public class PageIndicatorDot extends FrameLayout { - @SuppressWarnings("unused") - private static final String TAG = "PageIndicator"; - - private static final int MARKER_FADE_DURATION = 175; - - private ImageView mActiveMarker; - private ImageView mInactiveMarker; - private boolean mIsActive = false; - - public PageIndicatorDot(Context context) { - this(context, null); - } - - public PageIndicatorDot(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public PageIndicatorDot(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - protected void onFinishInflate() { - super.onFinishInflate(); - mActiveMarker = (ImageView) findViewById(R.id.active); - mInactiveMarker = (ImageView) findViewById(R.id.inactive); - } - - void setMarkerDrawables(int activeResId, int inactiveResId) { - Resources r = getResources(); - mActiveMarker.setImageDrawable(r.getDrawable(activeResId)); - mInactiveMarker.setImageDrawable(r.getDrawable(inactiveResId)); - } - - void activate(boolean immediate) { - if (immediate) { - mActiveMarker.animate().cancel(); - mActiveMarker.setAlpha(1f); - mActiveMarker.setScaleX(1f); - mActiveMarker.setScaleY(1f); - mInactiveMarker.animate().cancel(); - mInactiveMarker.setAlpha(0f); - } else { - mActiveMarker.animate() - .alpha(1f) - .scaleX(1f) - .scaleY(1f) - .setDuration(MARKER_FADE_DURATION).start(); - mInactiveMarker.animate() - .alpha(0f) - .setDuration(MARKER_FADE_DURATION).start(); - } - mIsActive = true; - } - - void inactivate(boolean immediate) { - if (immediate) { - mInactiveMarker.animate().cancel(); - mInactiveMarker.setAlpha(1f); - mActiveMarker.animate().cancel(); - mActiveMarker.setAlpha(0f); - mActiveMarker.setScaleX(0.5f); - mActiveMarker.setScaleY(0.5f); - } else { - mInactiveMarker.animate().alpha(1f) - .setDuration(MARKER_FADE_DURATION).start(); - mActiveMarker.animate() - .alpha(0f) - .scaleX(0.5f) - .scaleY(0.5f) - .setDuration(MARKER_FADE_DURATION).start(); - } - mIsActive = false; - } - - boolean isActive() { - return mIsActive; - } -} diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java index a488f028a6..4a1238ddd7 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,32 +16,97 @@ package com.android.launcher3.pageindicators; -import android.animation.LayoutTransition; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; -import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.view.animation.Interpolator; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.RectF; import android.util.AttributeSet; -import android.view.LayoutInflater; +import android.util.Property; import android.view.View; -import android.view.ViewDebug; -import android.widget.LinearLayout; +import android.view.ViewOutlineProvider; +import android.view.animation.OvershootInterpolator; import com.android.launcher3.R; +import com.android.launcher3.Utilities; -import java.util.ArrayList; +/** + * {@link PageIndicator} which shows dots per page. The active page is shown with the current + * accent color. + */ +public class PageIndicatorDots extends View implements PageIndicator { -public class PageIndicatorDots extends LinearLayout implements PageIndicator { - @SuppressWarnings("unused") - private static final String TAG = "PageIndicator"; - // Want this to look good? Keep it odd - private static final boolean MODULATE_ALPHA_ENABLED = false; + private static final float SHIFT_PER_ANIMATION = 0.5f; + private static final float SHIFT_THRESHOLD = 0.1f; + private static final long ANIMATION_DURATION = 150; - private LayoutInflater mLayoutInflater; - private int[] mWindowRange = new int[2]; - private int mMaxWindowSize; + private static final int ENTER_ANIMATION_START_DELAY = 300; + private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150; + private static final int ENTER_ANIMATION_DURATION = 400; - private ArrayList mMarkers = new ArrayList<>(); - @ViewDebug.ExportedProperty(category = "launcher") - private int mActiveMarkerIndex; + // This value approximately overshoots to 1.5 times the original size. + private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f; + + private static final RectF sTempRect = new RectF(); + + private static final Property CURRENT_POSITION + = new Property(float.class, "current_position") { + @Override + public Float get(PageIndicatorDots obj) { + return obj.mCurrentPosition; + } + + @Override + public void set(PageIndicatorDots obj, Float pos) { + obj.mCurrentPosition = pos; + obj.invalidate(); + obj.invalidateOutline(); + } + }; + + /** + * Listener for keep running the animation until the final state is reached. + */ + private final AnimatorListenerAdapter mAnimCycleListener = new AnimatorListenerAdapter() { + + @Override + public void onAnimationEnd(Animator animation) { + mAnimator = null; + animateToPostion(mFinalPosition); + } + }; + + private final Paint mCirclePaint; + private final float mDotRadius; + private final int mActiveColor; + private final int mInActiveColor; + private final boolean mIsRtl; + + private int mNumPages; + private int mActivePage; + + /** + * The current position of the active dot including the animation progress. + * For ex: + * 0.0 => Active dot is at position 0 + * 0.33 => Active dot is at position 0 and is moving towards 1 + * 0.50 => Active dot is at position [0, 1] + * 0.77 => Active dot has left position 0 and is collapsing towards position 1 + * 1.0 => Active dot is at position 1 + */ + private float mCurrentPosition; + private float mFinalPosition; + private ObjectAnimator mAnimator; + + private float[] mEntryAnimationRadiusFactors; public PageIndicatorDots(Context context) { this(context, null); @@ -51,137 +116,18 @@ public class PageIndicatorDots extends LinearLayout implements PageIndicator { this(context, attrs, 0); } - public PageIndicatorDots(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - TypedArray a = context.obtainStyledAttributes(attrs, - R.styleable.PageIndicatorDots, defStyle, 0); - mMaxWindowSize = a.getInteger(R.styleable.PageIndicatorDots_windowSize, 15); - mWindowRange[0] = 0; - mWindowRange[1] = 0; - mLayoutInflater = LayoutInflater.from(context); - a.recycle(); + public PageIndicatorDots(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); - // Set the layout transition properties - LayoutTransition transition = getLayoutTransition(); - transition.setDuration(175); - } + mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mCirclePaint.setStyle(Style.FILL); + mDotRadius = getResources().getDimension(R.dimen.page_indicator_dot_size) / 2; + setOutlineProvider(new MyOutlineProver()); - private void enableLayoutTransitions() { - LayoutTransition transition = getLayoutTransition(); - transition.enableTransitionType(LayoutTransition.APPEARING); - transition.enableTransitionType(LayoutTransition.DISAPPEARING); - transition.enableTransitionType(LayoutTransition.CHANGE_APPEARING); - transition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); - } + mActiveColor = getResources().getColor(R.color.launcher_accent_color); + mInActiveColor = getResources().getColor(R.color.page_indicator_dot_color); - private void disableLayoutTransitions() { - LayoutTransition transition = getLayoutTransition(); - transition.disableTransitionType(LayoutTransition.APPEARING); - transition.disableTransitionType(LayoutTransition.DISAPPEARING); - transition.disableTransitionType(LayoutTransition.CHANGE_APPEARING); - transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING); - } - - public void offsetWindowCenterTo(int activeIndex, boolean allowAnimations) { - if (activeIndex < 0) { - new Throwable().printStackTrace(); - } - int windowSize = Math.min(mMarkers.size(), mMaxWindowSize); - int hWindowSize = (int) windowSize / 2; - float hfWindowSize = windowSize / 2f; - int windowStart = Math.max(0, activeIndex - hWindowSize); - int windowEnd = Math.min(mMarkers.size(), windowStart + mMaxWindowSize); - windowStart = windowEnd - Math.min(mMarkers.size(), windowSize); - int windowMid = windowStart + (windowEnd - windowStart) / 2; - boolean windowAtStart = (windowStart == 0); - boolean windowAtEnd = (windowEnd == mMarkers.size()); - boolean windowMoved = (mWindowRange[0] != windowStart) || - (mWindowRange[1] != windowEnd); - - if (!allowAnimations) { - disableLayoutTransitions(); - } - - // Remove all the previous children that are no longer in the window - for (int i = getChildCount() - 1; i >= 0; --i) { - PageIndicatorDot marker = (PageIndicatorDot) getChildAt(i); - int markerIndex = mMarkers.indexOf(marker); - if (markerIndex < windowStart || markerIndex >= windowEnd) { - removeView(marker); - } - } - - // Add all the new children that belong in the window - for (int i = 0; i < mMarkers.size(); ++i) { - PageIndicatorDot marker = (PageIndicatorDot) mMarkers.get(i); - if (windowStart <= i && i < windowEnd) { - if (indexOfChild(marker) < 0) { - addView(marker, i - windowStart); - } - if (i == activeIndex) { - marker.activate(windowMoved); - } else { - marker.inactivate(windowMoved); - } - } else { - marker.inactivate(true); - } - - if (MODULATE_ALPHA_ENABLED) { - // Update the marker's alpha - float alpha = 1f; - if (mMarkers.size() > windowSize) { - if ((windowAtStart && i > hWindowSize) || - (windowAtEnd && i < (mMarkers.size() - hWindowSize)) || - (!windowAtStart && !windowAtEnd)) { - alpha = 1f - Math.abs((i - windowMid) / hfWindowSize); - } - } - marker.animate().alpha(alpha).setDuration(500).start(); - } - } - - if (!allowAnimations) { - enableLayoutTransitions(); - } - - mWindowRange[0] = windowStart; - mWindowRange[1] = windowEnd; - } - - @Override - public void addMarker(int index, PageMarkerResources marker, boolean allowAnimations) { - index = Math.max(0, Math.min(index, mMarkers.size())); - - PageIndicatorDot m = - (PageIndicatorDot) mLayoutInflater.inflate(R.layout.page_indicator_marker, - this, false); - m.setMarkerDrawables(marker.activeId, marker.inactiveId); - - mMarkers.add(index, m); - offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations); - } - - @Override - public void addMarkers(ArrayList markers, boolean allowAnimations) { - for (int i = 0; i < markers.size(); ++i) { - addMarker(Integer.MAX_VALUE, markers.get(i), allowAnimations); - } - } - - @Override - public void updateMarker(int index, PageMarkerResources marker) { - PageIndicatorDot m = mMarkers.get(index); - m.setMarkerDrawables(marker.activeId, marker.inactiveId); - } - - @Override - public void removeMarker(int index, boolean allowAnimations) { - if (mMarkers.size() > 0) { - index = Math.max(0, Math.min(mMarkers.size() - 1, index)); - mMarkers.remove(index); - offsetWindowCenterTo(mActiveMarkerIndex, allowAnimations); - } + mIsRtl = Utilities.isRtl(getResources()); } @Override @@ -190,36 +136,209 @@ public class PageIndicatorDots extends LinearLayout implements PageIndicator { } @Override - public void setProgress(float progress) { + public void setScroll(int currentScroll, int totalScroll) { + if (mNumPages > 1) { + if (mIsRtl) { + currentScroll = totalScroll - currentScroll; + } + int scrollPerPage = totalScroll / (mNumPages - 1); + int absScroll = mActivePage * scrollPerPage; + float scrollThreshold = SHIFT_THRESHOLD * scrollPerPage; + + if ((absScroll - currentScroll) > scrollThreshold) { + // current scroll is before absolute scroll + animateToPostion(mActivePage - SHIFT_PER_ANIMATION); + } else if ((currentScroll - absScroll) > scrollThreshold) { + // current scroll is ahead of absolute scroll + animateToPostion(mActivePage + SHIFT_PER_ANIMATION); + } else { + animateToPostion(mActivePage); + } + } + } + + private void animateToPostion(float position) { + mFinalPosition = position; + if (Math.abs(mCurrentPosition - mFinalPosition) < SHIFT_THRESHOLD) { + mCurrentPosition = mFinalPosition; + } + if (mAnimator == null && Float.compare(mCurrentPosition, mFinalPosition) != 0) { + float positionForThisAnim = mCurrentPosition > mFinalPosition ? + mCurrentPosition - SHIFT_PER_ANIMATION : mCurrentPosition + SHIFT_PER_ANIMATION; + mAnimator = ObjectAnimator.ofFloat(this, CURRENT_POSITION, positionForThisAnim); + mAnimator.addListener(mAnimCycleListener); + mAnimator.setDuration(ANIMATION_DURATION); + mAnimator.start(); + } + } + + public void stopAllAnimations() { + if (mAnimator != null) { + mAnimator.removeAllListeners(); + mAnimator.cancel(); + mAnimator = null; + } + mFinalPosition = mActivePage; + CURRENT_POSITION.set(this, mFinalPosition); + } + + /** + * Sets up up the page indicator to play the entry animation. + * {@link #playEntryAnimation()} must be called after this. + */ + public void prepareEntryAnimation() { + mEntryAnimationRadiusFactors = new float[mNumPages]; + invalidate(); + } + + public void playEntryAnimation() { + int count = mEntryAnimationRadiusFactors.length; + if (count == 0) { + mEntryAnimationRadiusFactors = null; + invalidate(); + return; + } + + Interpolator interpolator = new OvershootInterpolator(ENTER_ANIMATION_OVERSHOOT_TENSION); + AnimatorSet animSet = new AnimatorSet(); + for (int i = 0; i < count; i++) { + ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(ENTER_ANIMATION_DURATION); + final int index = i; + anim.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mEntryAnimationRadiusFactors[index] = (Float) animation.getAnimatedValue(); + invalidate(); + } + }); + anim.setInterpolator(interpolator); + anim.setStartDelay(ENTER_ANIMATION_START_DELAY + ENTER_ANIMATION_STAGGERED_DELAY * i); + animSet.play(anim); + } + + animSet.addListener(new AnimatorListenerAdapter() { + + @Override + public void onAnimationEnd(Animator animation) { + mEntryAnimationRadiusFactors = null; + invalidateOutline(); + invalidate(); + } + }); + animSet.start(); } @Override - public void removeAllMarkers(boolean allowAnimations) { - while (mMarkers.size() > 0) { - removeMarker(Integer.MAX_VALUE, allowAnimations); - } + public void setActiveMarker(int activePage) { + mActivePage = activePage; + invalidate(); } @Override - public void setActiveMarker(int index) { - // Center the active marker - mActiveMarkerIndex = index; - offsetWindowCenterTo(index, false); + public void addMarker() { + mNumPages++; + requestLayout(); } - private void dumpState(String txt) { - System.out.println(txt); - System.out.println("\tmMarkers: " + mMarkers.size()); - for (int i = 0; i < mMarkers.size(); ++i) { - PageIndicatorDot m = mMarkers.get(i); - System.out.println("\t\t(" + i + ") " + m); + @Override + public void removeMarker() { + mNumPages--; + requestLayout(); + } + + @Override + public void setMarkersCount(int numMarkers) { + mNumPages = numMarkers; + requestLayout(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Add extra spacing of mDotRadius on all sides so than entry animation could be run. + int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ? + MeasureSpec.getSize(widthMeasureSpec) : (int) ((mNumPages * 3 + 2) * mDotRadius); + int height= MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY ? + MeasureSpec.getSize(heightMeasureSpec) : (int) (4 * mDotRadius); + setMeasuredDimension(width, height); + } + + @Override + protected void onDraw(Canvas canvas) { + // Draw all page indicators; + float circleGap = 3 * mDotRadius; + float startX = (getWidth() - mNumPages * circleGap + mDotRadius) / 2; + + float x = startX + mDotRadius; + float y = canvas.getHeight() / 2; + + if (mEntryAnimationRadiusFactors != null) { + // During entry animation, only draw the circles + if (mIsRtl) { + x = getWidth() - x; + circleGap = -circleGap; + } + for (int i = 0; i < mEntryAnimationRadiusFactors.length; i++) { + mCirclePaint.setColor(i == mActivePage ? mActiveColor : mInActiveColor); + canvas.drawCircle(x, y, mDotRadius * mEntryAnimationRadiusFactors[i], mCirclePaint); + x += circleGap; + } + } else { + mCirclePaint.setColor(mInActiveColor); + for (int i = 0; i < mNumPages; i++) { + canvas.drawCircle(x, y, mDotRadius, mCirclePaint); + x += circleGap; + } + + mCirclePaint.setColor(mActiveColor); + canvas.drawRoundRect(getActiveRect(), mDotRadius, mDotRadius, mCirclePaint); } - System.out.println("\twindow: [" + mWindowRange[0] + ", " + mWindowRange[1] + "]"); - System.out.println("\tchildren: " + getChildCount()); - for (int i = 0; i < getChildCount(); ++i) { - PageIndicatorDot m = (PageIndicatorDot) getChildAt(i); - System.out.println("\t\t(" + i + ") " + m); + } + + private RectF getActiveRect() { + float startCircle = (int) mCurrentPosition; + float delta = mCurrentPosition - startCircle; + float diameter = 2 * mDotRadius; + float circleGap = 3 * mDotRadius; + float startX = (getWidth() - mNumPages * circleGap + mDotRadius) / 2; + + sTempRect.top = getHeight() * 0.5f - mDotRadius; + sTempRect.bottom = getHeight() * 0.5f + mDotRadius; + sTempRect.left = startX + startCircle * circleGap; + sTempRect.right = sTempRect.left + diameter; + + if (delta < SHIFT_PER_ANIMATION) { + // dot is capturing the right circle. + sTempRect.right += delta * circleGap * 2; + } else { + // Dot is leaving the left circle. + sTempRect.right += circleGap; + + delta -= SHIFT_PER_ANIMATION; + sTempRect.left += delta * circleGap * 2; + } + + if (mIsRtl) { + float rectWidth = sTempRect.width(); + sTempRect.right = getWidth() - sTempRect.left; + sTempRect.left = sTempRect.right - rectWidth; + } + return sTempRect; + } + + private class MyOutlineProver extends ViewOutlineProvider { + + @Override + public void getOutline(View view, Outline outline) { + if (mEntryAnimationRadiusFactors == null) { + RectF activeRect = getActiveRect(); + outline.setRoundRect( + (int) activeRect.left, + (int) activeRect.top, + (int) activeRect.right, + (int) activeRect.bottom, + mDotRadius + ); + } } - System.out.println("\tactive: " + mActiveMarkerIndex); } } diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java index 449bf06096..e48168616f 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java @@ -20,8 +20,6 @@ import android.view.ViewConfiguration; import com.android.launcher3.Utilities; import com.android.launcher3.dynamicui.ExtractedColors; -import java.util.ArrayList; - /** * A PageIndicator that briefly shows a fraction of a line when moving between pages. * @@ -43,17 +41,17 @@ public class PageIndicatorLine extends View implements PageIndicator { private int mNumPages = 1; private Paint mLinePaint; - private Property mPaintAlphaProperty - = new Property(Integer.class, "paint_alpha") { + private static final Property PAINT_ALPHA + = new Property(Integer.class, "paint_alpha") { @Override - public Integer get(Paint paint) { - return paint.getAlpha(); + public Integer get(PageIndicatorLine obj) { + return obj.mLinePaint.getAlpha(); } @Override - public void set(Paint paint, Integer alpha) { - paint.setAlpha(alpha); - invalidate(); + public void set(PageIndicatorLine obj, Integer alpha) { + obj.mLinePaint.setAlpha(alpha); + obj.invalidate(); } }; @@ -99,13 +97,12 @@ public class PageIndicatorLine extends View implements PageIndicator { } @Override - public void setProgress(float progress) { + public void setScroll(int currentScroll, int totalScroll) { if (getAlpha() == 0) { return; } - progress = Utilities.boundToRange(progress, 0f, 1f); animateLineToAlpha(mAlpha); - mProgress = progress; + mProgress = Utilities.boundToRange(((float) currentScroll) / totalScroll, 0f, 1f);; invalidate(); // Hide after a brief period. @@ -113,33 +110,23 @@ public class PageIndicatorLine extends View implements PageIndicator { mHandler.postDelayed(mHideLineRunnable, LINE_FADE_DELAY); } - @Override - public void removeAllMarkers(boolean allowAnimations) { - mNumPages = 0; - } - - @Override - public void addMarkers(ArrayList markers, boolean allowAnimations) { - mNumPages += markers.size(); - } - @Override public void setActiveMarker(int activePage) { } @Override - public void addMarker(int pageIndex, PageMarkerResources pageIndicatorMarker, - boolean allowAnimations) { + public void addMarker() { mNumPages++; } @Override - public void removeMarker(int pageIndex, boolean allowAnimations) { + public void removeMarker() { mNumPages--; } @Override - public void updateMarker(int pageIndex, PageMarkerResources pageIndicatorMarker) { + public void setMarkersCount(int numMarkers) { + mNumPages = numMarkers; } /** @@ -174,7 +161,7 @@ public class PageIndicatorLine extends View implements PageIndicator { } mLineAlphaAnimator.cancel(); } - mLineAlphaAnimator = ObjectAnimator.ofInt(mLinePaint, mPaintAlphaProperty, alpha); + mLineAlphaAnimator = ObjectAnimator.ofInt(this, PAINT_ALPHA, alpha); mLineAlphaAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {