add addScrollFinishedListener

This commit is contained in:
Timi
2026-01-09 15:46:47 +08:00
parent e1b5cefc90
commit 9e1ec1debc

View File

@ -1,10 +1,18 @@
package com.imyeyu.fx; package com.imyeyu.fx;
import com.imyeyu.fx.utils.ScreenFX;
import com.imyeyu.java.bean.Callback;
import com.imyeyu.java.ref.Ref;
import com.imyeyu.utils.Calc;
import com.imyeyu.utils.OS;
import javafx.application.Application; import javafx.application.Application;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.geometry.Rectangle2D; import javafx.geometry.Rectangle2D;
import javafx.scene.Node; import javafx.scene.Node;
@ -18,10 +26,6 @@ import javafx.stage.Screen;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.stage.Window; import javafx.stage.Window;
import javafx.stage.WindowEvent; import javafx.stage.WindowEvent;
import com.imyeyu.fx.utils.ScreenFX;
import com.imyeyu.java.ref.Ref;
import com.imyeyu.utils.Calc;
import com.imyeyu.utils.OS;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -281,7 +285,7 @@ public final class TimiFX {
* @param control 控件({@link javafx.scene.control.ListView}, {@link javafx.scene.control.TableView} 等) * @param control 控件({@link javafx.scene.control.ListView}, {@link javafx.scene.control.TableView} 等)
* @param index 指定项下标 * @param index 指定项下标
*/ */
public static void scrollToCenter(Control control, int index) { public static void scrollToCenter(Control control, int index) {
try { try {
if (control.getSkin() == null) { if (control.getSkin() == null) {
return; return;
@ -301,7 +305,38 @@ public final class TimiFX {
} }
} }
public static void addScrollFinishedListener(Control control, Callback callback) {
BooleanProperty finish = new SimpleBooleanProperty(false);
control.skinProperty().addListener((obs, o, skin) -> {
try {
VirtualFlow<?> flow = Ref.getFieldValue(control.getSkin(), "flow", VirtualFlow.class);
if (flow == null) {
throw new UnsupportedOperationException("unsupported this control");
}
// 监听总高度和视口高度的变化
Observable[] dependencies = {flow.layoutBoundsProperty(), flow.parentProperty()};
BooleanBinding binding = Bindings.createBooleanBinding(() -> {
double totalHeight = flow.prefHeight(-1);
double viewportHeight = flow.getLayoutBounds().getHeight();
if (viewportHeight <= 0 || totalHeight <= 0) {
return false;
}
double maxVValue = (totalHeight - viewportHeight) / viewportHeight;
double currentVValue = flow.getLayoutY() / viewportHeight;
return currentVValue >= (maxVValue - 0.01);
}, dependencies);
finish.bind(binding);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
finish.addListener((obs, o, isFinished) -> {
if (isFinished) {
callback.handler();
}
});
}
/** /**
* 重启程序,命令需自定 * 重启程序,命令需自定