This page was machine-translated from Portuguese and may contain errors. The Portuguese version is canonical.
How to make a Component scrollable and adjust the overscroll
Purpose. Any Component can become a scrollable container: just declare the direction with
setScrollable(ScrollDirection). If the content (the sum of the children’s heights) exceeds the
visible area, the ScrollEngine handles pan, momentum, fling, and the overscroll (elastic effect when
pulling beyond the limit).
APIs used
Component.setScrollable(ScrollDirection dir, ScrollEngine... engine)— enables scrolling.engineis optional (default: a newScrollEngine). Passnullasdirto disable.UIConstants.ScrollDirection— enum with three values:HORIZONTAL,VERTICAL,BOTH.Component.isScrollable()— whether the component is scrollable.Component.scrollable()— returns theScrollableobject (with.engine), ornull.Component.setShowScrollPosition(boolean)— shows/hides the scroll position indicator.ScrollEngine.setOverscroll(boolean x, boolean y)— turns the elastic effect on/off per axis. Default: bothtrue.ScrollEngine.setupOverscroll(float distance, float speedMin, float speedMax)— adjusts the overscroll distance and return speed.ScrollEngine.setScrollListener(ScrollListener listener)— callback on every offset change (receivesvx, vy).ScrollEngine.scrollTo(float x, float y)/scrollToStartSmooth()/scrollToEndSmooth()— repositions the scroll.ScrollEngine.setOverscrollEffect(OverscrollEffect effect)— static: sets/disables (null) the global gray edge curve; customizable vianew OverscrollEffect().setColor(...).setMaxAlpha(...).setMaxArcHeight(...).
Complete example (copy, paste and run)
package com.exemplo;
import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;
/** Runnable main screen. Point the launcher (classname) and run: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
@Override
public void onShow() throws Exception
{
super.onShow();
setLayout(new VerticalLayout());
Component painel = new Component();
painel.setLayout(new GridLayout(Position.CENTER, Position.START));
for (int i = 0; i < 60; i++)
painel.add(.95f, new Label("Linha " + i));
painel.setScrollable(ScrollDirection.VERTICAL); // scrolls on the Y axis
// optional tweaks to the scroll engine:
painel.scrollable().engine.setOverscroll(true, false); // elastic only on the vertical
painel.setShowScrollPosition(true); // position indicator
painel.scrollable().engine.setScrollListener((vx, vy) ->
Debug.log("scrollY = " + vy)); // reacts to scroll
add(LAY_FILL, painel);
}
}
The snippet below shows only the core. To run it, place it inside the
MainWindowskeleton above.
Minimal snippet
// verified in source: Component.setScrollable (line ~1027) + ScrollEngine.java
Component painel = new Component();
painel.setLayout(new GridLayout(Position.CENTER, Position.START));
for (int i = 0; i < 60; i++)
painel.add(.95f, new Label("Linha " + i));
painel.setScrollable(ScrollDirection.VERTICAL); // scrolls on the Y axis
// optional tweaks to the scroll engine:
painel.scrollable().engine.setOverscroll(true, false); // elastic only on the vertical
painel.setShowScrollPosition(true); // position indicator
painel.scrollable().engine.setScrollListener((vx, vy) ->
Debug.log("scrollY = " + vy)); // reacts to scroll
layout.add(1f, painel);
Repositioning by code:
painel.scrollable().engine.scrollToStartSmooth(); // scrolls back to top with animation
painel.scrollable().engine.scrollTo(0, 500); // jumps to offset y=500 px
Honest note: there is no ready-made pull-to-refresh
The framework does not offer a ready-made “pull-to-refresh” widget. What
exists is the overscroll effect (elastic curve when pulling beyond the limit), which is purely
visual/physical — it does not expose a “released after pulling X pixels” callback for you to trigger
a refresh. If you need that behavior, you will have to build it manually by monitoring the offset
via setScrollListener and detecting overscroll beyond a threshold. For large lists with
data reload, prefer VirtualListView.reloadData() triggered by a button or your own gesture.
Go deeper
- Huge lists come scrollable by default (the
VirtualListViewcallssetScrollable(VERTICAL)internally): see lista-virtual-grande.md.