Merge "Updating the swipe-to-dismiss animation" into ub-launcher3-master
This commit is contained in:
commit
9da6c526cb
|
@ -18,14 +18,11 @@ package com.android.launcher3.uioverrides;
|
|||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
@ -43,6 +40,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
|||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.quickstep.PendingAnimation;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
||||
|
@ -65,6 +63,7 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
|||
private final RecentsView mRecentsView;
|
||||
private final int[] mTempCords = new int[2];
|
||||
|
||||
private PendingAnimation mPendingAnimation;
|
||||
private AnimatorPlaybackController mCurrentAnimation;
|
||||
private boolean mCurrentAnimationIsGoingUp;
|
||||
|
||||
|
@ -178,6 +177,11 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
|||
if (mCurrentAnimation != null) {
|
||||
mCurrentAnimation.setPlayFraction(0);
|
||||
}
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(false);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
|
||||
mCurrentAnimationIsGoingUp = goingUp;
|
||||
float range = mLauncher.getAllAppsController().getShiftRange();
|
||||
long maxDuration = (long) (2 * range);
|
||||
|
@ -194,19 +198,11 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
|||
}
|
||||
} else {
|
||||
if (goingUp) {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
ObjectAnimator translate = ObjectAnimator.ofFloat(
|
||||
mTaskBeingDragged, View.TRANSLATION_Y, -mTaskBeingDragged.getBottom());
|
||||
translate.setInterpolator(LINEAR);
|
||||
translate.setDuration(maxDuration);
|
||||
anim.play(translate);
|
||||
|
||||
ObjectAnimator alpha = ObjectAnimator.ofFloat(mTaskBeingDragged, View.ALPHA, 0);
|
||||
alpha.setInterpolator(DEACCEL_1_5);
|
||||
alpha.setDuration(maxDuration);
|
||||
anim.play(alpha);
|
||||
mCurrentAnimation = AnimatorPlaybackController.wrap(anim, maxDuration);
|
||||
mEndDisplacement = -mTaskBeingDragged.getBottom();
|
||||
mPendingAnimation = mRecentsView
|
||||
.createTaskDismissAnimation(mTaskBeingDragged, maxDuration);
|
||||
mCurrentAnimation = AnimatorPlaybackController
|
||||
.wrap(mPendingAnimation.anim, maxDuration);
|
||||
mEndDisplacement = -mTaskBeingDragged.getHeight();
|
||||
} else {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
// TODO: Setup a zoom animation
|
||||
|
@ -292,15 +288,17 @@ public class OverviewSwipeController extends AnimatorListenerAdapter
|
|||
}
|
||||
|
||||
private void onCurrentAnimationEnd(boolean wasSuccess, int logAction) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.finish(wasSuccess);
|
||||
mPendingAnimation = null;
|
||||
}
|
||||
if (mTaskBeingDragged == null) {
|
||||
LauncherState state = wasSuccess ?
|
||||
(mCurrentAnimationIsGoingUp ? ALL_APPS : NORMAL) : OVERVIEW;
|
||||
mLauncher.getStateManager().goToState(state, false);
|
||||
|
||||
} else if (wasSuccess) {
|
||||
if (mCurrentAnimationIsGoingUp) {
|
||||
mRecentsView.onTaskDismissed(mTaskBeingDragged);
|
||||
} else {
|
||||
if (!mCurrentAnimationIsGoingUp) {
|
||||
mTaskBeingDragged.launchTask(false);
|
||||
mLauncher.getUserEventDispatcher().logTaskLaunch(logAction,
|
||||
Direction.DOWN, mTaskBeingDragged.getTask().getTopComponent());
|
||||
|
|
|
@ -57,10 +57,7 @@ public class RecentsViewStateController implements StateHandler {
|
|||
setVisibility(state.overviewUi);
|
||||
setTransitionProgress(state.overviewUi ? 1 : 0);
|
||||
if (state.overviewUi) {
|
||||
for (int i = 0; i < mRecentsView.getPageCount(); i++) {
|
||||
((TaskView) mRecentsView.getPageAt(i)).resetVisualProperties();
|
||||
}
|
||||
mRecentsView.updateCurveProperties();
|
||||
mRecentsView.resetTaskVisuals();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.quickstep;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Utility class to keep track of a running animation.
|
||||
*
|
||||
* This class allows attaching end callbacks to an animation is intended to be used with
|
||||
* {@link com.android.launcher3.anim.AnimatorPlaybackController}, since in that case
|
||||
* AnimationListeners are not properly dispatched.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class PendingAnimation {
|
||||
|
||||
private final ArrayList<Consumer<Boolean>> mEndListeners = new ArrayList<>();
|
||||
|
||||
public final AnimatorSet anim;
|
||||
|
||||
public PendingAnimation(AnimatorSet anim) {
|
||||
this.anim = anim;
|
||||
}
|
||||
|
||||
public void finish(boolean isSuccess) {
|
||||
for (Consumer<Boolean> listeners : mEndListeners) {
|
||||
listeners.accept(isSuccess);
|
||||
}
|
||||
mEndListeners.clear();
|
||||
}
|
||||
|
||||
public void addEndListener(Consumer<Boolean> listener) {
|
||||
mEndListeners.add(listener);
|
||||
}
|
||||
}
|
|
@ -16,23 +16,32 @@
|
|||
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.animation.LayoutTransition.TransitionListener;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.quickstep.PendingAnimation;
|
||||
import com.android.quickstep.QuickScrubController;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
|
||||
|
@ -49,6 +58,7 @@ import java.util.ArrayList;
|
|||
/**
|
||||
* A list of recent tasks.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public abstract class RecentsView<T extends BaseActivity>
|
||||
extends PagedView implements OnSharedPreferenceChangeListener {
|
||||
|
||||
|
@ -90,14 +100,14 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
|
||||
private boolean mOverviewStateEnabled;
|
||||
private boolean mTaskStackListenerRegistered;
|
||||
private LayoutTransition mLayoutTransition;
|
||||
private Runnable mNextPageSwitchRunnable;
|
||||
|
||||
private PendingAnimation mPendingAnimation;
|
||||
|
||||
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
|
||||
enableFreeScroll(true);
|
||||
setupLayoutTransition();
|
||||
setClipToOutline(true);
|
||||
|
||||
mFastFlingVelocity = getResources()
|
||||
|
@ -136,33 +146,6 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
return null;
|
||||
}
|
||||
|
||||
private void setupLayoutTransition() {
|
||||
// We want to show layout transitions when pages are deleted, to close the gap.
|
||||
// TODO: We should this manually so we can control the animation (fill in the gap as the
|
||||
// dismissing task is being tracked, and also so we can update the visible task data during
|
||||
// the transition. For now, the workaround is to expand the visible tasks to load.
|
||||
mLayoutTransition = new LayoutTransition();
|
||||
mLayoutTransition.enableTransitionType(LayoutTransition.DISAPPEARING);
|
||||
mLayoutTransition.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
|
||||
|
||||
mLayoutTransition.disableTransitionType(LayoutTransition.APPEARING);
|
||||
mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
|
||||
mLayoutTransition.addTransitionListener(new TransitionListener() {
|
||||
@Override
|
||||
public void startTransition(LayoutTransition layoutTransition, ViewGroup viewGroup,
|
||||
View view, int i) {
|
||||
loadVisibleTaskData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTransition(LayoutTransition layoutTransition, ViewGroup viewGroup,
|
||||
View view, int i) {
|
||||
loadVisibleTaskData();
|
||||
}
|
||||
});
|
||||
setLayoutTransition(mLayoutTransition);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onWindowVisibilityChanged(int visibility) {
|
||||
super.onWindowVisibilityChanged(visibility);
|
||||
|
@ -231,6 +214,10 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
}
|
||||
|
||||
private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) {
|
||||
if (mPendingAnimation != null) {
|
||||
mPendingAnimation.addEndListener((b) -> applyLoadPlan(loadPlan));
|
||||
return;
|
||||
}
|
||||
TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null;
|
||||
if (stack == null) {
|
||||
removeAllViews();
|
||||
|
@ -243,7 +230,6 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
// necessary)
|
||||
final LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
final ArrayList<Task> tasks = new ArrayList<>(stack.getTasks());
|
||||
setLayoutTransition(null);
|
||||
|
||||
final int requiredChildCount = tasks.size();
|
||||
for (int i = getChildCount(); i < requiredChildCount; i++) {
|
||||
|
@ -254,7 +240,6 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1);
|
||||
removeView(taskView);
|
||||
}
|
||||
setLayoutTransition(mLayoutTransition);
|
||||
|
||||
// Unload existing visible task data
|
||||
unloadVisibleTaskData();
|
||||
|
@ -265,12 +250,8 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
final Task task = tasks.get(i);
|
||||
final TaskView taskView = (TaskView) getChildAt(pageIndex);
|
||||
taskView.bind(task);
|
||||
taskView.resetVisualProperties();
|
||||
}
|
||||
updateCurveProperties();
|
||||
|
||||
// Update the set of visible task's data
|
||||
loadVisibleTaskData();
|
||||
resetTaskVisuals();
|
||||
applyIconScale(false /* animate */);
|
||||
|
||||
if (oldChildCount != getChildCount()) {
|
||||
|
@ -278,6 +259,16 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
}
|
||||
}
|
||||
|
||||
public void resetTaskVisuals() {
|
||||
for (int i = getChildCount() - 1; i >= 0; i--) {
|
||||
((TaskView) getChildAt(i)).resetVisualProperties();
|
||||
}
|
||||
|
||||
updateCurveProperties();
|
||||
// Update the set of visible task's data
|
||||
loadVisibleTaskData();
|
||||
}
|
||||
|
||||
private void updateTaskStackListenerState() {
|
||||
boolean registerStackListener = mOverviewStateEnabled && isAttachedToWindow()
|
||||
&& getWindowVisibility() == VISIBLE;
|
||||
|
@ -375,7 +366,7 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
final int pageCount = getPageCount();
|
||||
for (int i = 0; i < pageCount; i++) {
|
||||
View page = getPageAt(i);
|
||||
int pageCenter = page.getLeft() + halfPageWidth;
|
||||
float pageCenter = page.getLeft() + page.getTranslationX() + halfPageWidth;
|
||||
float distanceFromScreenCenter = screenCenter - pageCenter;
|
||||
float distanceToReachEdge = halfScreenWidth + halfPageWidth + pageSpacing;
|
||||
mScrollState.linearInterpolation = Math.min(1,
|
||||
|
@ -432,13 +423,6 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
mHasVisibleTaskData.clear();
|
||||
}
|
||||
|
||||
public void onTaskDismissed(TaskView taskView) {
|
||||
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
|
||||
removeView(taskView);
|
||||
if (getChildCount() == 0) {
|
||||
onAllTasksRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onAllTasksRemoved();
|
||||
|
||||
|
@ -470,11 +454,9 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
if (getChildCount() == 0) {
|
||||
needsReload = true;
|
||||
// Add an empty view for now
|
||||
setLayoutTransition(null);
|
||||
final TaskView taskView = (TaskView) LayoutInflater.from(getContext())
|
||||
.inflate(R.layout.task, this, false);
|
||||
addView(taskView, 0);
|
||||
setLayoutTransition(mLayoutTransition);
|
||||
}
|
||||
mRunningTaskId = runningTaskId;
|
||||
setCurrentPage(0);
|
||||
|
@ -529,4 +511,78 @@ public abstract class RecentsView<T extends BaseActivity>
|
|||
*/
|
||||
public float linearInterpolation;
|
||||
}
|
||||
|
||||
public PendingAnimation createTaskDismissAnimation(TaskView taskView, long duration) {
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) {
|
||||
throw new IllegalStateException("Another pending animation is still running");
|
||||
}
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
PendingAnimation pendingAnimation = new PendingAnimation(anim);
|
||||
|
||||
int count = getChildCount();
|
||||
if (count == 0) {
|
||||
return pendingAnimation;
|
||||
}
|
||||
|
||||
int[] oldScroll = new int[count];
|
||||
getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
|
||||
|
||||
int[] newScroll = new int[count];
|
||||
getPageScrolls(newScroll, false, (v) -> v.getVisibility() != GONE && v != taskView);
|
||||
|
||||
int maxScrollDiff = 0;
|
||||
int lastPage = mIsRtl ? 0 : count - 1;
|
||||
if (getChildAt(lastPage) == taskView) {
|
||||
if (count > 1) {
|
||||
int secondLastPage = mIsRtl ? 1 : count - 2;
|
||||
maxScrollDiff = oldScroll[lastPage] - newScroll[secondLastPage];
|
||||
}
|
||||
}
|
||||
|
||||
boolean needsCurveUpdates = false;
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child == taskView) {
|
||||
addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim);
|
||||
addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()),
|
||||
duration, LINEAR, anim);
|
||||
} else {
|
||||
int scrollDiff = newScroll[i] - oldScroll[i] + maxScrollDiff;
|
||||
if (scrollDiff != 0) {
|
||||
addAnim(ObjectAnimator.ofFloat(child, TRANSLATION_X, scrollDiff),
|
||||
duration, ACCEL, anim);
|
||||
needsCurveUpdates = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needsCurveUpdates) {
|
||||
ValueAnimator va = ValueAnimator.ofFloat(0, 1);
|
||||
va.addUpdateListener((a) -> updateCurveProperties());
|
||||
anim.play(va);
|
||||
}
|
||||
|
||||
// Add a tiny bit of translation Z, so that it draws on top of other views
|
||||
taskView.setTranslationZ(0.1f);
|
||||
|
||||
mPendingAnimation = pendingAnimation;
|
||||
mPendingAnimation.addEndListener((isSuccess) -> {
|
||||
if (isSuccess) {
|
||||
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
|
||||
removeView(taskView);
|
||||
if (getChildCount() == 0) {
|
||||
onAllTasksRemoved();
|
||||
}
|
||||
}
|
||||
resetTaskVisuals();
|
||||
mPendingAnimation = null;
|
||||
});
|
||||
return pendingAnimation;
|
||||
}
|
||||
|
||||
private static void addAnim(ObjectAnimator anim, long duration,
|
||||
TimeInterpolator interpolator, AnimatorSet set) {
|
||||
anim.setDuration(duration).setInterpolator(interpolator);
|
||||
set.play(anim);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback
|
|||
setScaleY(1f);
|
||||
setTranslationX(0f);
|
||||
setTranslationY(0f);
|
||||
setTranslationZ(0);
|
||||
setAlpha(1f);
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,9 @@ import java.util.ArrayList;
|
|||
public abstract class PagedView<T extends View & PageIndicator> extends ViewGroup {
|
||||
private static final String TAG = "PagedView";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
protected static final int INVALID_PAGE = -1;
|
||||
protected static final ComputePageScrollsLogic SIMPLE_SCROLL_LOGIC = (v) -> v.getVisibility() != GONE;
|
||||
|
||||
public static final int PAGE_SNAP_ANIMATION_DURATION = 750;
|
||||
public static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
|
||||
|
@ -540,43 +542,13 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
|||
if (DEBUG) Log.d(TAG, "PagedView.onLayout()");
|
||||
final int childCount = getChildCount();
|
||||
|
||||
final int startIndex = mIsRtl ? childCount - 1 : 0;
|
||||
final int endIndex = mIsRtl ? -1 : childCount;
|
||||
final int delta = mIsRtl ? -1 : 1;
|
||||
|
||||
int verticalPadding = getPaddingTop() + getPaddingBottom();
|
||||
|
||||
int scrollOffsetLeft = mInsets.left + getPaddingLeft();
|
||||
int childLeft = scrollOffsetLeft;
|
||||
|
||||
boolean pageScrollChanged = false;
|
||||
if (mPageScrolls == null || childCount != mChildCountOnLastLayout) {
|
||||
mPageScrolls = new int[childCount];
|
||||
pageScrollChanged = true;
|
||||
}
|
||||
|
||||
for (int i = startIndex; i != endIndex; i += delta) {
|
||||
final View child = getPageAt(i);
|
||||
if (child.getVisibility() != View.GONE) {
|
||||
int childTop = getPaddingTop() + mInsets.top;
|
||||
childTop += (getMeasuredHeight() - mInsets.top - mInsets.bottom - verticalPadding
|
||||
- child.getMeasuredHeight()) / 2;
|
||||
|
||||
final int childWidth = child.getMeasuredWidth();
|
||||
final int childHeight = child.getMeasuredHeight();
|
||||
|
||||
if (DEBUG) Log.d(TAG, "\tlayout-child" + i + ": " + childLeft + ", " + childTop);
|
||||
child.layout(childLeft, childTop,
|
||||
childLeft + child.getMeasuredWidth(), childTop + childHeight);
|
||||
|
||||
final int pageScroll = childLeft - scrollOffsetLeft;
|
||||
if (mPageScrolls[i] != pageScroll) {
|
||||
pageScrollChanged = true;
|
||||
mPageScrolls[i] = pageScroll;
|
||||
}
|
||||
|
||||
childLeft += childWidth + mPageSpacing + getChildGap();
|
||||
}
|
||||
if (getPageScrolls(mPageScrolls, true, SIMPLE_SCROLL_LOGIC)) {
|
||||
pageScrollChanged = true;
|
||||
}
|
||||
|
||||
final LayoutTransition transition = getLayoutTransition();
|
||||
|
@ -614,6 +586,51 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
|||
mChildCountOnLastLayout = childCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes {@code outPageScrolls} with scroll positions for view at that index. The length
|
||||
* of {@code outPageScrolls} should be same as the the childCount
|
||||
*
|
||||
*/
|
||||
protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren,
|
||||
ComputePageScrollsLogic scrollLogic) {
|
||||
final int childCount = getChildCount();
|
||||
|
||||
final int startIndex = mIsRtl ? childCount - 1 : 0;
|
||||
final int endIndex = mIsRtl ? -1 : childCount;
|
||||
final int delta = mIsRtl ? -1 : 1;
|
||||
|
||||
int verticalPadding = getPaddingTop() + getPaddingBottom();
|
||||
|
||||
int scrollOffsetLeft = mInsets.left + getPaddingLeft();
|
||||
int childLeft = scrollOffsetLeft;
|
||||
boolean pageScrollChanged = false;
|
||||
|
||||
for (int i = startIndex; i != endIndex; i += delta) {
|
||||
final View child = getPageAt(i);
|
||||
if (scrollLogic.shouldIncludeView(child)) {
|
||||
int childTop = getPaddingTop() + mInsets.top;
|
||||
childTop += (getMeasuredHeight() - mInsets.top - mInsets.bottom - verticalPadding
|
||||
- child.getMeasuredHeight()) / 2;
|
||||
final int childWidth = child.getMeasuredWidth();
|
||||
|
||||
if (layoutChildren) {
|
||||
final int childHeight = child.getMeasuredHeight();
|
||||
child.layout(childLeft, childTop,
|
||||
childLeft + child.getMeasuredWidth(), childTop + childHeight);
|
||||
}
|
||||
|
||||
final int pageScroll = childLeft - scrollOffsetLeft;
|
||||
if (outPageScrolls[i] != pageScroll) {
|
||||
pageScrollChanged = true;
|
||||
outPageScrolls[i] = pageScroll;
|
||||
}
|
||||
|
||||
childLeft += childWidth + mPageSpacing + getChildGap();
|
||||
}
|
||||
}
|
||||
return pageScrollChanged;
|
||||
}
|
||||
|
||||
protected int getChildGap() {
|
||||
return 0;
|
||||
}
|
||||
|
@ -1525,4 +1542,9 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
|||
public boolean onHoverEvent(android.view.MotionEvent event) {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected interface ComputePageScrollsLogic {
|
||||
|
||||
boolean shouldIncludeView(View view);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue