Skip to content

Commit c7d84cf

Browse files
committed
Introduces ScreenOverlay and ModalScreenOverlayDialogFactory
`ScreenOverlay` marks an `Overlay` with a `Screen` defining its content. `ModalScreenOverlayDialogFactory` can show a `ScreenOverlay` as an `android.app.Dialog`, taking care of updating the content view and managing the Back button. It's the much simpler replacement for `ModalViewContainer`. Also introduces two new `ViewEnvironment` values: - `ModalArea`, which allows dialogs to restrict themselves to a subset of the screen. `ModalScreenOverlayDialogFactory` applies this automatically - `CoveredByModal`, used by `BodyAndModalsContainer` and `LayeredDialogs` to disable touch and keyboard events reliably In sample code, `PanelOverlay` replaces `PanelContainerScreen`, and the Tic Tac Toe sample is updated to use the new hotness. I think the diff of the sample code really highlights how much the new marker interfaces improve our composition story. That said, the `ScrimScreen` bit in the sample is a little rough. In the old code we magically swizzled the scrim into place automatically. This PR seems big enough already, so I'll follow up with a clean up that does something similar and deletes all the deprecated sample code. Fixes #259, #138, #99, #204, #314, #589
1 parent 45ece5a commit c7d84cf

File tree

36 files changed

+908
-452
lines changed

36 files changed

+908
-452
lines changed
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package com.squareup.sample.container
22

33
import com.squareup.sample.container.overviewdetail.OverviewDetailContainer
4-
import com.squareup.sample.container.panel.PanelContainer
5-
import com.squareup.sample.container.panel.ScrimContainer
6-
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
4+
import com.squareup.sample.container.panel.PanelOverlayDialogFactory
75
import com.squareup.workflow1.ui.ViewRegistry
6+
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
87

98
@OptIn(WorkflowUiExperimentalApi::class)
109
val SampleContainers = ViewRegistry(
11-
BackButtonViewFactory, OverviewDetailContainer, PanelContainer, ScrimContainer
10+
BackButtonViewFactory, OverviewDetailContainer, PanelOverlayDialogFactory, ScrimContainer
1211
)
Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
package com.squareup.sample.container.panel
1+
package com.squareup.sample.container
22

