Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 906d882f authored by Alex Chau's avatar Alex Chau
Browse files

Update drop target button alignment across devices

- Partial re-land of http://ag/18520765
- Layout the buttons from center of screen for two panels, or from center of workspace for all other cases

Bug: 229789612
Fix: 231706480
Fix: 232063941
Fix: 232283628
Test: manual
Change-Id: Icbc9e2a19140ce3127d5dfe9f798a8ada336cea8
parent 29405655
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -24,6 +24,8 @@
    <dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
    <dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
    <!-- Minimum space between workspace and hotseat in spring loaded mode -->
    <!-- Minimum space between workspace and hotseat in spring loaded mode -->
    <dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
    <dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
    <!-- Minimum amount of next page visible in spring loaded mode -->
    <dimen name="dynamic_grid_spring_loaded_min_next_space_visible">24dp</dimen>


    <dimen name="dynamic_grid_cell_border_spacing">16dp</dimen>
    <dimen name="dynamic_grid_cell_border_spacing">16dp</dimen>
    <dimen name="cell_layout_padding">10.77dp</dimen>
    <dimen name="cell_layout_padding">10.77dp</dimen>
@@ -58,9 +60,10 @@
    <!-- Drop target bar -->
    <!-- Drop target bar -->
    <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
    <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
    <dimen name="drop_target_vertical_gap">20dp</dimen>
    <dimen name="drop_target_vertical_gap">20dp</dimen>
    <dimen name="drop_target_top_margin">36dp</dimen>
    <dimen name="drop_target_top_margin">32dp</dimen>
    <dimen name="drop_target_bottom_margin">16dp</dimen>
    <dimen name="drop_target_bottom_margin">16dp</dimen>


    <!-- App Widget resize frame -->
    <!-- Button drop target bar -->
    <!-- Button drop target bar -->
    <dimen name="button_drop_target_min_text_size">10sp</dimen>
    <dimen name="button_drop_target_min_text_size">10sp</dimen>
    <dimen name="button_drop_target_resize_text_increment">1sp</dimen>
    <dimen name="button_drop_target_resize_text_increment">1sp</dimen>
@@ -237,7 +240,7 @@
    <dimen name="drop_target_button_drawable_padding">8dp</dimen>
    <dimen name="drop_target_button_drawable_padding">8dp</dimen>
    <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
    <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
    <dimen name="drop_target_button_drawable_vertical_padding">8dp</dimen>
    <dimen name="drop_target_button_drawable_vertical_padding">8dp</dimen>
    <dimen name="drop_target_button_gap">22dp</dimen>
    <dimen name="drop_target_button_gap">28dp</dimen>


    <!-- the distance an icon must be dragged before button drop targets accept it -->
    <!-- the distance an icon must be dragged before button drop targets accept it -->
    <dimen name="drag_distanceThreshold">30dp</dimen>
    <dimen name="drag_distanceThreshold">30dp</dimen>
+45 −39
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
@@ -49,6 +50,8 @@ public abstract class ButtonDropTarget extends TextView
    private static final int[] sTempCords = new int[2];
    private static final int[] sTempCords = new int[2];
    private static final int DRAG_VIEW_DROP_DURATION = 285;
    private static final int DRAG_VIEW_DROP_DURATION = 285;
    private static final float DRAG_VIEW_HOVER_OVER_OPACITY = 0.65f;
    private static final float DRAG_VIEW_HOVER_OVER_OPACITY = 0.65f;
    private static final int MAX_LINES_TEXT_MULTI_LINE = 2;
    private static final int MAX_LINES_TEXT_SINGLE_LINE = 1;


    public static final int TOOLTIP_DEFAULT = 0;
    public static final int TOOLTIP_DEFAULT = 0;
    public static final int TOOLTIP_LEFT = 1;
    public static final int TOOLTIP_LEFT = 1;
