Loading core/java/com/android/internal/widget/ResolverDrawerLayout.java +63 −15 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ public class ResolverDrawerLayout extends ViewGroup { private int mCollapsibleHeightReserved; private int mTopOffset; private boolean mShowAtTop; private boolean mIsDragging; private boolean mOpenOnClick; Loading Loading @@ -134,6 +135,7 @@ public class ResolverDrawerLayout extends ViewGroup { mMaxCollapsedHeightSmall = a.getDimensionPixelSize( R.styleable.ResolverDrawerLayout_maxCollapsedHeightSmall, mMaxCollapsedHeight); mShowAtTop = a.getBoolean(R.styleable.ResolverDrawerLayout_showAtTop, false); a.recycle(); mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); Loading Loading @@ -162,6 +164,16 @@ public class ResolverDrawerLayout extends ViewGroup { return mCollapseOffset > 0; } public void setShowAtTop(boolean showOnTop) { mShowAtTop = showOnTop; invalidate(); requestLayout(); } public boolean getShowAtTop() { return mShowAtTop; } public void setCollapsed(boolean collapsed) { if (!isLaidOut()) { mOpenOnLayout = collapsed; Loading Loading @@ -206,6 +218,12 @@ public class ResolverDrawerLayout extends ViewGroup { return false; } if (getShowAtTop()) { // Keep the drawer fully open. mCollapseOffset = 0; return false; } if (isLaidOut()) { final boolean isCollapsedOld = mCollapseOffset != 0; if (remainClosed && (oldCollapsibleHeight < mCollapsibleHeight Loading Loading @@ -372,6 +390,14 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.computeCurrentVelocity(1000); final float yvel = mVelocityTracker.getYVelocity(mActivePointerId); if (Math.abs(yvel) > mMinFlingVelocity) { if (getShowAtTop()) { if (isDismissable() && yvel < 0) { abortAnimation(); dismiss(); } else { smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); } } else { if (isDismissable() && yvel > 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel); Loading @@ -379,6 +405,7 @@ public class ResolverDrawerLayout extends ViewGroup { } else { smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); } } }else { smoothScrollTo( mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0); Loading Loading @@ -421,6 +448,11 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.clear(); } private void dismiss() { mRunOnDismissedListener = new RunOnDismissedListener(); post(mRunOnDismissedListener); } @Override public void computeScroll() { super.computeScroll(); Loading @@ -430,8 +462,7 @@ public class ResolverDrawerLayout extends ViewGroup { if (keepGoing) { postInvalidateOnAnimation(); } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) { mRunOnDismissedListener = new RunOnDismissedListener(); post(mRunOnDismissedListener); dismiss(); } } } Loading @@ -443,6 +474,10 @@ public class ResolverDrawerLayout extends ViewGroup { } private float performDrag(float dy) { if (getShowAtTop()) { return 0; } final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, mCollapsibleHeight + mUncollapsibleHeight)); if (newPos != mCollapseOffset) { Loading Loading @@ -656,7 +691,7 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public boolean onNestedPreFling(View target, float velocityX, float velocityY) { if (velocityY > mMinFlingVelocity && mCollapseOffset != 0) { if (!getShowAtTop() && velocityY > mMinFlingVelocity && mCollapseOffset != 0) { smoothScrollTo(0, velocityY); return true; } Loading @@ -666,6 +701,14 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) { if (getShowAtTop()) { if (isDismissable() && velocityY > 0) { abortAnimation(); dismiss(); } else { smoothScrollTo(velocityY < 0 ? mCollapsibleHeight : 0, velocityY); } } else { if (isDismissable() && velocityY < 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY); Loading @@ -673,6 +716,7 @@ public class ResolverDrawerLayout extends ViewGroup { } else { smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY); } } return true; } return false; Loading Loading @@ -794,7 +838,11 @@ public class ResolverDrawerLayout extends ViewGroup { updateCollapseOffset(oldCollapsibleHeight, !isDragging()); if (getShowAtTop()) { mTopOffset = 0; } else { mTopOffset = Math.max(0, heightSize - heightUsed) + (int) mCollapseOffset; } setMeasuredDimension(sourceWidth, heightSize); } Loading core/res/res/values/attrs.xml +2 −0 Original line number Diff line number Diff line Loading @@ -8538,6 +8538,8 @@ <attr name="maxWidth" /> <attr name="maxCollapsedHeight" format="dimension" /> <attr name="maxCollapsedHeightSmall" format="dimension" /> <!-- Whether the Drawer should be positioned at the top rather than at the bottom. --> <attr name="showAtTop" format="boolean" /> </declare-styleable> <declare-styleable name="MessagingLinearLayout"> Loading core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +32 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.app; import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.widget.ResolverDrawerLayout; import org.junit.Before; import org.junit.Rule; Loading @@ -33,6 +34,8 @@ import android.os.UserHandle; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.view.View; import android.widget.RelativeLayout; import java.util.ArrayList; import java.util.List; Loading Loading @@ -99,6 +102,34 @@ public class ResolverActivityTest { assertThat(chosen[0], is(toChoose)); } @Test public void setShowAtTopToTrue() throws Exception { Intent sendIntent = createSendImageIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); waitForIdle(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); final View resolverList = activity.findViewById(R.id.resolver_list); final RelativeLayout profileView = (RelativeLayout) activity.findViewById(R.id.profile_button).getParent(); assertThat("Drawer should show at bottom by default", profileView.getBottom() == resolverList.getTop() && profileView.getTop() > 0); activity.runOnUiThread(() -> { ResolverDrawerLayout layout = (ResolverDrawerLayout) activity.findViewById( R.id.contentPanel); layout.setShowAtTop(true); }); waitForIdle(); assertThat("Drawer should show at top with new attribute", profileView.getBottom() == resolverList.getTop() && profileView.getTop() == 0); } @Test public void hasLastChosenActivity() throws Exception { Intent sendIntent = createSendImageIntent(); Loading Loading
core/java/com/android/internal/widget/ResolverDrawerLayout.java +63 −15 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ public class ResolverDrawerLayout extends ViewGroup { private int mCollapsibleHeightReserved; private int mTopOffset; private boolean mShowAtTop; private boolean mIsDragging; private boolean mOpenOnClick; Loading Loading @@ -134,6 +135,7 @@ public class ResolverDrawerLayout extends ViewGroup { mMaxCollapsedHeightSmall = a.getDimensionPixelSize( R.styleable.ResolverDrawerLayout_maxCollapsedHeightSmall, mMaxCollapsedHeight); mShowAtTop = a.getBoolean(R.styleable.ResolverDrawerLayout_showAtTop, false); a.recycle(); mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material); Loading Loading @@ -162,6 +164,16 @@ public class ResolverDrawerLayout extends ViewGroup { return mCollapseOffset > 0; } public void setShowAtTop(boolean showOnTop) { mShowAtTop = showOnTop; invalidate(); requestLayout(); } public boolean getShowAtTop() { return mShowAtTop; } public void setCollapsed(boolean collapsed) { if (!isLaidOut()) { mOpenOnLayout = collapsed; Loading Loading @@ -206,6 +218,12 @@ public class ResolverDrawerLayout extends ViewGroup { return false; } if (getShowAtTop()) { // Keep the drawer fully open. mCollapseOffset = 0; return false; } if (isLaidOut()) { final boolean isCollapsedOld = mCollapseOffset != 0; if (remainClosed && (oldCollapsibleHeight < mCollapsibleHeight Loading Loading @@ -372,6 +390,14 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.computeCurrentVelocity(1000); final float yvel = mVelocityTracker.getYVelocity(mActivePointerId); if (Math.abs(yvel) > mMinFlingVelocity) { if (getShowAtTop()) { if (isDismissable() && yvel < 0) { abortAnimation(); dismiss(); } else { smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); } } else { if (isDismissable() && yvel > 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, yvel); Loading @@ -379,6 +405,7 @@ public class ResolverDrawerLayout extends ViewGroup { } else { smoothScrollTo(yvel < 0 ? 0 : mCollapsibleHeight, yvel); } } }else { smoothScrollTo( mCollapseOffset < mCollapsibleHeight / 2 ? 0 : mCollapsibleHeight, 0); Loading Loading @@ -421,6 +448,11 @@ public class ResolverDrawerLayout extends ViewGroup { mVelocityTracker.clear(); } private void dismiss() { mRunOnDismissedListener = new RunOnDismissedListener(); post(mRunOnDismissedListener); } @Override public void computeScroll() { super.computeScroll(); Loading @@ -430,8 +462,7 @@ public class ResolverDrawerLayout extends ViewGroup { if (keepGoing) { postInvalidateOnAnimation(); } else if (mDismissOnScrollerFinished && mOnDismissedListener != null) { mRunOnDismissedListener = new RunOnDismissedListener(); post(mRunOnDismissedListener); dismiss(); } } } Loading @@ -443,6 +474,10 @@ public class ResolverDrawerLayout extends ViewGroup { } private float performDrag(float dy) { if (getShowAtTop()) { return 0; } final float newPos = Math.max(0, Math.min(mCollapseOffset + dy, mCollapsibleHeight + mUncollapsibleHeight)); if (newPos != mCollapseOffset) { Loading Loading @@ -656,7 +691,7 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public boolean onNestedPreFling(View target, float velocityX, float velocityY) { if (velocityY > mMinFlingVelocity && mCollapseOffset != 0) { if (!getShowAtTop() && velocityY > mMinFlingVelocity && mCollapseOffset != 0) { smoothScrollTo(0, velocityY); return true; } Loading @@ -666,6 +701,14 @@ public class ResolverDrawerLayout extends ViewGroup { @Override public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) { if (!consumed && Math.abs(velocityY) > mMinFlingVelocity) { if (getShowAtTop()) { if (isDismissable() && velocityY > 0) { abortAnimation(); dismiss(); } else { smoothScrollTo(velocityY < 0 ? mCollapsibleHeight : 0, velocityY); } } else { if (isDismissable() && velocityY < 0 && mCollapseOffset > mCollapsibleHeight) { smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, velocityY); Loading @@ -673,6 +716,7 @@ public class ResolverDrawerLayout extends ViewGroup { } else { smoothScrollTo(velocityY > 0 ? 0 : mCollapsibleHeight, velocityY); } } return true; } return false; Loading Loading @@ -794,7 +838,11 @@ public class ResolverDrawerLayout extends ViewGroup { updateCollapseOffset(oldCollapsibleHeight, !isDragging()); if (getShowAtTop()) { mTopOffset = 0; } else { mTopOffset = Math.max(0, heightSize - heightUsed) + (int) mCollapseOffset; } setMeasuredDimension(sourceWidth, heightSize); } Loading
core/res/res/values/attrs.xml +2 −0 Original line number Diff line number Diff line Loading @@ -8538,6 +8538,8 @@ <attr name="maxWidth" /> <attr name="maxCollapsedHeight" format="dimension" /> <attr name="maxCollapsedHeightSmall" format="dimension" /> <!-- Whether the Drawer should be positioned at the top rather than at the bottom. --> <attr name="showAtTop" format="boolean" /> </declare-styleable> <declare-styleable name="MessagingLinearLayout"> Loading
core/tests/coretests/src/com/android/internal/app/ResolverActivityTest.java +32 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.internal.app; import com.android.internal.R; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.widget.ResolverDrawerLayout; import org.junit.Before; import org.junit.Rule; Loading @@ -33,6 +34,8 @@ import android.os.UserHandle; import android.support.test.InstrumentationRegistry; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.view.View; import android.widget.RelativeLayout; import java.util.ArrayList; import java.util.List; Loading Loading @@ -99,6 +102,34 @@ public class ResolverActivityTest { assertThat(chosen[0], is(toChoose)); } @Test public void setShowAtTopToTrue() throws Exception { Intent sendIntent = createSendImageIntent(); List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2); when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.isA(List.class))).thenReturn(resolvedComponentInfos); waitForIdle(); final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent); final View resolverList = activity.findViewById(R.id.resolver_list); final RelativeLayout profileView = (RelativeLayout) activity.findViewById(R.id.profile_button).getParent(); assertThat("Drawer should show at bottom by default", profileView.getBottom() == resolverList.getTop() && profileView.getTop() > 0); activity.runOnUiThread(() -> { ResolverDrawerLayout layout = (ResolverDrawerLayout) activity.findViewById( R.id.contentPanel); layout.setShowAtTop(true); }); waitForIdle(); assertThat("Drawer should show at top with new attribute", profileView.getBottom() == resolverList.getTop() && profileView.getTop() == 0); } @Test public void hasLastChosenActivity() throws Exception { Intent sendIntent = createSendImageIntent(); Loading