Merge changes from topic "sticky_placeholders_custom_finishing_behavior" into sc-v2-dev

* changes:
  Add custom finishing behaviors for split pair
  Add support for sticky placeholders
This commit is contained in:
Andrii Kulian
2021-11-11 03:44:38 +00:00
committed by Android (Google) Code Review
4 changed files with 103 additions and 2 deletions

View File

@@ -73,17 +73,55 @@ class SplitContainer {
static boolean shouldFinishPrimaryWithSecondary(@NonNull SplitRule splitRule) {
final boolean isPlaceholderContainer = splitRule instanceof SplitPlaceholderRule;
final boolean shouldFinishPrimaryWithSecondary = (splitRule instanceof SplitPairRule)
&& ((SplitPairRule) splitRule).shouldFinishPrimaryWithSecondary();
&& ((SplitPairRule) splitRule).getFinishPrimaryWithSecondary()
!= SplitRule.FINISH_NEVER;
return shouldFinishPrimaryWithSecondary || isPlaceholderContainer;
}
static boolean shouldFinishSecondaryWithPrimary(@NonNull SplitRule splitRule) {
final boolean isPlaceholderContainer = splitRule instanceof SplitPlaceholderRule;
final boolean shouldFinishSecondaryWithPrimary = (splitRule instanceof SplitPairRule)
&& ((SplitPairRule) splitRule).shouldFinishSecondaryWithPrimary();
&& ((SplitPairRule) splitRule).getFinishSecondaryWithPrimary()
!= SplitRule.FINISH_NEVER;
return shouldFinishSecondaryWithPrimary || isPlaceholderContainer;
}
static boolean shouldFinishAssociatedContainerWhenStacked(int finishBehavior) {
return finishBehavior == SplitRule.FINISH_ALWAYS;
}
static boolean shouldFinishAssociatedContainerWhenAdjacent(int finishBehavior) {
return finishBehavior == SplitRule.FINISH_ALWAYS
|| finishBehavior == SplitRule.FINISH_ADJACENT;
}
static int getFinishPrimaryWithSecondaryBehavior(@NonNull SplitRule splitRule) {
if (splitRule instanceof SplitPlaceholderRule) {
return ((SplitPlaceholderRule) splitRule).getFinishPrimaryWithSecondary();
}
if (splitRule instanceof SplitPairRule) {
return ((SplitPairRule) splitRule).getFinishPrimaryWithSecondary();
}
return SplitRule.FINISH_NEVER;
}
static int getFinishSecondaryWithPrimaryBehavior(@NonNull SplitRule splitRule) {
if (splitRule instanceof SplitPlaceholderRule) {
return SplitRule.FINISH_ALWAYS;
}
if (splitRule instanceof SplitPairRule) {
return ((SplitPairRule) splitRule).getFinishSecondaryWithPrimary();
}
return SplitRule.FINISH_NEVER;
}
static boolean isStickyPlaceholderRule(@NonNull SplitRule splitRule) {
if (!(splitRule instanceof SplitPlaceholderRule)) {
return false;
}
return ((SplitPlaceholderRule) splitRule).isSticky();
}
@Override
public String toString() {
return "SplitContainer{"

View File

@@ -16,6 +16,12 @@
package androidx.window.extensions.embedding;
import static androidx.window.extensions.embedding.SplitContainer.getFinishPrimaryWithSecondaryBehavior;
import static androidx.window.extensions.embedding.SplitContainer.getFinishSecondaryWithPrimaryBehavior;
import static androidx.window.extensions.embedding.SplitContainer.isStickyPlaceholderRule;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenAdjacent;
import static androidx.window.extensions.embedding.SplitContainer.shouldFinishAssociatedContainerWhenStacked;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
@@ -460,6 +466,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return false;
}
if (isStickyPlaceholderRule(splitContainer.getSplitRule())) {
// The placeholder should remain after it was first shown.
return false;
}
if (mPresenter.shouldShowSideBySide(splitContainer)) {
return false;
}
@@ -643,6 +654,52 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return false;
}
/**
* Checks whether the associated container should be destroyed together with a finishing
* container. There is a case when primary containers for placeholders should be retained
* despite the rule configuration to finish primary with secondary - if they are marked as
* 'sticky' and the placeholder was finished when fully overlapping the primary container.
* @return {@code true} if the associated container should be retained (and not be finished).
*/
boolean shouldRetainAssociatedContainer(@NonNull TaskFragmentContainer finishingContainer,
@NonNull TaskFragmentContainer associatedContainer) {
SplitContainer splitContainer = getActiveSplitForContainers(associatedContainer,
finishingContainer);
if (splitContainer == null) {
// Containers are not in the same split, no need to retain.
return false;
}
// Find the finish behavior for the associated container
int finishBehavior;
SplitRule splitRule = splitContainer.getSplitRule();
if (finishingContainer == splitContainer.getPrimaryContainer()) {
finishBehavior = getFinishSecondaryWithPrimaryBehavior(splitRule);
} else {
finishBehavior = getFinishPrimaryWithSecondaryBehavior(splitRule);
}
// Decide whether the associated container should be retained based on the current
// presentation mode.
if (mPresenter.shouldShowSideBySide(splitContainer)) {
return !shouldFinishAssociatedContainerWhenAdjacent(finishBehavior);
} else {
return !shouldFinishAssociatedContainerWhenStacked(finishBehavior);
}
}
/**
* @see #shouldRetainAssociatedContainer(TaskFragmentContainer, TaskFragmentContainer)
*/
boolean shouldRetainAssociatedActivity(@NonNull TaskFragmentContainer finishingContainer,
@NonNull Activity associatedActivity) {
TaskFragmentContainer associatedContainer = getContainerWithActivity(
associatedActivity.getActivityToken());
if (associatedContainer == null) {
return false;
}
return shouldRetainAssociatedContainer(finishingContainer, associatedContainer);
}
private final class LifecycleCallbacks implements ActivityLifecycleCallbacks {
@Override

View File

@@ -228,6 +228,9 @@ class TaskFragmentContainer {
// Finish dependent containers
for (TaskFragmentContainer container : mContainersToFinishOnExit) {
if (controller.shouldRetainAssociatedContainer(this, container)) {
continue;
}
container.finish(true /* shouldFinishDependent */, presenter,
wct, controller);
}
@@ -235,6 +238,9 @@ class TaskFragmentContainer {
// Finish associated activities
for (Activity activity : mActivitiesToFinishOnExit) {
if (controller.shouldRetainAssociatedActivity(this, activity)) {
continue;
}
activity.finish();
}
mActivitiesToFinishOnExit.clear();