@@ -72,6 +75,8 @@ public abstract class ButtonDropTarget extends TextView
    protected CharSequence mText;
    protected CharSequence mText;
    protected Drawable mDrawable;
    protected Drawable mDrawable;
    private boolean mTextVisible = true;
    private boolean mTextVisible = true;
    private boolean mIconVisible = true;
    private boolean mTextMultiLine = true;


    private PopupWindow mToolTip;
    private PopupWindow mToolTip;
    private int mToolTipLocation;
    private int mToolTipLocation;
@@ -109,8 +114,7 @@ public abstract class ButtonDropTarget extends TextView
        // drawableLeft and drawableStart.
        // drawableLeft and drawableStart.
        mDrawable = getContext().getDrawable(resId).mutate();
        mDrawable = getContext().getDrawable(resId).mutate();
        mDrawable.setTintList(getTextColors());
        mDrawable.setTintList(getTextColors());
        centerIcon();
        updateIconVisibility();
        setCompoundDrawablesRelative(mDrawable, null, null, null);
    }
    }


    public void setDropTargetBar(DropTargetBar dropTargetBar) {
    public void setDropTargetBar(DropTargetBar dropTargetBar) {
@@ -306,11 +310,47 @@ public abstract class ButtonDropTarget extends TextView
        if (mTextVisible != isVisible || !TextUtils.equals(newText, getText())) {
        if (mTextVisible != isVisible || !TextUtils.equals(newText, getText())) {
            mTextVisible = isVisible;
            mTextVisible = isVisible;
            setText(newText);
            setText(newText);
            updateIconVisibility();
        }
    }

    /**
     * Display button text over multiple lines when isMultiLine is true, single line otherwise.
     */
    public void setTextMultiLine(boolean isMultiLine) {
        if (mTextMultiLine != isMultiLine) {
            mTextMultiLine = isMultiLine;
            setSingleLine(!isMultiLine);
            setMaxLines(isMultiLine ? MAX_LINES_TEXT_MULTI_LINE : MAX_LINES_TEXT_SINGLE_LINE);
            int inputType = InputType.TYPE_CLASS_TEXT;
            if (isMultiLine) {
                inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE;

            }
            setInputType(inputType);
        }
    }

    protected boolean isTextMultiLine() {
        return mTextMultiLine;
    }

    /**
     * Sets the button icon visible when isVisible is true, hides it otherwise.
     */
    public void setIconVisible(boolean isVisible) {
        if (mIconVisible != isVisible) {
            mIconVisible = isVisible;
            updateIconVisibility();
        }
    }

    private void updateIconVisibility() {
        if (mIconVisible) {
            centerIcon();
            centerIcon();
            setCompoundDrawablesRelative(mDrawable, null, null, null);
            int drawablePadding = mTextVisible ? mDrawablePadding : 0;
            setCompoundDrawablePadding(drawablePadding);
        }
        }
        setCompoundDrawablesRelative(mIconVisible ? mDrawable : null, null, null, null);
        setCompoundDrawablePadding(mIconVisible && mTextVisible ? mDrawablePadding : 0);
    }
    }


    @Override
    @Override
