DividerSnapAlgorithm.java revision 1b12ef55b74f47eedde8afe22b997d40c3668a31
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 191fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggiimport android.content.Context; 20737af724eb31f513386e91ee5510cc6991350937Jorim Jaggiimport android.content.res.Resources; 2181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggiimport android.graphics.Rect; 22df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggiimport android.util.Log; 231fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 241fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggiimport java.util.ArrayList; 251fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 261fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi/** 271fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Calculates the snap targets and the snap position given a position and a velocity. All positions 281fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * here are to be interpreted as the left/top edge of the divider rectangle. 29737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi * 30737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi * @hide 311fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 321fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggipublic class DividerSnapAlgorithm { 331fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 34df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private static final int MIN_FLING_VELOCITY_DP_PER_SECOND = 400; 35df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private static final int MIN_DISMISS_VELOCITY_DP_PER_SECOND = 600; 36df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 3781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 3881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 3 snap targets: left/top has 16:9 ratio (for videos), 1:1, and right/bottom has 16:9 ratio 3981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 4081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_MODE_16_9 = 0; 4181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 4281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 4381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 3 snap targets: fixed ratio, 1:1, (1 - fixed ratio) 4481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 4581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_FIXED_RATIO = 1; 4681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 4781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi /** 4881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi * 1 snap target: 1:1 4981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi */ 5081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private static final int SNAP_ONLY_1_1 = 2; 5181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 52737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi private final float mMinFlingVelocityPxPerSecond; 53df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private final float mMinDismissVelocityPxPerSecond; 5481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mDisplayWidth; 5581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mDisplayHeight; 561fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final int mDividerSize; 5781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final ArrayList<SnapTarget> mTargets = new ArrayList<>(); 5881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final Rect mInsets = new Rect(); 5981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final int mSnapMode; 6081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private final float mFixedRatio; 611b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private boolean mIsHorizontalDivision; 621fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 631fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** The first target which is still splitting the screen */ 641fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mFirstSplitTarget; 651fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 661fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** The last target which is still splitting the screen */ 671fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mLastSplitTarget; 681fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 691fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mDismissStartTarget; 701fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi private final SnapTarget mDismissEndTarget; 71d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi private final SnapTarget mMiddleTarget; 721fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 73df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize, 74df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi boolean isHorizontalDivision, Rect insets) { 75df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mMinFlingVelocityPxPerSecond = 76df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi MIN_FLING_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density; 77df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mMinDismissVelocityPxPerSecond = 78df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi MIN_DISMISS_VELOCITY_DP_PER_SECOND * res.getDisplayMetrics().density; 791fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDividerSize = dividerSize; 8081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mDisplayWidth = displayWidth; 8181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mDisplayHeight = displayHeight; 821b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi mIsHorizontalDivision = isHorizontalDivision; 8381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mInsets.set(insets); 84737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi mSnapMode = res.getInteger( 8581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi com.android.internal.R.integer.config_dockedStackDividerSnapMode); 86737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi mFixedRatio = res.getFraction( 8781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1); 8881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi calculateTargets(isHorizontalDivision); 891fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mFirstSplitTarget = mTargets.get(1); 901fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mLastSplitTarget = mTargets.get(mTargets.size() - 2); 911fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDismissStartTarget = mTargets.get(0); 921fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi mDismissEndTarget = mTargets.get(mTargets.size() - 1); 93d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi mMiddleTarget = mTargets.get(mTargets.size() / 2); 941fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 951fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 961fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public SnapTarget calculateSnapTarget(int position, float velocity) { 97df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi return calculateSnapTarget(position, velocity, true /* hardDismiss */); 98df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 99df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 100df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi /** 101df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param position the top/left position of the divider 102df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param velocity current dragging velocity 103df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * @param hardDismiss if set, make it a bit harder to get reach the dismiss targets 104df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi */ 105df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public SnapTarget calculateSnapTarget(int position, float velocity, boolean hardDismiss) { 106df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (position < mFirstSplitTarget.position && velocity < -mMinDismissVelocityPxPerSecond) { 1071fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mDismissStartTarget; 1081fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 109df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (position > mLastSplitTarget.position && velocity > mMinDismissVelocityPxPerSecond) { 1101fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mDismissEndTarget; 1111fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 112df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (Math.abs(velocity) < mMinFlingVelocityPxPerSecond) { 113df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi return snap(position, hardDismiss); 114df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 1151fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi if (velocity < 0) { 1161fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mFirstSplitTarget; 1171fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } else { 1181fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mLastSplitTarget; 1191fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1201fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 1211fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 122737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi public SnapTarget calculateNonDismissingSnapTarget(int position) { 123df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi SnapTarget target = snap(position, false /* hardDismiss */); 124737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi if (target == mDismissStartTarget) { 125737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return mFirstSplitTarget; 126737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } else if (target == mDismissEndTarget) { 127737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return mLastSplitTarget; 128737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } else { 129737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi return target; 130737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } 131737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi } 132737af724eb31f513386e91ee5510cc6991350937Jorim Jaggi 1335098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi public float calculateDismissingFraction(int position) { 1345098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi if (position < mFirstSplitTarget.position) { 1351b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return 1f - (float) (position - getStartInset()) 1361b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi / (mFirstSplitTarget.position - getStartInset()); 1375098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } else if (position > mLastSplitTarget.position) { 1385098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return (float) (position - mLastSplitTarget.position) 1391b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi / (mDismissEndTarget.position - getEndInset() 1401b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi - mLastSplitTarget.position - mDividerSize); 1415098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 1425098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return 0f; 1435098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 1445098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi 1455098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi public SnapTarget getClosestDismissTarget(int position) { 1468f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi if (position < mFirstSplitTarget.position) { 1478f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi return mDismissStartTarget; 1488f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi } else if (position > mLastSplitTarget.position) { 1498f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi return mDismissEndTarget; 1508f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi } else if (position - mDismissStartTarget.position 1518f8155ba8a1c66d539101e55f2d06ae0422682c0Jorim Jaggi < mDismissEndTarget.position - position) { 1525098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return mDismissStartTarget; 1535098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } else { 1545098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi return mDismissEndTarget; 1555098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 1565098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi } 1575098159ae31bc59aa3857fecb1847f8d7bb73e54Jorim Jaggi 158e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getFirstSplitTarget() { 159e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mFirstSplitTarget; 160e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 161e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 162e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getLastSplitTarget() { 163e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mLastSplitTarget; 164e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 165e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 166e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getDismissStartTarget() { 167e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mDismissStartTarget; 168e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 169e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 170e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi public SnapTarget getDismissEndTarget() { 171e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi return mDismissEndTarget; 172e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi } 173e435e982fa43832b183bac2d00d9415ac58ac06eJorim Jaggi 1741b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private int getStartInset() { 1751b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi if (mIsHorizontalDivision) { 1761b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.top; 1771b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } else { 1781b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.left; 1791b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 1801b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 1811b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi 1821b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi private int getEndInset() { 1831b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi if (mIsHorizontalDivision) { 1841b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.bottom; 1851b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } else { 1861b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi return mInsets.right; 1871b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 1881b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi } 1891b12ef55b74f47eedde8afe22b997d40c3668a31Jorim Jaggi 190df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private SnapTarget snap(int position, boolean hardDismiss) { 1911fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int minIndex = -1; 192df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi float minDistance = Float.MAX_VALUE; 1931fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int size = mTargets.size(); 1941fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi for (int i = 0; i < size; i++) { 195df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi SnapTarget target = mTargets.get(i); 196df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi float distance = Math.abs(position - target.position); 197df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi if (hardDismiss) { 198df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi distance /= target.distanceMultiplier; 199df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 2001fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi if (distance < minDistance) { 2011fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi minIndex = i; 2021fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi minDistance = distance; 2031fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2041fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2051fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi return mTargets.get(minIndex); 2061fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2071fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 20881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void calculateTargets(boolean isHorizontalDivision) { 20981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.clear(); 2101fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi int dividerMax = isHorizontalDivision 21181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight 21281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth; 213df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f)); 21481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi switch (mSnapMode) { 21581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_MODE_16_9: 21681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addRatio16_9Targets(isHorizontalDivision); 21781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 21881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_FIXED_RATIO: 21981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addFixedDivisionTargets(isHorizontalDivision); 22081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 22181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi case SNAP_ONLY_1_1: 22281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addMiddleTarget(isHorizontalDivision); 22381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi break; 22481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 225df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi mTargets.add(new SnapTarget(dividerMax, SnapTarget.FLAG_DISMISS_END, 0.35f)); 22681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 2271fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 22881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void addFixedDivisionTargets(boolean isHorizontalDivision) { 22981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int start = isHorizontalDivision ? mInsets.top : mInsets.left; 23081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int end = isHorizontalDivision 23181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight - mInsets.bottom 23281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth - mInsets.right; 23381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.add(new SnapTarget((int) (start + mFixedRatio * (end - start)) - mDividerSize / 2, 2341fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi SnapTarget.FLAG_NONE)); 23581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addMiddleTarget(isHorizontalDivision); 23681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.add(new SnapTarget((int) (start + (1 - mFixedRatio) * (end - start)) 23781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi - mDividerSize / 2, SnapTarget.FLAG_NONE)); 23881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 23981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 24081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void addRatio16_9Targets(boolean isHorizontalDivision) { 24181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int start = isHorizontalDivision ? mInsets.top : mInsets.left; 24281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int end = isHorizontalDivision 24381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayHeight - mInsets.bottom 24481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayWidth - mInsets.right; 24581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int startOther = isHorizontalDivision ? mInsets.left : mInsets.top; 24681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int endOther = isHorizontalDivision 24781fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi ? mDisplayWidth - mInsets.right 24881fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi : mDisplayHeight - mInsets.bottom; 24981fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi float size = 9.0f / 16.0f * (endOther - startOther); 25081fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi int sizeInt = (int) Math.floor(size); 25181fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.add(new SnapTarget(start + sizeInt, SnapTarget.FLAG_NONE)); 25281fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi addMiddleTarget(isHorizontalDivision); 25381fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi mTargets.add(new SnapTarget(end - sizeInt - mDividerSize, SnapTarget.FLAG_NONE)); 25481fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi } 25581fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi 25681fe2d1f0adc9e752d7f1a410d66af6a326fd6e2Jorim Jaggi private void addMiddleTarget(boolean isHorizontalDivision) { 2573e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson mTargets.add(new SnapTarget(DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision, 2583e8747414520ee348cf4b9c4a6afd9ff80b5a8f8Winson mInsets, mDisplayWidth, mDisplayHeight, mDividerSize), SnapTarget.FLAG_NONE)); 2591fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 2601fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 261d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi public SnapTarget getMiddleTarget() { 262d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi return mMiddleTarget; 263d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi } 264d434dcbfc9407baad28b6b40fea75b1b6050ad7eJorim Jaggi 26550cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi public SnapTarget getNextTarget(SnapTarget snapTarget) { 26650cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi int index = mTargets.indexOf(snapTarget); 26750cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi if (index != -1 && index < mTargets.size() - 1) { 26850cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return mTargets.get(index + 1); 26950cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 27050cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return snapTarget; 27150cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 27250cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi 27350cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi public SnapTarget getPreviousTarget(SnapTarget snapTarget) { 27450cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi int index = mTargets.indexOf(snapTarget); 27550cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi if (index != -1 && index > 0) { 27650cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return mTargets.get(index - 1); 27750cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 27850cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi return snapTarget; 27950cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi } 28050cd6361d7cb50bdc0ee199f42307885abc65f0bJorim Jaggi 2811fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** 2821fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi * Represents a snap target for the divider. 2831fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi */ 2841fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static class SnapTarget { 2851fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_NONE = 0; 2861fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 2871fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** If the divider reaches this value, the left/top task should be dismissed. */ 2881fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_DISMISS_START = 1; 2891fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 2901fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi /** If the divider reaches this value, the right/bottom task should be dismissed */ 2911fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public static final int FLAG_DISMISS_END = 2; 2921fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 2931fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public final int position; 2941fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public final int flag; 2951fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi 296df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi /** 297df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * Multiplier used to calculate distance to snap position. The lower this value, the harder 298df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi * it's to snap on this target 299df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi */ 300df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi private final float distanceMultiplier; 301df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 3021fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi public SnapTarget(int position, int flag) { 303df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi this(position, flag, 1f); 304df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi } 305df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi 306df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi public SnapTarget(int position, int flag, float distanceMultiplier) { 3071fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi this.position = position; 3081fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi this.flag = flag; 309df012d5102735412d9f38513c103aa53df4bcab9Jorim Jaggi this.distanceMultiplier = distanceMultiplier; 3101fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 3111fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi } 3121fcbab6ae5c99acab70eacc015d194e2c6ddd4e2Jorim Jaggi} 313