33
import android.animation.ValueAnimator
44
import android.content.Context
55
import android.util.AttributeSet
66
import android.view.View
77
import android.view.ViewGroup
88
import androidx.core.content.ContextCompat
9-
import com.squareup.sample.container.R
9+
import com.squareup.sample.container.panel.ScrimScreen
1010
import com.squareup.workflow1.ui.ManualScreenViewFactory
1111
import com.squareup.workflow1.ui.ScreenViewFactory
1212
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
@@ -17,9 +17,9 @@ import com.squareup.workflow1.ui.bindShowRendering
1717
* A view that renders only its first child, behind a smoke scrim if
1818
* [isDimmed] is true (tablets only). Other children are ignored.
1919
*
20-
* Able to [render][com.squareup.workflow1.ui.showRendering] [ScrimContainerScreen].
20+
* Able to [render][com.squareup.workflow1.ui.showRendering] [ScrimScreen].
2121
*/
22-
class ScrimContainer @JvmOverloads constructor(
22+
internal class ScrimContainer @JvmOverloads constructor(
2323
context: Context,
2424
attributeSet: AttributeSet? = null,
2525
defStyle: Int = 0,
@@ -91,21 +91,21 @@ class ScrimContainer @JvmOverloads constructor(
9191
}
9292

9393
@OptIn(WorkflowUiExperimentalApi::class)
94-
companion object : ScreenViewFactory<ScrimContainerScreen<*>> by ManualScreenViewFactory(
95-
type = ScrimContainerScreen::class,
94+
companion object : ScreenViewFactory<ScrimScreen<*>> by ManualScreenViewFactory(
95+
type = ScrimScreen::class,
9696
viewConstructor = { initialRendering, initialViewEnvironment, contextForNewView, _ ->
9797
val stub = WorkflowViewStub(contextForNewView)
9898

9999
ScrimContainer(contextForNewView)
100-
.apply {
101-
layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
102-
addView(stub)
100+
.also { view ->
101+
view.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
102+
view.addView(stub)
103103

104-
bindShowRendering(
105-
initialRendering, initialViewEnvironment
104+
view.bindShowRendering(
105+
initialRendering, initialViewEnvironment
106106
) { rendering, environment ->
107-
stub.show(rendering.wrapped, environment)
108-
isDimmed = rendering.dimmed
107+
stub.show(rendering.content, environment)
108+
view.isDimmed = rendering.dimmed
109109
}
110110
}
111111
}

samples/containers/android/src/main/java/com/squareup/sample/container/panel/Contexts.kt

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,9 @@ package com.squareup.sample.container.panel
22

33
import android.content.Context
44
import android.content.Context.WINDOW_SERVICE
5-
import android.view.Display
65
import android.view.WindowManager
76
import com.squareup.sample.container.R
87

9-
val Context.isPortrait: Boolean get() = resources.getBoolean(R.bool.is_portrait)
10-
118
val Context.isTablet: Boolean get() = resources.getBoolean(R.bool.is_tablet)
129

1310
val Context.windowManager: WindowManager get() = getSystemService(WINDOW_SERVICE) as WindowManager
14-
15-
@Suppress("DEPRECATION")
16-
val Context.defaultDisplay: Display get() = windowManager.defaultDisplay

samples/containers/android/src/main/java/com/squareup/sample/container/panel/PanelContainer.kt

Lines changed: 0 additions & 72 deletions
This file was deleted.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.squareup.sample.container.panel
2+
3+
import android.app.Dialog
4+
import android.graphics.drawable.ColorDrawable
5+
import android.util.TypedValue
6+
import android.view.View
7+
import com.squareup.sample.container.R
8+
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
9+
import com.squareup.workflow1.ui.container.Bounds
10+
import com.squareup.workflow1.ui.container.ModalScreenOverlayDialogFactory
11+
import com.squareup.workflow1.ui.container.setBounds
12+
13+
/**
14+
* Android support for [PanelOverlay].
15+
*/
16+
@OptIn(WorkflowUiExperimentalApi::class)
17+
internal object PanelOverlayDialogFactory : ModalScreenOverlayDialogFactory<PanelOverlay<*>>(
18+
type = PanelOverlay::class
19+
) {
20+
override fun buildDialogWithContentView(contentView: View): Dialog {
21+
val context = contentView.context
22+
return Dialog(context, R.style.PanelDialog).also { dialog ->
23+
dialog.setContentView(contentView)
24+
25+
val typedValue = TypedValue()
26+
context.theme.resolveAttribute(android.R.attr.windowBackground, typedValue, true)
27+
if (typedValue.type in TypedValue.TYPE_FIRST_COLOR_INT..TypedValue.TYPE_LAST_COLOR_INT) {
28+
dialog.window!!.setBackgroundDrawable(ColorDrawable(typedValue.data))
29+
}
30+
}
31+
}
32+
33+
override fun updateBounds(
34+
dialog: Dialog,
35+
bounds: Bounds
36+
) {
37+
val refinedBounds: Bounds = if (!dialog.context.isTablet) {
38+
// On a phone, fill the bounds entirely.
39+
bounds
40+
} else {
41+
if (bounds.height > bounds.width) {
42+
val margin = bounds.height - bounds.width
43+
val topDelta = margin / 2
44+
val bottomDelta = margin - topDelta
45+
bounds.copy(top = bounds.top + topDelta, bottom = bounds.bottom - bottomDelta)
46+
} else {
47+
val margin = bounds.width - bounds.height
48+
val leftDelta = margin / 2
49+
val rightDelta = margin - leftDelta
50+
bounds.copy(left = bounds.left + leftDelta, right = bounds.right - rightDelta)
51+
}
52+
}
53+
dialog.setBounds(refinedBounds)
54+
}
55+
}

samples/containers/android/src/main/res/values-land/bools.xml

Lines changed: 0 additions & 4 deletions
This file was deleted.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<resources>
3-
<bool name="is_portrait">true</bool>
43
<bool name="is_tablet">false</bool>
54
</resources>

samples/containers/common/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ plugins {
55

66
dependencies {
77
implementation(project(":workflow-ui:container-common"))
8+
implementation(project(":workflow-ui:core-android"))
89
implementation(project(":workflow-core"))
910

1011
implementation(Dependencies.Kotlin.Stdlib.jdk6)

samples/containers/common/src/main/java/com/squareup/sample/container/panel/PanelContainerScreen.kt

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.squareup.sample.container.panel
2+
3+
import com.squareup.workflow1.ui.Screen
4+
import com.squareup.workflow1.ui.WorkflowUiExperimentalApi
5+
import com.squareup.workflow1.ui.container.ScreenOverlay
6+
7+
@OptIn(WorkflowUiExperimentalApi::class)
8+
class PanelOverlay<T : Screen>(
9+
override val content: T
10+
) : ScreenOverlay<T>

0 commit comments

Comments
 (0)