@@ -324,40 +364,6 @@ public abstract class ButtonDropTarget extends TextView
        hideTooltip();
        hideTooltip();
    }
    }



    /**
     * Reduce the size of the text until it fits or reaches a minimum.
     *
     * The minimum size is defined by {@code R.dimen.button_drop_target_min_text_size} and
     * it diminishes by intervals defined by
     * {@code R.dimen.button_drop_target_resize_text_increment}
     * This functionality is very similar to the option
     * {@link TextView#setAutoSizeTextTypeWithDefaults(int)} but can't be used in this view because
     * the layout width is {@code WRAP_CONTENT}.
     *
     * @param availableWidth Available width in the button to fit the text, used in
     *        {@code ButtonDropTarget#isTextTruncated(int)}
     * @return The biggest text size in SP that makes the text fit or if the text can't fit returns
     *         the min available value
     */
    public float resizeTextToFit(int availableWidth) {
        float minSize = Utilities.pxToSp(getResources()
                .getDimensionPixelSize(R.dimen.button_drop_target_min_text_size));
        float step = Utilities.pxToSp(getResources()
                .getDimensionPixelSize(R.dimen.button_drop_target_resize_text_increment));
        float textSize = Utilities.pxToSp(getTextSize());

        while (textSize > minSize) {
            if (isTextTruncated(availableWidth)) {
                textSize -= step;
                setTextSize(textSize);
            } else {
                return textSize;
            }
        }
        return minSize;
    }

    public boolean isTextTruncated(int availableWidth) {
    public boolean isTextTruncated(int availableWidth) {
        availableWidth -= (getPaddingLeft() + getPaddingRight() + mDrawable.getIntrinsicWidth()
        availableWidth -= (getPaddingLeft() + getPaddingRight() + mDrawable.getIntrinsicWidth()
                + getCompoundDrawablePadding());
                + getCompoundDrawablePadding());
+9 −10
Original line number Original line Diff line number Diff line
@@ -108,6 +108,7 @@ public class DeviceProfile {
    public float workspaceSpringLoadShrunkTop;
    public float workspaceSpringLoadShrunkTop;
    public float workspaceSpringLoadShrunkBottom;
    public float workspaceSpringLoadShrunkBottom;
    public final int workspaceSpringLoadedBottomSpace;
    public final int workspaceSpringLoadedBottomSpace;
    public final int workspaceSpringLoadedMinNextPageVisiblePx;


    private final int extraSpace;
    private final int extraSpace;
    public int workspaceTopPadding;
    public int workspaceTopPadding;
@@ -344,6 +345,8 @@ public class DeviceProfile {


        workspaceSpringLoadedBottomSpace =
        workspaceSpringLoadedBottomSpace =
                res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
                res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
        workspaceSpringLoadedMinNextPageVisiblePx = res.getDimensionPixelSize(
                R.dimen.dynamic_grid_spring_loaded_min_next_space_visible);


        workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
        workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);


@@ -499,7 +502,7 @@ public class DeviceProfile {
     */
     */
    private int calculateQsbWidth() {
    private int calculateQsbWidth() {
        if (isQsbInline) {
        if (isQsbInline) {
            int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
            int columns = getPanelCount() * inv.numColumns;
            return getIconToIconWidthForColumns(columns)
            return getIconToIconWidthForColumns(columns)
                    - iconSizePx * numShownHotseatIcons
                    - iconSizePx * numShownHotseatIcons
                    - hotseatBorderSpace * numShownHotseatIcons;
                    - hotseatBorderSpace * numShownHotseatIcons;
@@ -951,13 +954,6 @@ public class DeviceProfile {
        return workspaceSpringLoadShrunkBottom;
        return workspaceSpringLoadShrunkBottom;
    }
    }


    /**
     * Gets the minimum visible amount of the next workspace page when in the spring-loaded state.
     */
    private float getWorkspaceSpringLoadedMinimumNextPageVisible() {
        return getCellSize().x / 2f;
    }

    /**
    /**
     * Gets the scale of the workspace for the spring-loaded edit state.
     * Gets the scale of the workspace for the spring-loaded edit state.
     */
     */
@@ -969,8 +965,7 @@ public class DeviceProfile {
        // Reduce scale if next pages would not be visible after scaling the workspace
        // Reduce scale if next pages would not be visible after scaling the workspace
        int workspaceWidth = availableWidthPx;
        int workspaceWidth = availableWidthPx;
        float scaledWorkspaceWidth = workspaceWidth * scale;
        float scaledWorkspaceWidth = workspaceWidth * scale;
        float maxAvailableWidth =
        float maxAvailableWidth = workspaceWidth - (2 * workspaceSpringLoadedMinNextPageVisiblePx);
                workspaceWidth - (2 * getWorkspaceSpringLoadedMinimumNextPageVisible());
        if (scaledWorkspaceWidth > maxAvailableWidth) {
        if (scaledWorkspaceWidth > maxAvailableWidth) {
            scale *= maxAvailableWidth / scaledWorkspaceWidth;
            scale *= maxAvailableWidth / scaledWorkspaceWidth;
        }
        }
@@ -1414,6 +1409,10 @@ public class DeviceProfile {
                prefix + pxToDpStr("workspaceSpringLoadShrunkTop", workspaceSpringLoadShrunkTop));
                prefix + pxToDpStr("workspaceSpringLoadShrunkTop", workspaceSpringLoadShrunkTop));
        writer.println(prefix + pxToDpStr("workspaceSpringLoadShrunkBottom",
        writer.println(prefix + pxToDpStr("workspaceSpringLoadShrunkBottom",
                workspaceSpringLoadShrunkBottom));
                workspaceSpringLoadShrunkBottom));
        writer.println(prefix + pxToDpStr("workspaceSpringLoadedBottomSpace",
                workspaceSpringLoadedBottomSpace));
        writer.println(prefix + pxToDpStr("workspaceSpringLoadedMinNextPageVisiblePx",
                workspaceSpringLoadedMinNextPageVisiblePx));
        writer.println(
        writer.println(
                prefix + pxToDpStr("getWorkspaceSpringLoadScale()", getWorkspaceSpringLoadScale()));
                prefix + pxToDpStr("getWorkspaceSpringLoadScale()", getWorkspaceSpringLoadScale()));
    }
    }
+97 −104
Original line number Original line Diff line number Diff line
@@ -39,8 +39,6 @@ import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.testing.TestProtocol;


import java.util.Arrays;

/*
/*
 * The top bar containing various drop targets: Delete/App Info/Uninstall.
 * The top bar containing various drop targets: Delete/App Info/Uninstall.
 */
 */
@@ -53,6 +51,8 @@ public class DropTargetBar extends FrameLayout
    private final Runnable mFadeAnimationEndRunnable =
    private final Runnable mFadeAnimationEndRunnable =
            () -> updateVisibility(DropTargetBar.this);
            () -> updateVisibility(DropTargetBar.this);


    private final Launcher mLauncher;

    @ViewDebug.ExportedProperty(category = "launcher")
    @ViewDebug.ExportedProperty(category = "launcher")
    protected boolean mDeferOnDragEnd;
    protected boolean mDeferOnDragEnd;


@@ -60,16 +60,19 @@ public class DropTargetBar extends FrameLayout
    protected boolean mVisible = false;
    protected boolean mVisible = false;


    private ButtonDropTarget[] mDropTargets;
    private ButtonDropTarget[] mDropTargets;
    private ButtonDropTarget[] mTempTargets;
    private ViewPropertyAnimator mCurrentAnimation;
    private ViewPropertyAnimator mCurrentAnimation;


    private boolean mIsVertical = true;
    private boolean mIsVertical = true;


    public DropTargetBar(Context context, AttributeSet attrs) {
    public DropTargetBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        super(context, attrs);
        mLauncher = Launcher.getLauncher(context);
    }
    }


    public DropTargetBar(Context context, AttributeSet attrs, int defStyle) {
    public DropTargetBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        super(context, attrs, defStyle);
        mLauncher = Launcher.getLauncher(context);
    }
    }


    @Override
    @Override
@@ -80,12 +83,13 @@ public class DropTargetBar extends FrameLayout
            mDropTargets[i] = (ButtonDropTarget) getChildAt(i);
            mDropTargets[i] = (ButtonDropTarget) getChildAt(i);
            mDropTargets[i].setDropTargetBar(this);
            mDropTargets[i].setDropTargetBar(this);
        }
        }
        mTempTargets = new ButtonDropTarget[getChildCount()];
    }
    }


    @Override
    @Override
    public void setInsets(Rect insets) {
    public void setInsets(Rect insets) {
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
        DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile();
        DeviceProfile grid = mLauncher.getDeviceProfile();
        mIsVertical = grid.isVerticalBarLayout();
        mIsVertical = grid.isVerticalBarLayout();


        lp.leftMargin = insets.left;
        lp.leftMargin = insets.left;
@@ -116,10 +120,15 @@ public class DropTargetBar extends FrameLayout
        lp.height = grid.dropTargetBarSizePx;
        lp.height = grid.dropTargetBarSizePx;
        lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
        lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;


        DeviceProfile dp = mLauncher.getDeviceProfile();
        int horizontalPadding = dp.dropTargetHorizontalPaddingPx;
        int verticalPadding = dp.dropTargetVerticalPaddingPx;
        setLayoutParams(lp);
        setLayoutParams(lp);
        for (ButtonDropTarget button : mDropTargets) {
        for (ButtonDropTarget button : mDropTargets) {
            button.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.dropTargetTextSizePx);
            button.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.dropTargetTextSizePx);
            button.setToolTipLocation(tooltipLocation);
            button.setToolTipLocation(tooltipLocation);
            button.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
                    verticalPadding);
        }
        }
    }
    }


