最近,在我的一个项目中,我发现用户很难看到ScrollPane实例的内容当前是否已滚动。 一种更清晰的方法是在滚动窗格的顶部添加阴影。
这也是Google的Material Design建议的。 所以我尝试了一下。 在我的解决方案中,我只是向ScrollPane添加了一个区域,并在对其进行布局时将其移出ScrollPane的视口边界,因此只有应用于该区域的阴影效果仍可以到达该区域。
为了真正确保该区域不可见,我还必须在ScrollPane上设置一个剪辑。 尽管我必须承认我不是100%确信这是实现此目标的最佳方法,但它的效果很好。 因此,如果有人有任何建议/替代方法,请发表评论。
在下面您将看到滚动我们应用程序屏幕之一的屏幕截图之前和之后的内容。
滚动之前
滚动后
顺便说一句:我实现了这种方式,使阴影不会突然出现,而是逐步移入视口,具体取决于用户滚动了多远。 要查看此内容,您需要非常缓慢地向下滚动。
ShadowScrollPane的代码可以在GitHub的以下要点中找到:
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;
}
}
翻译自: https://www.javacodegeeks.com/2018/06/javafx-scrollpane-dropshadow.html