/* * Copyright (C) 2019 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.touch; import static android.widget.ListPopupWindow.WRAP_CONTENT; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN; import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.ShapeDrawable; import android.util.FloatProperty; import android.view.MotionEvent; import android.view.Surface; import android.view.VelocityTracker; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.widget.LinearLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.views.BaseDragLayer; import java.util.Collections; import java.util.List; public class LandscapePagedViewHandler implements PagedOrientationHandler { @Override public T getPrimaryValue(T x, T y) { return y; } @Override public T getSecondaryValue(T x, T y) { return x; } @Override public int getPrimaryValue(int x, int y) { return y; } @Override public int getSecondaryValue(int x, int y) { return x; } @Override public float getPrimaryValue(float x, float y) { return y; } @Override public float getSecondaryValue(float x, float y) { return x; } @Override public boolean isLayoutNaturalToLauncher() { return false; } @Override public void adjustFloatingIconStartVelocity(PointF velocity) { float oldX = velocity.x; float oldY = velocity.y; velocity.set(-oldY, oldX); } @Override public void set(T target, Int2DAction action, int param) { action.call(target, 0, param); } @Override public void set(T target, Float2DAction action, float param) { action.call(target, 0, param); } @Override public void setSecondary(T target, Float2DAction action, float param) { action.call(target, param, 0); } @Override public float getPrimaryDirection(MotionEvent event, int pointerIndex) { return event.getY(pointerIndex); } @Override public float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId) { return velocityTracker.getYVelocity(pointerId); } @Override public int getMeasuredSize(View view) { return view.getMeasuredHeight(); } @Override public int getPrimarySize(View view) { return view.getHeight(); } @Override public float getPrimarySize(RectF rect) { return rect.height(); } @Override public float getStart(RectF rect) { return rect.top; } @Override public float getEnd(RectF rect) { return rect.bottom; } @Override public int getClearAllSidePadding(View view, boolean isRtl) { return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2; } @Override public int getSecondaryDimension(View view) { return view.getWidth(); } @Override public FloatProperty getPrimaryViewTranslate() { return VIEW_TRANSLATE_Y; } @Override public FloatProperty getSecondaryViewTranslate() { return VIEW_TRANSLATE_X; } @Override public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition, DeviceProfile dp) { // Don't use device profile here because we know we're in fake landscape, only split option // available is top/left if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) { // Top (visually left) side return SPLIT_TRANSLATE_PRIMARY_NEGATIVE; } throw new IllegalStateException("Invalid split stage position: " + splitPosition.mStagePosition); } @Override public int getPrimaryScroll(View view) { return view.getScrollY(); } @Override public float getPrimaryScale(View view) { return view.getScaleY(); } @Override public void setMaxScroll(AccessibilityEvent event, int maxScroll) { event.setMaxScrollY(maxScroll); } @Override public boolean getRecentsRtlSetting(Resources resources) { return !Utilities.isRtl(resources); } @Override public float getDegreesRotated() { return 90; } @Override public int getRotation() { return Surface.ROTATION_90; } @Override public int getChildStart(View view) { return view.getTop(); } @Override public float getChildStartWithTranslation(View view) { return view.getTop() + view.getTranslationY(); } @Override public int getCenterForPage(View view, Rect insets) { return (view.getPaddingLeft() + view.getMeasuredWidth() + insets.left - insets.right - view.getPaddingRight()) / 2; } @Override public int getScrollOffsetStart(View view, Rect insets) { return insets.top + view.getPaddingTop(); } @Override public int getScrollOffsetEnd(View view, Rect insets) { return view.getHeight() - view.getPaddingBottom() - insets.bottom; } @Override public int getPrimaryTranslationDirectionFactor() { return -1; } public int getSecondaryTranslationDirectionFactor() { return 1; } @Override public int getSplitTranslationDirectionFactor(int stagePosition) { if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) { return -1; } else { return 1; } } @Override public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) { return translationOffset; } @Override public float getTaskMenuX(float x, View thumbnailView, int overScroll) { return thumbnailView.getMeasuredWidth() + x; } @Override public float getTaskMenuY(float y, View thumbnailView, int overScroll) { return y + overScroll; } @Override public int getTaskMenuWidth(View view) { return view.getMeasuredHeight(); } @Override public void setTaskOptionsMenuLayoutOrientation(DeviceProfile deviceProfile, LinearLayout taskMenuLayout, int dividerSpacing, ShapeDrawable dividerDrawable) { taskMenuLayout.setOrientation(LinearLayout.HORIZONTAL); dividerDrawable.setIntrinsicWidth(dividerSpacing); taskMenuLayout.setDividerDrawable(dividerDrawable); } @Override public void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp, LinearLayout viewGroup, DeviceProfile deviceProfile) { // Phone fake landscape viewGroup.setOrientation(LinearLayout.VERTICAL); lp.width = 0; lp.height = WRAP_CONTENT; lp.weight = 1; Utilities.setStartMarginForView(viewGroup.findViewById(R.id.text), 0); Utilities.setStartMarginForView(viewGroup.findViewById(R.id.icon), 0); } @Override public void setTaskMenuAroundTaskView(LinearLayout taskView, float margin) { BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskView.getLayoutParams(); lp.topMargin += margin; } @Override public PointF getAdditionalInsetForTaskMenu(float margin) { return new PointF(margin, 0); } /* ---------- The following are only used by TaskViewTouchHandler. ---------- */ @Override public SingleAxisSwipeDetector.Direction getUpDownSwipeDirection() { return HORIZONTAL; } @Override public int getUpDirection(boolean isRtl) { return isRtl ? SingleAxisSwipeDetector.DIRECTION_NEGATIVE : SingleAxisSwipeDetector.DIRECTION_POSITIVE; } @Override public boolean isGoingUp(float displacement, boolean isRtl) { return isRtl ? displacement < 0 : displacement > 0; } @Override public int getTaskDragDisplacementFactor(boolean isRtl) { return isRtl ? 1 : -1; } /* -------------------- */ @Override public ChildBounds getChildBounds(View child, int childStart, int pageCenter, boolean layoutChild) { final int childHeight = child.getMeasuredHeight(); final int childBottom = childStart + childHeight; final int childWidth = child.getMeasuredWidth(); final int childLeft = pageCenter - childWidth/ 2; if (layoutChild) { child.layout(childLeft, childStart, childLeft + childWidth, childBottom); } return new ChildBounds(childHeight, childWidth, childBottom, childLeft); } @SuppressWarnings("SuspiciousNameCombination") @Override public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) { return rect.left; } @Override public List getSplitPositionOptions(DeviceProfile dp) { // Add "left" side of phone which is actually the top return Collections.singletonList(new SplitPositionOption( R.drawable.ic_split_screen, R.string.split_screen_position_left, STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN)); } @Override public FloatProperty getSplitSelectTaskOffset(FloatProperty primary, FloatProperty secondary, DeviceProfile deviceProfile) { return primary; } }