Loading packages/SystemUI/res/layout/car_qs_panel.xml +7 −0 Original line number Original line Diff line number Diff line Loading @@ -24,4 +24,11 @@ <include layout="@layout/car_status_bar_header" /> <include layout="@layout/car_status_bar_header" /> <include layout="@layout/car_qs_footer" /> <include layout="@layout/car_qs_footer" /> <com.android.systemui.statusbar.car.UserGridView android:id="@+id/user_grid" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/car_margin" android:layout_marginRight="@dimen/car_margin" /> </LinearLayout> </LinearLayout> packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java +22 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ import android.content.Intent; import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.View; import android.widget.ImageView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.RelativeLayout; Loading @@ -27,6 +28,7 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.car.UserGridView; import com.android.systemui.statusbar.phone.MultiUserSwitch; import com.android.systemui.statusbar.phone.MultiUserSwitch; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoController; Loading @@ -37,10 +39,13 @@ import com.android.systemui.statusbar.policy.UserInfoController; */ */ public class CarQSFooter extends RelativeLayout implements QSFooter, public class CarQSFooter extends RelativeLayout implements QSFooter, UserInfoController.OnUserInfoChangedListener { UserInfoController.OnUserInfoChangedListener { private static final String TAG = "CarQSFooter"; private UserInfoController mUserInfoController; private UserInfoController mUserInfoController; private MultiUserSwitch mMultiUserSwitch; private MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; private ImageView mMultiUserAvatar; private UserGridView mUserGridView; public CarQSFooter(Context context, AttributeSet attrs) { public CarQSFooter(Context context, AttributeSet attrs) { super(context, attrs); super(context, attrs); Loading @@ -54,6 +59,19 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, mUserInfoController = Dependency.get(UserInfoController.class); mUserInfoController = Dependency.get(UserInfoController.class); mMultiUserSwitch.setOnClickListener(v -> { if (mUserGridView == null) { Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher."); return; } if (!mUserGridView.isShowing()) { mUserGridView.show(); } else { mUserGridView.hide(); } }); findViewById(R.id.settings_button).setOnClickListener(v -> { findViewById(R.id.settings_button).setOnClickListener(v -> { ActivityStarter activityStarter = Dependency.get(ActivityStarter.class); ActivityStarter activityStarter = Dependency.get(ActivityStarter.class); Loading @@ -80,6 +98,10 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, } } } } public void setUserGridView(UserGridView view) { mUserGridView = view; } @Override @Override public void setListening(boolean listening) { public void setListening(boolean listening) { if (listening) { if (listening) { Loading packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +11 −1 Original line number Original line Diff line number Diff line Loading @@ -22,9 +22,12 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewGroup; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSFooter; import com.android.systemui.statusbar.car.UserGridView; import com.android.systemui.statusbar.policy.UserSwitcherController; /** /** * A quick settings fragment for the car. For auto, there is no row for quick settings or ability * A quick settings fragment for the car. For auto, there is no row for quick settings or ability Loading @@ -33,7 +36,8 @@ import com.android.systemui.qs.QSFooter; */ */ public class CarQSFragment extends Fragment implements QS { public class CarQSFragment extends Fragment implements QS { private View mHeader; private View mHeader; private QSFooter mFooter; private CarQSFooter mFooter; private UserGridView mUserGridView; @Override @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Loading @@ -46,6 +50,12 @@ public class CarQSFragment extends Fragment implements QS { super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState); mHeader = view.findViewById(R.id.header); mHeader = view.findViewById(R.id.header); mFooter = view.findViewById(R.id.qs_footer); mFooter = view.findViewById(R.id.qs_footer); mUserGridView = view.findViewById(R.id.user_grid); mUserGridView.init(null, Dependency.get(UserSwitcherController.class), false /* showInitially */); mFooter.setUserGridView(mUserGridView); } } @Override @Override Loading packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -53,7 +53,7 @@ public class FullscreenUserSwitcher { mParent = containerStub.inflate(); mParent = containerStub.inflate(); mContainer = mParent.findViewById(R.id.container); mContainer = mParent.findViewById(R.id.container); mUserGridView = mContainer.findViewById(R.id.user_grid); mUserGridView = mContainer.findViewById(R.id.user_grid); mUserGridView.init(statusBar, mUserSwitcherController); mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */); mUserGridView.setUserSelectionListener(record -> { mUserGridView.setUserSelectionListener(record -> { if (!record.isCurrent) { if (!record.isCurrent) { toggleSwitchInProgress(true); toggleSwitchInProgress(true); Loading packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java +102 −11 Original line number Original line Diff line number Diff line Loading @@ -16,20 +16,21 @@ package com.android.systemui.statusbar.car; package com.android.systemui.statusbar.car; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.ValueAnimator; import android.content.Context; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Align; import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable; import android.os.UserHandle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; Loading @@ -37,9 +38,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TextView; import com.android.internal.util.UserIcons; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.statusbar.UserUtil; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.UserSwitcherController; Loading @@ -48,21 +47,44 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; * One of the uses of this is for the lock screen in auto. * One of the uses of this is for the lock screen in auto. */ */ public class UserGridView extends ViewPager { public class UserGridView extends ViewPager { private static final int EXPAND_ANIMATION_TIME_MS = 200; private static final int HIDE_ANIMATION_TIME_MS = 133; private StatusBar mStatusBar; private StatusBar mStatusBar; private UserSwitcherController mUserSwitcherController; private UserSwitcherController mUserSwitcherController; private Adapter mAdapter; private Adapter mAdapter; private UserSelectionListener mUserSelectionListener; private UserSelectionListener mUserSelectionListener; private ValueAnimator mHeightAnimator; private int mTargetHeight; private int mHeightChildren; private boolean mShowing; public UserGridView(Context context, AttributeSet attrs) { public UserGridView(Context context, AttributeSet attrs) { super(context, attrs); super(context, attrs); } } public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) { public void init(StatusBar statusBar, UserSwitcherController userSwitcherController, boolean showInitially) { mStatusBar = statusBar; mStatusBar = statusBar; mUserSwitcherController = userSwitcherController; mUserSwitcherController = userSwitcherController; mAdapter = new Adapter(mUserSwitcherController); mAdapter = new Adapter(mUserSwitcherController); addOnLayoutChangeListener(mAdapter); addOnLayoutChangeListener(mAdapter); setAdapter(mAdapter); setAdapter(mAdapter); mShowing = showInitially; } public boolean isShowing() { return mShowing; } public void show() { mShowing = true; animateHeightChange(getMeasuredHeight(), mHeightChildren); } public void hide() { mShowing = false; animateHeightChange(getMeasuredHeight(), 0); } } public void onUserSwitched(int newUserId) { public void onUserSwitched(int newUserId) { Loading @@ -83,16 +105,85 @@ public class UserGridView extends ViewPager { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Wrap content doesn't work in ViewPagers, so simulate the behavior in code. // Wrap content doesn't work in ViewPagers, so simulate the behavior in code. int height = 0; int height = 0; if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { height = MeasureSpec.getSize(heightMeasureSpec); } else { for (int i = 0; i < getChildCount(); i++) { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); View child = getChildAt(i); child.measure(widthMeasureSpec, child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); height = Math.max(child.getMeasuredHeight(), height); height = Math.max(child.getMeasuredHeight(), height); } } mHeightChildren = height; // Override the height if it's not showing. if (!mShowing) { height = 0; } // Respect the AT_MOST request from parent. if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height); } } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } private void animateHeightChange(int oldHeight, int newHeight) { // If there is no change in height or an animation is already in progress towards the // desired height, then there's no need to make any changes. if (oldHeight == newHeight || newHeight == mTargetHeight) { return; } // Animation in progress is not going towards the new target, so cancel it. if (mHeightAnimator != null){ mHeightAnimator.cancel(); } mTargetHeight = newHeight; mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight); mHeightAnimator.addUpdateListener(valueAnimator -> { ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.height = (Integer) valueAnimator.getAnimatedValue(); requestLayout(); }); mHeightAnimator.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animator) {} @Override public void onAnimationEnd(Animator animator) { // ValueAnimator does not guarantee that the update listener will get an update // to the final value, so here, the final value is set. Though the final calculated // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate. ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; requestLayout(); mHeightAnimator = null; } @Override public void onAnimationCancel(Animator animator) {} @Override public void onAnimationRepeat(Animator animator) {} }); mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator()); if (oldHeight < newHeight) { // Expanding mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS); } else { // Hiding mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS); } mHeightAnimator.start(); } /** /** * This is a ViewPager.PagerAdapter which deletegates the work to a * This is a ViewPager.PagerAdapter which deletegates the work to a * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have Loading Loading
packages/SystemUI/res/layout/car_qs_panel.xml +7 −0 Original line number Original line Diff line number Diff line Loading @@ -24,4 +24,11 @@ <include layout="@layout/car_status_bar_header" /> <include layout="@layout/car_status_bar_header" /> <include layout="@layout/car_qs_footer" /> <include layout="@layout/car_qs_footer" /> <com.android.systemui.statusbar.car.UserGridView android:id="@+id/user_grid" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/car_margin" android:layout_marginRight="@dimen/car_margin" /> </LinearLayout> </LinearLayout>
packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java +22 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ import android.content.Intent; import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable; import android.support.annotation.Nullable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.View; import android.widget.ImageView; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.RelativeLayout; Loading @@ -27,6 +28,7 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.car.UserGridView; import com.android.systemui.statusbar.phone.MultiUserSwitch; import com.android.systemui.statusbar.phone.MultiUserSwitch; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserInfoController; Loading @@ -37,10 +39,13 @@ import com.android.systemui.statusbar.policy.UserInfoController; */ */ public class CarQSFooter extends RelativeLayout implements QSFooter, public class CarQSFooter extends RelativeLayout implements QSFooter, UserInfoController.OnUserInfoChangedListener { UserInfoController.OnUserInfoChangedListener { private static final String TAG = "CarQSFooter"; private UserInfoController mUserInfoController; private UserInfoController mUserInfoController; private MultiUserSwitch mMultiUserSwitch; private MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; private ImageView mMultiUserAvatar; private UserGridView mUserGridView; public CarQSFooter(Context context, AttributeSet attrs) { public CarQSFooter(Context context, AttributeSet attrs) { super(context, attrs); super(context, attrs); Loading @@ -54,6 +59,19 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, mUserInfoController = Dependency.get(UserInfoController.class); mUserInfoController = Dependency.get(UserInfoController.class); mMultiUserSwitch.setOnClickListener(v -> { if (mUserGridView == null) { Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher."); return; } if (!mUserGridView.isShowing()) { mUserGridView.show(); } else { mUserGridView.hide(); } }); findViewById(R.id.settings_button).setOnClickListener(v -> { findViewById(R.id.settings_button).setOnClickListener(v -> { ActivityStarter activityStarter = Dependency.get(ActivityStarter.class); ActivityStarter activityStarter = Dependency.get(ActivityStarter.class); Loading @@ -80,6 +98,10 @@ public class CarQSFooter extends RelativeLayout implements QSFooter, } } } } public void setUserGridView(UserGridView view) { mUserGridView = view; } @Override @Override public void setListening(boolean listening) { public void setListening(boolean listening) { if (listening) { if (listening) { Loading
packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java +11 −1 Original line number Original line Diff line number Diff line Loading @@ -22,9 +22,12 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewGroup; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.QSFooter; import com.android.systemui.qs.QSFooter; import com.android.systemui.statusbar.car.UserGridView; import com.android.systemui.statusbar.policy.UserSwitcherController; /** /** * A quick settings fragment for the car. For auto, there is no row for quick settings or ability * A quick settings fragment for the car. For auto, there is no row for quick settings or ability Loading @@ -33,7 +36,8 @@ import com.android.systemui.qs.QSFooter; */ */ public class CarQSFragment extends Fragment implements QS { public class CarQSFragment extends Fragment implements QS { private View mHeader; private View mHeader; private QSFooter mFooter; private CarQSFooter mFooter; private UserGridView mUserGridView; @Override @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Loading @@ -46,6 +50,12 @@ public class CarQSFragment extends Fragment implements QS { super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState); mHeader = view.findViewById(R.id.header); mHeader = view.findViewById(R.id.header); mFooter = view.findViewById(R.id.qs_footer); mFooter = view.findViewById(R.id.qs_footer); mUserGridView = view.findViewById(R.id.user_grid); mUserGridView.init(null, Dependency.get(UserSwitcherController.class), false /* showInitially */); mFooter.setUserGridView(mUserGridView); } } @Override @Override Loading
packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -53,7 +53,7 @@ public class FullscreenUserSwitcher { mParent = containerStub.inflate(); mParent = containerStub.inflate(); mContainer = mParent.findViewById(R.id.container); mContainer = mParent.findViewById(R.id.container); mUserGridView = mContainer.findViewById(R.id.user_grid); mUserGridView = mContainer.findViewById(R.id.user_grid); mUserGridView.init(statusBar, mUserSwitcherController); mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */); mUserGridView.setUserSelectionListener(record -> { mUserGridView.setUserSelectionListener(record -> { if (!record.isCurrent) { if (!record.isCurrent) { toggleSwitchInProgress(true); toggleSwitchInProgress(true); Loading
packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java +102 −11 Original line number Original line Diff line number Diff line Loading @@ -16,20 +16,21 @@ package com.android.systemui.statusbar.car; package com.android.systemui.statusbar.car; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.ValueAnimator; import android.content.Context; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Align; import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable; import android.os.UserHandle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.View; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup; Loading @@ -37,9 +38,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TextView; import com.android.internal.util.UserIcons; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.statusbar.UserUtil; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.UserSwitcherController; Loading @@ -48,21 +47,44 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; * One of the uses of this is for the lock screen in auto. * One of the uses of this is for the lock screen in auto. */ */ public class UserGridView extends ViewPager { public class UserGridView extends ViewPager { private static final int EXPAND_ANIMATION_TIME_MS = 200; private static final int HIDE_ANIMATION_TIME_MS = 133; private StatusBar mStatusBar; private StatusBar mStatusBar; private UserSwitcherController mUserSwitcherController; private UserSwitcherController mUserSwitcherController; private Adapter mAdapter; private Adapter mAdapter; private UserSelectionListener mUserSelectionListener; private UserSelectionListener mUserSelectionListener; private ValueAnimator mHeightAnimator; private int mTargetHeight; private int mHeightChildren; private boolean mShowing; public UserGridView(Context context, AttributeSet attrs) { public UserGridView(Context context, AttributeSet attrs) { super(context, attrs); super(context, attrs); } } public void init(StatusBar statusBar, UserSwitcherController userSwitcherController) { public void init(StatusBar statusBar, UserSwitcherController userSwitcherController, boolean showInitially) { mStatusBar = statusBar; mStatusBar = statusBar; mUserSwitcherController = userSwitcherController; mUserSwitcherController = userSwitcherController; mAdapter = new Adapter(mUserSwitcherController); mAdapter = new Adapter(mUserSwitcherController); addOnLayoutChangeListener(mAdapter); addOnLayoutChangeListener(mAdapter); setAdapter(mAdapter); setAdapter(mAdapter); mShowing = showInitially; } public boolean isShowing() { return mShowing; } public void show() { mShowing = true; animateHeightChange(getMeasuredHeight(), mHeightChildren); } public void hide() { mShowing = false; animateHeightChange(getMeasuredHeight(), 0); } } public void onUserSwitched(int newUserId) { public void onUserSwitched(int newUserId) { Loading @@ -83,16 +105,85 @@ public class UserGridView extends ViewPager { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Wrap content doesn't work in ViewPagers, so simulate the behavior in code. // Wrap content doesn't work in ViewPagers, so simulate the behavior in code. int height = 0; int height = 0; if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { height = MeasureSpec.getSize(heightMeasureSpec); } else { for (int i = 0; i < getChildCount(); i++) { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); View child = getChildAt(i); child.measure(widthMeasureSpec, child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); height = Math.max(child.getMeasuredHeight(), height); height = Math.max(child.getMeasuredHeight(), height); } } mHeightChildren = height; // Override the height if it's not showing. if (!mShowing) { height = 0; } // Respect the AT_MOST request from parent. if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height); } } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } private void animateHeightChange(int oldHeight, int newHeight) { // If there is no change in height or an animation is already in progress towards the // desired height, then there's no need to make any changes. if (oldHeight == newHeight || newHeight == mTargetHeight) { return; } // Animation in progress is not going towards the new target, so cancel it. if (mHeightAnimator != null){ mHeightAnimator.cancel(); } mTargetHeight = newHeight; mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight); mHeightAnimator.addUpdateListener(valueAnimator -> { ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.height = (Integer) valueAnimator.getAnimatedValue(); requestLayout(); }); mHeightAnimator.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animator) {} @Override public void onAnimationEnd(Animator animator) { // ValueAnimator does not guarantee that the update listener will get an update // to the final value, so here, the final value is set. Though the final calculated // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate. ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; requestLayout(); mHeightAnimator = null; } @Override public void onAnimationCancel(Animator animator) {} @Override public void onAnimationRepeat(Animator animator) {} }); mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator()); if (oldHeight < newHeight) { // Expanding mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS); } else { // Hiding mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS); } mHeightAnimator.start(); } /** /** * This is a ViewPager.PagerAdapter which deletegates the work to a * This is a ViewPager.PagerAdapter which deletegates the work to a * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have * UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have Loading