11fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi/* 21fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Copyright (C) 2015 The Android Open Source Project 31fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * 41fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Licensed under the Apache License, Version 2.0 (the "License"); 51fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * you may not use this file except in compliance with the License. 61fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * You may obtain a copy of the License at 71fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * 81fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * http://www.apache.org/licenses/LICENSE-2.0 91fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * 101fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Unless required by applicable law or agreed to in writing, software 111fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * distributed under the License is distributed on an "AS IS" BASIS, 121fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * See the License for the specific language governing permissions and 141fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * limitations under the License. 151fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 161fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 17737af724eb31f513386e91ee5510cc6991350937Jorim Jaggipackage com.android.internal.policy; 181fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 19f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ngimport static android.view.WindowManager.DOCKED_INVALID; 20f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ngimport static android.view.WindowManager.DOCKED_LEFT; 21f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ngimport static android.view.WindowManager.DOCKED_RIGHT; 22f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng 231fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggiimport android.content.Context; 2419cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.content.res.Configuration; 25737af724eb31f513386e91ee5510cc6991350937Jorim Jaggiimport android.content.res.Resources; 2681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggiimport android.graphics.Rect; 2719cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.hardware.display.DisplayManager; 2819cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.view.Display; 2919cf2972582198484816ac15ba83a4f46946082bJorim Jaggiimport android.view.DisplayInfo; 301fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 311fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggiimport java.util.ArrayList; 321fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 331fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi/** 341fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Calculates the snap targets and the snap position given a position and a velocity. All positions 351fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * here are to be interpreted as the left/top edge of the divider rectangle. 36737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi * 37737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi * @hide 381fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 391fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggipublic class DividerSnapAlgorithm { 401fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 41df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private static final int MIN_FLING_VELOCITY_DP_PER_SECOND = 400; 42df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private static final int MIN_DISMISS_VELOCITY_DP_PER_SECOND = 600; 43df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 4481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 4581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 3 snap targets: left/top has 16:9 ratio (for videos), 1:1, and right/bottom has 16:9 ratio 4681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 4781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_MODE_16_9 = 0; 4881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 4981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 5081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 3 snap targets: fixed ratio, 1:1, (1 - fixed ratio) 5181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 5281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_FIXED_RATIO = 1; 5381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 5481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 5581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 1 snap target: 1:1 5681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 5781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_ONLY_1_1 = 2; 5881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 59e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng /** 60e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng * 1 snap target: minimized height, (1 - minimized height) 61e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng */ 62e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng private static final int SNAP_MODE_MINIMIZED = 3; 63e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng 64737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi private final float mMinFlingVelocityPxPerSecond; 65df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private final float mMinDismissVelocityPxPerSecond; 6681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mDisplayWidth; 6781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mDisplayHeight; 681fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final int mDividerSize; 6981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final ArrayList<SnapTarget> mTargets = new ArrayList<>(); 7081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final Rect mInsets = new Rect(); 7181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mSnapMode; 7219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private final int mMinimalSizeResizableTask; 73e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng private final int mTaskHeightInMinimizedMode; 7481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final float mFixedRatio; 751b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private boolean mIsHorizontalDivision; 761fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 771fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** The first target which is still splitting the screen */ 781fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mFirstSplitTarget; 791fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 801fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** The last target which is still splitting the screen */ 811fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mLastSplitTarget; 821fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 831fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mDismissStartTarget; 841fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mDismissEndTarget; 85d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi private final SnapTarget mMiddleTarget; 861fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 8719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi public static DividerSnapAlgorithm create(Context ctx, Rect insets) { 8819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi DisplayInfo displayInfo = new DisplayInfo(); 8919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi ctx.getSystemService(DisplayManager.class).getDisplay( 9019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo); 9119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int dividerWindowWidth = ctx.getResources().getDimensionPixelSize( 9219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi com.android.internal.R.dimen.docked_stack_divider_thickness); 9319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int dividerInsets = ctx.getResources().getDimensionPixelSize( 9419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi com.android.internal.R.dimen.docked_stack_divider_insets); 9519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi return new DividerSnapAlgorithm(ctx.getResources(), 9619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi displayInfo.logicalWidth, displayInfo.logicalHeight, 9719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi dividerWindowWidth - 2 * dividerInsets, 989832f8f463a7d5448af2294bce05eac85f4dbef0Winson ctx.getApplicationContext().getResources().getConfiguration().orientation 9919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi == Configuration.ORIENTATION_PORTRAIT, 10019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi insets); 10119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 10219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi 103df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, 104df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi boolean isHorizontalDivision, Rect insets) { 105f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets, 106f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng DOCKED_INVALID, false); 107e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng } 108e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng 109e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, 110303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng boolean isHorizontalDivision, Rect insets, int dockSide) { 111303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng this(res, displayWidth, displayHeight, dividerSize, isHorizontalDivision, insets, 112303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng dockSide, false); 113303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng } 114303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng 115303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, 116f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng boolean isHorizontalDivision, Rect insets, int dockSide, boolean isMinimizedMode) { 117df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mMinFlingVelocityPxPerSecond = 118df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi MIN_FLING_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density; 119df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mMinDismissVelocityPxPerSecond = 120df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi MIN_DISMISS_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density; 1211fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDividerSize = dividerSize; 12281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mDisplayWidth = displayWidth; 12381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mDisplayHeight = displayHeight; 1241b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi mIsHorizontalDivision = isHorizontalDivision; 12581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mInsets.set(insets); 126e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng mSnapMode = isMinimizedMode ? SNAP_MODE_MINIMIZED : 127e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng res.getInteger(com.android.internal.R.integer.config_dockedStackDividerSnapMode); 128737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi mFixedRatio = res.getFraction( 12981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1); 13019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi mMinimalSizeResizableTask = res.getDimensionPixelSize( 13119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi com.android.internal.R.dimen.default_minimal_size_resizable_task); 132e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng mTaskHeightInMinimizedMode = res.getDimensionPixelSize( 133e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng com.android.internal.R.dimen.task_height_of_minimized_mode); 134f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng calculateTargets(isHorizontalDivision, dockSide); 1351fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mFirstSplitTarget = mTargets.get(1); 1361fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mLastSplitTarget = mTargets.get(mTargets.size() - 2); 1371fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDismissStartTarget = mTargets.get(0); 1381fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDismissEndTarget = mTargets.get(mTargets.size() - 1); 139d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi mMiddleTarget = mTargets.get(mTargets.size() / 2); 1401fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1411fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 14219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi /** 14319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * @return whether it's feasible to enable split screen in the current configuration, i.e. when 14419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * snapping in the middle both tasks are larger than the minimal task size. 14519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi */ 14619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi public boolean isSplitScreenFeasible() { 14719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int statusBarSize = mInsets.top; 14819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right; 14919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int size = mIsHorizontalDivision 15019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi ? mDisplayHeight 15119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi : mDisplayWidth; 15219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int availableSpace = size - navBarSize - statusBarSize - mDividerSize; 15319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi return availableSpace / 2 >= mMinimalSizeResizableTask; 15419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 15519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi 1561fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public SnapTarget calculateSnapTarget(int position, float velocity) { 157df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi return calculateSnapTarget(position, velocity, true /* hardDismiss */); 158df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 159df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 160df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi /** 161df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param position the top/left position of the divider 162df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param velocity current dragging velocity 163df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param hardDismiss if set, make it a bit harder to get reach the dismiss targets 164df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi */ 165df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public SnapTarget calculateSnapTarget(int position, float velocity, boolean hardDismiss) { 166df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (position < mFirstSplitTarget.position && velocity < -mMinDismissVelocityPxPerSecond) { 1671fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mDismissStartTarget; 1681fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 169df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (position > mLastSplitTarget.position && velocity > mMinDismissVelocityPxPerSecond) { 1701fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mDismissEndTarget; 1711fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 172df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (Math.abs(velocity) < mMinFlingVelocityPxPerSecond) { 173df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi return snap(position, hardDismiss); 174df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 1751fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi if (velocity < 0) { 1761fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mFirstSplitTarget; 1771fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } else { 1781fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mLastSplitTarget; 1791fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1801fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1811fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 182737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi public SnapTarget calculateNonDismissingSnapTarget(int position) { 183df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi SnapTarget target = snap(position, false /* hardDismiss */); 184737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi if (target == mDismissStartTarget) { 185737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return mFirstSplitTarget; 186737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } else if (target == mDismissEndTarget) { 187737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return mLastSplitTarget; 188737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } else { 189737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return target; 190737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } 191737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } 192737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi 1935098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi public float calculateDismissingFraction(int position) { 1945098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi if (position < mFirstSplitTarget.position) { 1951b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return 1f - (float) (position - getStartInset()) 1961b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi / (mFirstSplitTarget.position - getStartInset()); 1975098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } else if (position > mLastSplitTarget.position) { 1985098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return (float) (position - mLastSplitTarget.position) 19981ba11eccbc2519338782100c13cf4a5909ad6beJorim Jaggi / (mDismissEndTarget.position - mLastSplitTarget.position - mDividerSize); 2005098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 2015098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return 0f; 2025098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 2035098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi 2045098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi public SnapTarget getClosestDismissTarget(int position) { 2058f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi if (position < mFirstSplitTarget.position) { 2068f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi return mDismissStartTarget; 2078f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi } else if (position > mLastSplitTarget.position) { 2088f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi return mDismissEndTarget; 2098f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi } else if (position - mDismissStartTarget.position 2108f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi < mDismissEndTarget.position - position) { 2115098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return mDismissStartTarget; 2125098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } else { 2135098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return mDismissEndTarget; 2145098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 2155098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 2165098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi 217e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getFirstSplitTarget() { 218e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mFirstSplitTarget; 219e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 220e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 221e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getLastSplitTarget() { 222e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mLastSplitTarget; 223e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 224e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 225e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getDismissStartTarget() { 226e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mDismissStartTarget; 227e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 228e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 229e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getDismissEndTarget() { 230e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mDismissEndTarget; 231e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 232e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 2331b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private int getStartInset() { 2341b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi if (mIsHorizontalDivision) { 2351b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.top; 2361b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } else { 2371b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.left; 2381b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2391b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2401b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi 2411b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private int getEndInset() { 2421b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi if (mIsHorizontalDivision) { 2431b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.bottom; 2441b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } else { 2451b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.right; 2461b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2471b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 2481b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi 249df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private SnapTarget snap(int position, boolean hardDismiss) { 2501fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int minIndex = -1; 251df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi float minDistance = Float.MAX_VALUE; 2521fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int size = mTargets.size(); 2531fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi for (int i = 0; i < size; i++) { 254df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi SnapTarget target = mTargets.get(i); 255df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi float distance = Math.abs(position - target.position); 256df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (hardDismiss) { 257df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi distance /= target.distanceMultiplier; 258df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 2591fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi if (distance < minDistance) { 2601fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi minIndex = i; 2611fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi minDistance = distance; 2621fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2631fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2641fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mTargets.get(minIndex); 2651fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2661fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 267f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng private void calculateTargets(boolean isHorizontalDivision, int dockedSide) { 26881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.clear(); 2691fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int dividerMax = isHorizontalDivision 27081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight 27181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth; 272e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right; 273303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng int startPos = -mDividerSize; 274303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng if (dockedSide == DOCKED_RIGHT) { 275303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng startPos += mInsets.left; 276303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng } 277303071233bff3cd4242f24d00a104a14091d54e0Matthew Ng mTargets.add(new SnapTarget(startPos, startPos, SnapTarget.FLAG_DISMISS_START, 2788563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 0.35f)); 27981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi switch (mSnapMode) { 28081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_MODE_16_9: 28119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addRatio16_9Targets(isHorizontalDivision, dividerMax); 28281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 28381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_FIXED_RATIO: 28419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addFixedDivisionTargets(isHorizontalDivision, dividerMax); 28581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 28681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_ONLY_1_1: 28781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addMiddleTarget(isHorizontalDivision); 28881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 289e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng case SNAP_MODE_MINIMIZED: 290f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng addMinimizedTarget(isHorizontalDivision, dockedSide); 291e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng break; 29281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 2938563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(dividerMax - navBarSize, dividerMax, 2948563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi SnapTarget.FLAG_DISMISS_END, 0.35f)); 29581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 2961fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 29719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition, 29819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int bottomPosition, int dividerMax) { 29919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi maybeAddTarget(topPosition, topPosition - mInsets.top); 30019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addMiddleTarget(isHorizontalDivision); 30119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom 30219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi - (bottomPosition + mDividerSize)); 30319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 3048563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 30519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) { 30681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int start = isHorizontalDivision ? mInsets.top : mInsets.left; 30781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int end = isHorizontalDivision 30881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight - mInsets.bottom 30981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth - mInsets.right; 3108563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int size = (int) (mFixedRatio * (end - start)) - mDividerSize / 2; 3118563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int topPosition = start + size; 3128563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int bottomPosition = end - size - mDividerSize; 31319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); 31481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 31581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 31619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void addRatio16_9Targets(boolean isHorizontalDivision, int dividerMax) { 31781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int start = isHorizontalDivision ? mInsets.top : mInsets.left; 31881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int end = isHorizontalDivision 31981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight - mInsets.bottom 32081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth - mInsets.right; 32181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int startOther = isHorizontalDivision ? mInsets.left : mInsets.top; 32281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int endOther = isHorizontalDivision 32381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayWidth - mInsets.right 32481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayHeight - mInsets.bottom; 32581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi float size = 9.0f / 16.0f * (endOther - startOther); 32681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int sizeInt = (int) Math.floor(size); 32719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int topPosition = start + sizeInt; 32819cf2972582198484816ac15ba83a4f46946082bJorim Jaggi int bottomPosition = end - sizeInt - mDividerSize; 32919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax); 33019cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 33119cf2972582198484816ac15ba83a4f46946082bJorim Jaggi 33219cf2972582198484816ac15ba83a4f46946082bJorim Jaggi /** 33319cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * Adds a target at {@param position} but only if the area with size of {@param smallerSize} 33419cf2972582198484816ac15ba83a4f46946082bJorim Jaggi * meets the minimal size requirement. 33519cf2972582198484816ac15ba83a4f46946082bJorim Jaggi */ 33619cf2972582198484816ac15ba83a4f46946082bJorim Jaggi private void maybeAddTarget(int position, int smallerSize) { 33719cf2972582198484816ac15ba83a4f46946082bJorim Jaggi if (smallerSize >= mMinimalSizeResizableTask) { 3388563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE)); 33919cf2972582198484816ac15ba83a4f46946082bJorim Jaggi } 34081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 34181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 34281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void addMiddleTarget(boolean isHorizontalDivision) { 3438563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 3448563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mInsets, mDisplayWidth, mDisplayHeight, mDividerSize); 3458563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE)); 346e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng } 347e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng 348f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng private void addMinimizedTarget(boolean isHorizontalDivision, int dockedSide) { 3497ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng // In portrait offset the position by the statusbar height, in landscape add the statusbar 3507ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng // height as well to match portrait offset 3517ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng int position = mTaskHeightInMinimizedMode + mInsets.top; 3527ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng if (!isHorizontalDivision) { 353f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng if (dockedSide == DOCKED_LEFT) { 354f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng position += mInsets.left; 355f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng } else if (dockedSide == DOCKED_RIGHT) { 35662c7846bf89c170f1f41624866d3249a4e30a33aMatthew Ng position = mDisplayWidth - position - mInsets.right - mDividerSize; 357f59a4132e8d65ab253f3f4cdd1e69f3f99526ba8Matthew Ng } 3587ccdb52fc98da546bdd565d0757f1fa09522862dMatthew Ng } 359e15352e516fb6ecde12866f0eb27c32470ddbdedMatthew Ng mTargets.add(new SnapTarget(position, position, SnapTarget.FLAG_NONE)); 3601fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 3611fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 362d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi public SnapTarget getMiddleTarget() { 363d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi return mMiddleTarget; 364d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi } 365d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi 36650cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi public SnapTarget getNextTarget(SnapTarget snapTarget) { 36750cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi int index = mTargets.indexOf(snapTarget); 36850cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi if (index != -1 && index < mTargets.size() - 1) { 36950cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return mTargets.get(index + 1); 37050cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 37150cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return snapTarget; 37250cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 37350cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi 37450cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi public SnapTarget getPreviousTarget(SnapTarget snapTarget) { 37550cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi int index = mTargets.indexOf(snapTarget); 37650cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi if (index != -1 && index > 0) { 37750cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return mTargets.get(index - 1); 37850cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 37950cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return snapTarget; 38050cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 38150cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi 3826317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng /** 3836317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng * @return whether or not there are more than 1 split targets that do not include the two 3846317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng * dismiss targets, used in deciding to display the middle target for accessibility 3856317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng */ 3866317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng public boolean showMiddleSplitTargetForAccessibility() { 3876317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng return (mTargets.size() - 2) > 1; 3886317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng } 3896317df6e1e7bc1338089c8402efadccb39201abaMatthew Ng 390ce9630da86342c7bf30f00d1ced34a1d051c55baWinson public boolean isFirstSplitTargetAvailable() { 391ce9630da86342c7bf30f00d1ced34a1d051c55baWinson return mFirstSplitTarget != mMiddleTarget; 392ce9630da86342c7bf30f00d1ced34a1d051c55baWinson } 393ce9630da86342c7bf30f00d1ced34a1d051c55baWinson 394ce9630da86342c7bf30f00d1ced34a1d051c55baWinson public boolean isLastSplitTargetAvailable() { 395ce9630da86342c7bf30f00d1ced34a1d051c55baWinson return mLastSplitTarget != mMiddleTarget; 396ce9630da86342c7bf30f00d1ced34a1d051c55baWinson } 397ce9630da86342c7bf30f00d1ced34a1d051c55baWinson 3981fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** 399a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li * Cycles through all non-dismiss targets with a stepping of {@param increment}. It moves left 400a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li * if {@param increment} is negative and moves right otherwise. 401a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li */ 402a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li public SnapTarget cycleNonDismissTarget(SnapTarget snapTarget, int increment) { 403a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li int index = mTargets.indexOf(snapTarget); 404a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li if (index != -1) { 405a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li SnapTarget newTarget = mTargets.get((index + mTargets.size() + increment) 406a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li % mTargets.size()); 407a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li if (newTarget == mDismissStartTarget) { 408a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return mLastSplitTarget; 409a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } else if (newTarget == mDismissEndTarget) { 410a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return mFirstSplitTarget; 411a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } else { 412a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return newTarget; 413a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } 414a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } 415a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li return snapTarget; 416a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li } 417a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li 418a212999f245032f033e6a0993fd2be9832a9b9ccMuyuan Li /** 4191fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Represents a snap target for the divider. 4201fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 4211fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static class SnapTarget { 4221fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_NONE = 0; 4231fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 4241fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** If the divider reaches this value, the left/top task should be dismissed. */ 4251fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_DISMISS_START = 1; 4261fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 4271fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** If the divider reaches this value, the right/bottom task should be dismissed */ 4281fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_DISMISS_END = 2; 4291fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 4308563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi /** Position of this snap target. The right/bottom edge of the top/left task snaps here. */ 4311fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public final int position; 4328563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 4338563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi /** 4348563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi * Like {@link #position}, but used to calculate the task bounds which might be different 4358563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi * from the stack bounds. 4368563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi */ 4378563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi public final int taskPosition; 4388563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi 4391fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public final int flag; 4401fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 441df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi /** 442df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * Multiplier used to calculate distance to snap position. The lower this value, the harder 443df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * it's to snap on this target 444df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi */ 445df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private final float distanceMultiplier; 446df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 4478563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi public SnapTarget(int position, int taskPosition, int flag) { 4488563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi this(position, taskPosition, flag, 1f); 449df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 450df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 4518563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi public SnapTarget(int position, int taskPosition, int flag, float distanceMultiplier) { 4521fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi this.position = position; 4538563943bd39107b5a7ff9ea475592d0040423ba1Jorim Jaggi this.taskPosition = taskPosition; 4541fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi this.flag = flag; 455df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi this.distanceMultiplier = distanceMultiplier; 4561fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 4571fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 4581fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi} 459