@@ -135,36 +144,69 @@ public class DropTargetBar extends FrameLayout
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);


        int visibleCount = getVisibleButtonsCount();
        int visibleCount = getVisibleButtons(mTempTargets);
        if (visibleCount > 0) {
        if (visibleCount == 1) {
            int availableWidth = width / visibleCount;
            int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST);
            boolean textVisible = true;
            boolean textResized = false;
            float textSize = mDropTargets[0].getTextSize();
            for (ButtonDropTarget button : mDropTargets) {
                if (button.getVisibility() == GONE) {
                    continue;
                }
                if (button.isTextTruncated(availableWidth)) {
                    textSize = Math.min(textSize, button.resizeTextToFit(availableWidth));
                    textResized = true;
                }
                textVisible = textVisible && !button.isTextTruncated(availableWidth);
            }


            if (textResized) {
            ButtonDropTarget firstButton = mTempTargets[0];
                for (ButtonDropTarget button : mDropTargets) {
            firstButton.setTextVisible(true);
                    button.setTextSize(textSize);
            firstButton.setIconVisible(true);
                }
            firstButton.measure(widthSpec, heightSpec);
        } else if (visibleCount == 2) {
            DeviceProfile dp = mLauncher.getDeviceProfile();
            int verticalPadding = dp.dropTargetVerticalPaddingPx;
            int horizontalPadding = dp.dropTargetHorizontalPaddingPx;

            ButtonDropTarget firstButton = mTempTargets[0];
            firstButton.setTextVisible(true);
            firstButton.setIconVisible(true);
            firstButton.setTextMultiLine(false);
            // Reset second button padding in case it was previously changed to multi-line text.
            firstButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
                    verticalPadding);

            ButtonDropTarget secondButton = mTempTargets[1];
            secondButton.setTextVisible(true);
            secondButton.setIconVisible(true);
            secondButton.setTextMultiLine(false);
            // Reset second button padding in case it was previously changed to multi-line text.
            secondButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
                    verticalPadding);

            float scale = dp.getWorkspaceSpringLoadScale();
            int scaledPanelWidth = (int) (dp.getCellLayoutWidth() * scale);

            int availableWidth;
            if (dp.isTwoPanels) {
                // Both buttons for two panel fit to the width of one Cell Layout (less
                // half of the center gap between the buttons).
                int halfButtonGap = dp.dropTargetGapPx / 2;
                availableWidth = scaledPanelWidth - halfButtonGap / 2;
            } else {
                // Both buttons plus the button gap do not display past the edge of the scaled
                // workspace.
                availableWidth = (scaledPanelWidth - dp.dropTargetGapPx) / 2;
            }
            }


            int widthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
            int widthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
            int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
            firstButton.measure(widthSpec, heightSpec);
            for (ButtonDropTarget button : mDropTargets) {
            secondButton.measure(widthSpec, heightSpec);
                if (button.getVisibility() != GONE) {

                    button.setTextVisible(textVisible);
            if (!mIsVertical) {
                    button.measure(widthSpec, heightSpec);
                // Remove icons and put the button's text on two lines if text is truncated.
                if (firstButton.isTextTruncated(availableWidth)) {
                    firstButton.setIconVisible(false);
                    firstButton.setTextMultiLine(true);
                    firstButton.setPadding(horizontalPadding, verticalPadding / 2,
                            horizontalPadding, verticalPadding / 2);
                }
                if (secondButton.isTextTruncated(availableWidth)) {
                    secondButton.setIconVisible(false);
                    secondButton.setTextMultiLine(true);
                    secondButton.setPadding(horizontalPadding, verticalPadding / 2,
                            horizontalPadding, verticalPadding / 2);
                }
                }
            }
            }
        }
        }
