Skip to content

Configuration

petterp edited this page Aug 30, 2026 · 2 revisions

Configuration

FxConfig is immutable. Kotlin uses the FxConfigScope DSL (FloatingX.install(tag) {} takes an FxInstallScope, which is an FxConfigScope plus a host); Java uses FxConfig.builder(FxContent.layout(id)). Once installed, control.update {} patches the old config — anything you do not set explicitly keeps its previous value.

Capabilities

Capability API Notes
Anchor positioning anchor(FxGravity, dx, dy) 9 gravities; dx/dy are offsets inward from the anchored edge; START/END flip under RTL
Margin margin(left, top, right, bottom) Extra inset on the four edges of the usable area
Safe area safeArea = true/false Whether to avoid status bar / navigation bar / display cutout
Overflow overflow(top, bottom, left, right) Which edges the content may exceed
Edge adsorption adsorb(FxAdsorb.Edges(edges, halfHide, rebound)) Any of the four edges; FxAdsorb.horizontal()/vertical()/all()/none()
Half hide FxHalfHide(start, end) Different ratios for the start and end edges
Rebound FxAdsorb.Edges(rebound = true) May leave the usable area while dragging, springs back on release
Drag mode gesture { drag = FxDrag.IMMEDIATE / AFTER_LONG_PRESS / DISABLED } Drag on touch / after long press / never
Drag region gesture { dragRegion = FxRegion.child(R.id.header) } Also FxRegion.rect(...) or your own
Child priority gesture { childPriority = FxChildPriority.AUTO / PARENT / CHILD } Who owns vertical gestures when the content holds a RecyclerView
Touch pass-through gesture { touchable = false } The window eats no touches at all
Click / long press gesture { click = …; longPress = …; longPressTimeout = … } Presets: FxGesture.Normal / ClickOnly / DisplayOnly / LongPressToDrag
Animation animation(FxAnimations.fade()) / scale() / a custom FxAnimation Show / hide animations
Position persistence persist(FxSpStorage(context)) Key includes the tag and the orientation, so portrait and landscape are remembered separately; or implement FxStorage
Black / white list appHost(app) { blacklist(X::class.java); whitelist(...); filter { … } } The Class form matches with isInstance, so subclasses are hit too; class-name strings also work
Attach target appHost(app) { attachTo(AppAttachTarget.DECOR / CONTENT) } DecorView by default (truly full-screen dragging)
Modal modal(enabled, dismissOnOutsideTouch) Intercepts touches outside the content while the window is shown (a hidden window lets them through), optionally hiding on outside touch (app / scope only)
Keyboard systemHost(app) { keyboard(R.id.etInput) } System windows are not focusable by default; touching these EditTexts makes them temporarily focusable
Back key systemHost(app) { onBackPressed { true } } Only delivered while the keyboard is up (that's when the window is focusable)
Multiple windows FloatingX.install(tag) {} / controls() / uninstall(tag) Global windows are keyed by tag; installing over a tag cancels the old one
Logging enableLog("Fx-demo") adb logcat | grep "Fx-"; completely silent unless enabled
Custom behaviour addFeature(FxFeature) Container behaviour plugin; Location / Gesture / Animation / ModalScrim are built in

Black/white lists and the attach target belong to App Host, keyboard and back key to System Host; the sections below cover only the host-independent options.

Content

layout(R.layout.fx_card)          // layout id
view(someView)                    // an existing view
view { ctx -> DemoContent.card(ctx) }   // built from a context on demand (preferred: can be rebuilt on host / theme change)
content(FxContent.layout(id))     // hand over an FxContent directly

The three forms map to FxContent.Layout / FxContent.Static / FxContent.Provider; from Java they are FxContent.layout(id) / FxContent.view(v) / FxContent.provider {}. After installation you can swap the content wholesale or edit views inside it, see API Reference.

Anchor and offsets

anchor(gravity, dx = 0f, dy = 0f). What is stored is "which edge + offset", not a top-left coordinate, so the anchored edge stays put when the content resizes (longer text, expand/collapse). dx/dy are offsets inward from the anchored edge, in dp. The 9 FxGravity values are TOP_START / TOP_CENTER / TOP_END / CENTER_START / CENTER / CENTER_END / BOTTOM_START / BOTTOM_CENTER / BOTTOM_END; START / END are logical directions and flip under RTL.

margin / safeArea / overflow

margin(top = 24f, bottom = 24f)   // extra inset on the edges of the usable area (named args, set what you need)
safeArea = false                  // true by default: avoid status bar / navigation bar / cutout
overflow(top = true, left = true) // which edges the content may exceed; none by default

Together they define the "usable area": the screen (or container) minus the safe area, minus the margin; overflow lifts the limit on the edges you name.

Adsorption, half hide and rebound

adsorb(FxAdsorb.Edges(setOf(FxEdge.START, FxEdge.END), halfHide = FxHalfHide(0.3f), rebound = true))
adsorb(FxAdsorb.horizontal())     // vertical() / all() / none() also exist

Pass FxHalfHide(start, end) to use different ratios on the start and end edges; rebound = true lets the window leave the usable area while dragging and spring back on release (always on in 2.x, switchable in 3.0). Which edge it settled on is reported by FxListener.onPositionChanged(control, anchor), see API Reference.

Gestures

gesture {
    drag = FxDrag.AFTER_LONG_PRESS            // IMMEDIATE / AFTER_LONG_PRESS / DISABLED
    dragRegion = FxRegion.child(R.id.header)  // also FxRegion.rect(...) or your own (fun interface)
    childPriority = FxChildPriority.AUTO      // AUTO / PARENT / CHILD: conflict policy with scrollable children
    touchable = true                          // false = full pass-through, touching it touches what is below
    click = true
    longPress = true
    longPressTimeout = 0L                     // 0 = use the system ViewConfiguration.getLongPressTimeout()
}
gesture(FxGesture.LongPressToDrag)            // or just take a preset

Presets: FxGesture.Normal (default) / ClickOnly / DisplayOnly / LongPressToDrag. They are @JvmField statics on the Java side; use new FxGesture(...) when you need finer control.

Animation

animation(FxAnimations.fade())     // or FxAnimations.scale(), both take a duration
animation(null)                    // no animation (the default)

For a custom one, implement FxAnimation and override showAnimator(view) / hideAnimator(view) to return an Animator.

Modal

modal(enabled = true, dismissOnOutsideTouch = false)

Intercepts touches outside the content while the window is shown and lets them through once hidden; dismissOnOutsideTouch = true hides the window on an outside touch. It applies to the app and scope hosts only (a system window's shielding is decided by its WindowManager flags).

Position persistence

persist(FxSpStorage(app))          // persist(null) turns it off

The storage key is generated as "$tag:$orientation", so portrait and landscape are remembered separately. Implement FxStorage (save(key, anchor) / load(key) / clear(key)) to use your own storage; drop a remembered position with FxStorage.clear(key). A local window with an empty tag persists nothing, see Scope Host.

Logging

enableLog("Fx-demo")               // completely silent unless called

The library's own log tags are Fx-<scope> (e.g. Fx-system), so adb logcat | grep "Fx-" catches everything.

Custom behaviour

addFeature(MyFeature())

FxFeature is a container behaviour plugin; Location / Gesture / Animation / ModalScrim are built in. Add a feature rather than stuffing code into the content — how to write one is in Architecture.

Changing the config afterwards

control.update { anchor(FxGravity.BOTTOM_END); gesture { drag = FxDrag.DISABLED } }   // patch the config

update {} uses the very same FxConfigScope DSL. The full FxControl surface is in API Reference.


Back to Home · Related: Getting Started API Reference Architecture App Host

Clone this wiki locally