Skip to content

Scope Host

petterp edited this page Aug 30, 2026 · 2 revisions

Local windows (Scope Host)

A local window is attached to one specific container: any ViewGroup, an Activity's content, or a Fragment's root view. It is not registered (FloatingX.controls() never shows it), its lifetime belongs to the caller, and you call control.cancel() when you no longer need it.

Requires the io.github.petterpx:floatingx-scope module, see Getting Started.

The three entry points

Entry point Attached to Notes
Activity.fxScope(tag) {} android.R.id.content Must be called after setContentView(); on API 29+ it cancels automatically when the page is destroyed
ViewGroup.fxScope(tag) {} that ViewGroup itself The window is confined to that container
Fragment.fxScope(tag) {} the Fragment's root view Fine to call in onCreate — it attaches once the view exists and cancels on destroy (#244)

Usage

// Activity: attached to android.R.id.content (must be called after setContentView)
val actFx = fxScope("scope-act") {
    layout(R.layout.fx_card)
    anchor(FxGravity.BOTTOM_END)
    persist(FxSpStorage(this@ScopeHostActivity))
}
actFx.show()

// Any ViewGroup: the window is confined to that container
val boxFx = box.fxScope("scope-box") {
    layout(R.layout.fx_card)
    anchor(FxGravity.TOP_START)
}

// Fragment: fine to call in onCreate — it attaches once the view exists and cancels on destroy
class ScopeFragment : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        fxScope("scope-frag") {
            layout(R.layout.fx_card)
            anchor(FxGravity.CENTER)
        }.show()
    }
}

Activity.fxScope has no automatic cleanup below API 29, so cancel it yourself in onDestroy there (not cancelling still leaks nothing: the host is only referenced by the Activity's own view tree).

Choosing the host inside the install / create DSL

fxScope {} is the shorthand; you can also name the host explicitly inside the FloatingX.create(tag) {} / FloatingX.install(tag) {} DSL with viewGroupHost(viewGroup) / fragmentHost(fragment):

val fx = FloatingX.create("scope-dsl") {
    layout(R.layout.fx_card)
    anchor(FxGravity.TOP_END)
    viewGroupHost(container)          // or fragmentHost(fragment)
}
fx.show()

FloatingX.create does not register, FloatingX.install does; local windows normally use create.

Showing a window on top of a Dialog

A Dialog has its own Window that sits above the Activity, so a window attached to the Activity cannot cover it. Attach it to the Dialog's decorView instead (read decorView only after dialog.show()):

dialog.show()
val decor = dialog.window?.decorView as? ViewGroup ?: return
val dialogFx = FloatingX.create("dialog") {
    layout(R.layout.fx_card)
    anchor(FxGravity.TOP_END)
    viewGroupHost(decor)
}
dialogFx.show()
dialog.setOnDismissListener { if (dialogFx.state != FxState.CANCELLED) dialogFx.cancel() }

See FAQ for more questions of this kind.

Java

There is no DSL from Java; use ViewGroupHost.of(...) with FloatingX.create(...):

ViewGroup content = activity.findViewById(android.R.id.content);
FxControl control = FloatingX.create(config, ViewGroupHost.of(content), "java-scope");
control.show();

What the tag is for

For a local window the tag is only used for logging and as the position-persistence key — leave it empty and nothing is persisted. It takes no part in the registry, so reusing one tag on different pages never cancels anything.

Configuration (anchor / adsorption / gestures / animation / persistence) is identical to the other hosts, see Configuration; the FxControl methods are in API Reference.


Back to Home · Related: Getting Started Configuration FAQ App Host

Clone this wiki locally