@@ -173,98 +215,49 @@ public class DropTargetBar extends FrameLayout


    @Override
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int visibleCount = getVisibleButtonsCount();
        int visibleCount = getVisibleButtons(mTempTargets);
        if (visibleCount == 0) {
        if (visibleCount == 0) {
            return;
            return;
        }
        }


        Launcher launcher = Launcher.getLauncher(getContext());
        DeviceProfile dp = mLauncher.getDeviceProfile();
        Workspace<?> workspace = launcher.getWorkspace();
        // Center vertical bar over scaled workspace, accounting for hotseat offset.
        DeviceProfile dp = launcher.getDeviceProfile();
        float scale = dp.getWorkspaceSpringLoadScale();
        int buttonHorizontalPadding = dp.dropTargetHorizontalPaddingPx;
        Workspace<?> ws = mLauncher.getWorkspace();
        int buttonVerticalPadding = dp.dropTargetVerticalPaddingPx;
        int barCenter;
        int barCenter = (right - left) / 2;
        if (dp.isTwoPanels) {

            barCenter = (right - left) / 2;
        ButtonDropTarget[] visibleButtons = Arrays.stream(mDropTargets)
        } else {
                .filter(b -> b.getVisibility() != GONE)
            int workspaceCenter = (ws.getLeft() + ws.getRight()) / 2;
                .toArray(ButtonDropTarget[]::new);
            int cellLayoutCenter = ((dp.getInsets().left + dp.workspacePadding.left) + (dp.widthPx
        Arrays.stream(visibleButtons).forEach(
                    - dp.getInsets().right - dp.workspacePadding.right)) / 2;
                b -> b.setPadding(buttonHorizontalPadding, buttonVerticalPadding,
            int cellLayoutCenterOffset = (int) ((cellLayoutCenter - workspaceCenter) * scale);
                        buttonHorizontalPadding, buttonVerticalPadding));
            barCenter = workspaceCenter + cellLayoutCenterOffset - left;
        }


        if (visibleCount == 1) {
        if (visibleCount == 1) {
            ButtonDropTarget button = visibleButtons[0];
            ButtonDropTarget button = mTempTargets[0];
            button.layout(barCenter - (button.getMeasuredWidth() / 2), 0,
            button.layout(barCenter - (button.getMeasuredWidth() / 2), 0,
                    barCenter + (button.getMeasuredWidth() / 2), button.getMeasuredHeight());
                    barCenter + (button.getMeasuredWidth() / 2), button.getMeasuredHeight());
        } else if (visibleCount == 2) {
        } else if (visibleCount == 2) {
            int buttonGap = dp.dropTargetGapPx;
            int buttonGap = dp.dropTargetGapPx;


            if (dp.isTwoPanels) {
            ButtonDropTarget leftButton = mTempTargets[0];
                ButtonDropTarget leftButton = visibleButtons[0];
            leftButton.layout(barCenter - leftButton.getMeasuredWidth() - (buttonGap / 2), 0,
            leftButton.layout(barCenter - leftButton.getMeasuredWidth() - (buttonGap / 2), 0,
                    barCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
                    barCenter - (buttonGap / 2), leftButton.getMeasuredHeight());


                ButtonDropTarget rightButton = visibleButtons[1];
            ButtonDropTarget rightButton = mTempTargets[1];
            rightButton.layout(barCenter + (buttonGap / 2), 0,
            rightButton.layout(barCenter + (buttonGap / 2), 0,
                        barCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
                    barCenter + (buttonGap / 2) + rightButton.getMeasuredWidth(),
                    rightButton.getMeasuredHeight());
                    rightButton.getMeasuredHeight());
            } else if (dp.isTablet) {
                int numberOfMargins = visibleCount - 1;
                int buttonWidths = Arrays.stream(mDropTargets)
                        .filter(b -> b.getVisibility() != GONE)
                        .mapToInt(ButtonDropTarget::getMeasuredWidth)
                        .sum();
                int totalWidth = buttonWidths + (numberOfMargins * buttonGap);
                int buttonsStartMargin = barCenter - (totalWidth / 2);

                int start = buttonsStartMargin;
                for (ButtonDropTarget button : visibleButtons) {
                    int margin = (start != buttonsStartMargin) ? buttonGap : 0;
                    button.layout(start + margin, 0, start + margin + button.getMeasuredWidth(),
                            button.getMeasuredHeight());
                    start += button.getMeasuredWidth() + margin;
                }
            } else if (mIsVertical) {
                // Center buttons over workspace, not screen.
                int verticalCenter = (workspace.getRight() - workspace.getLeft()) / 2;
                ButtonDropTarget leftButton = visibleButtons[0];
                leftButton.layout(verticalCenter - leftButton.getMeasuredWidth() - (buttonGap / 2),
                        0, verticalCenter - (buttonGap / 2), leftButton.getMeasuredHeight());

                ButtonDropTarget rightButton = visibleButtons[1];
                rightButton.layout(verticalCenter + (buttonGap / 2), 0,
                        verticalCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
                        rightButton.getMeasuredHeight());
            } else if (dp.isPhone) {
                // Buttons aligned to outer edges of scaled workspace.
                float scale = dp.getWorkspaceSpringLoadScale();

                int workspaceWidth = (int) (launcher.getWorkspace().getNormalChildWidth() * scale);
                int start = barCenter - (workspaceWidth / 2);
                int end = barCenter + (workspaceWidth / 2);

                ButtonDropTarget leftButton = visibleButtons[0];
                ButtonDropTarget rightButton = visibleButtons[1];

                // If the text within the buttons is too long, the buttons can overlap
                int overlap = start + leftButton.getMeasuredWidth() + rightButton.getMeasuredWidth()
                        - end;
                if (overlap > 0) {
                    end += overlap;
                }

                leftButton.layout(start, 0, start + leftButton.getMeasuredWidth(),
                        leftButton.getMeasuredHeight());
                rightButton.layout(end - rightButton.getMeasuredWidth(), 0, end,
                        rightButton.getMeasuredHeight());
            }
        }
        }
    }
    }


    private int getVisibleButtonsCount() {
    private int getVisibleButtons(ButtonDropTarget[] outVisibleButtons) {
        int visibleCount = 0;
        int visibleCount = 0;
        for (ButtonDropTarget buttons : mDropTargets) {
        for (ButtonDropTarget button : mDropTargets) {
            if (buttons.getVisibility() != GONE) {
            if (button.getVisibility() != GONE) {
                outVisibleButtons[visibleCount] = button;
                visibleCount++;
                visibleCount++;
            }
            }
        }
        }