Skip to content

Instantly share code, notes, and snippets.

@dlemmermann
Created June 19, 2018 09:08
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dlemmermann/20953076779073d706b6f152c6d32d2a to your computer and use it in GitHub Desktop.
Save dlemmermann/20953076779073d706b6f152c6d32d2a to your computer and use it in GitHub Desktop.
A JavaFX ScrollPane with a drop shadow effect at the top when the user scrolls down.
package uk.co.senapt.desktop.shell;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.Region;
import javafx.scene.shape.Rectangle;
/**
* Created by lemmi on 23.08.17.
*/
public class ShadowScrollPane extends ScrollPane {
private Region shadow = new Region();
public ShadowScrollPane() {
super();
init();
}
public ShadowScrollPane(Node content) {
super(content);
init();
}
private void init() {
skinProperty().addListener(it -> {
getChildren().addAll(shadow);
});
setFitToWidth(true);
setVbarPolicy(ScrollBarPolicy.NEVER);
setHbarPolicy(ScrollBarPolicy.NEVER);
shadow.setManaged(false);
shadow.setStyle("-fx-pref-height: 10;" +
"-fx-background-color: black;" +
"-fx-effect: dropshadow(gaussian, rgba(0, 0, 0, .75), 20, 0.19, 0, 6);");
shadow.getStyleClass().add("shadow");
shadow.visibleProperty().bind(showShadowProperty());
shadow.setMouseTransparent(true);
shadow.visibleProperty().bind(vvalueProperty().greaterThan(0));
Rectangle clip = new Rectangle();
clip.widthProperty().bind(widthProperty());
clip.heightProperty().bind(heightProperty());
setClip(clip);
vvalueProperty().addListener(it -> {
if (lastOffset != computeOffset()) {
requestLayout();
}
});
showShadowProperty().addListener(it -> requestLayout());
}
private final BooleanProperty showShadow = new SimpleBooleanProperty(this, "showShadow", true);
public final BooleanProperty showShadowProperty() {
return showShadow;
}
public final boolean isShowShadow() {
return showShadow.get();
}
public final void setShowShadow(boolean show) {
showShadow.set(show);
}
private final int SHADOW_HEIGHT = 30;
@Override
protected void layoutChildren() {
super.layoutChildren();
if (isShowShadow()) {
Insets insets = getInsets();
double w = getWidth();
double offset = computeOffset();
shadow.resizeRelocate(-10, insets.getTop() - shadow.prefHeight(-1) - SHADOW_HEIGHT + offset, w + 20, shadow.prefHeight(-1) - 1);
lastOffset = offset;
}
}
private double lastOffset = 0;
private double computeOffset() {
if (getContent() != null) {
return Math.min(getVvalue() * getContent().prefHeight(-1), SHADOW_HEIGHT);
}
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment