-
Notifications
You must be signed in to change notification settings - Fork 188
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.
| 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.
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 directlyThe 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(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(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 defaultTogether 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.
adsorb(FxAdsorb.Edges(setOf(FxEdge.START, FxEdge.END), halfHide = FxHalfHide(0.3f), rebound = true))
adsorb(FxAdsorb.horizontal()) // vertical() / all() / none() also existPass 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.
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 presetPresets: FxGesture.Normal (default) / ClickOnly / DisplayOnly / LongPressToDrag. They are
@JvmField statics on the Java side; use new FxGesture(...) when you need finer control.
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(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).
persist(FxSpStorage(app)) // persist(null) turns it offThe 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.
enableLog("Fx-demo") // completely silent unless calledThe library's own log tags are Fx-<scope> (e.g. Fx-system), so adb logcat | grep "Fx-" catches
everything.
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.
control.update { anchor(FxGravity.BOTTOM_END); gesture { drag = FxDrag.DISABLED } } // patch the configupdate {} 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