我想要一些关于如何在用户按下按钮时为窗格实现幻灯片转换的指南,就像Material Design为滑动菜单做的那样。
这是一段视频link,说明了我的需求。
我尝试过ScaleTransition,TranslateTransition,但他们没有做到这一点。
我试图实现它的方式效率不高。
package com.helloworld;
import com.gluonhq.charm.glisten.animation.ShrinkExpandAnimation;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HelloWorld extends Application {
ShrinkExpandAnimation anim;
@Override
public void start(Stage stage) {
Button btn = new Button("Click Me!");
btn.setOnMouseClicked(e-> {
System.out.println("swiping...");
anim.play();
});
AnchorPane pane = new AnchorPane();
pane.setStyle("-fx-background-color: coral");
pane.getChildren().add(btn);
// false to shrink or true to expand
anim = new ShrinkExpandAnimation(pane, false);
Scene scene = new Scene(new StackPane(pane), 640, 480);
stage.setScene(scene);
stage.show();
}
}
---更新---
以下是从here下载的Gluon应用示例。这是一个gradle项目,我修改它以显示一个按钮而不是默认标签。
我希望在用户点击按钮时缩小AnchorPane。
我错过了什么?
public class SwipeMenuDemo extends Application {
AnchorPane swapPane;
Button btnMenu;
boolean isExpanded = true;
@Override
public void start(Stage stage) {
Label swapPaneLabel = new Label("Expandable Pane");
swapPaneLabel.setMinWidth(0);
ImageView swapPaneImage = new ImageView("http://vignette1.wikia.nocookie.net/jfx/images/5/5a/JavaFXIsland600x300.png");
swapPaneImage.setLayoutY(100);
Label rootPaneLabel = new Label("Root Pane");
rootPaneLabel.setStyle("-fx-font-size: 60;");
rootPaneLabel.setLayoutX(180);
rootPaneLabel.setLayoutY(180);
swapPane = new AnchorPane();
swapPane.setPrefSize(640, 440);
swapPane.setMinWidth(0);
swapPane.setLayoutY(40);
swapPane.setStyle("-fx-background-color: coral; -fx-font-size: 52;");
swapPane.getChildren().addAll(swapPaneImage, swapPaneLabel);
btnMenu = new Button("Menu");
btnMenu.setLayoutX(5);
btnMenu.setLayoutY(5);
btnMenu.setOnMouseClicked(e -> {
if (isExpanded) hideSwapPane().play();
else showSwapPane().play();
});
Button btnClose = new Button("Close");
btnClose.setLayoutX(590);
btnClose.setLayoutY(5);
btnClose.setOnMouseClicked(e -> Platform.exit());
AnchorPane rootPane = new AnchorPane();
rootPane.setStyle("-fx-background-color: grey;");
rootPane.getChildren().addAll(btnMenu, btnClose, rootPaneLabel, swapPane);
Scene scene = new Scene(rootPane, 640, 480);
stage.setScene(scene);
stage.initStyle(StageStyle.UNDECORATED);
stage.show();
}
private Animation hideSwapPane() {
btnMenu.setMouseTransparent(true);
Animation collapsePanel = new Transition() {
{
setCycleDuration(Duration.millis(2500));
}
@Override
protected void interpolate(double fraction) {
swapPane.setPrefWidth(640 * (1.0 - fraction));
}
};
collapsePanel.setOnFinished(e-> {
isExpanded = false;
btnMenu.setMouseTransparent(false);
});
return collapsePanel;
}
private Animation showSwapPane() {
btnMenu.setMouseTransparent(true);
final Animation expandPanel = new Transition() {
{
setCycleDuration(Duration.millis(2500));
}
@Override
protected void interpolate(double fraction) {
swapPane.setPrefWidth(640 * fraction);
}
};
expandPanel.setOnFinished(e-> {
isExpanded = true;
btnMenu.setMouseTransparent(false);
});
return expandPanel;
}
}
---更新2 ---
我设法使用本机JavaFX API实现类似于我想要的东西,而没有外部库。
虽然,我遇到了一些问题。
接下来的两张图片说明了我遇到的第一个问题。
这是一个AnchorPane(珊瑚色全宽;展开),位于AnchorPane(灰色的根窗格)内。
当您单击“菜单”按钮缩小/隐藏它时会发生这种情况。如您所见,珊瑚色窗格收缩/隐藏,但不是它的节点(Label,ImageView)
我发布了整个代码来自己重现这个问题:
{{1}}
---更新3 ---
根据我的需要修改了Felipe Guizar Diaz为我提供的代码,因为我想在透明的舞台窗口上设置一个阴影效果。
当我点击菜单按钮显示左侧窗格时,它会显示在阴影前面。即使在SceneBuilder中,我已经将StackPane放置在所有节点前面。
当我按下显示菜单并开始播放开放转换时,这是“神器”...
我该如何解决?
答案 0 :(得分:18)
我是示例视频的作者。我将重复我在视频评论中所做的回复:
“你应该把它想象成android中的导航抽屉,JavaFX中的导航抽屉将是一个AnchorPane
,有2个孩子,首先是StackPane
,相当于FrameLayout
作为我们的工作主要内容,其中窗格的转换取决于左侧菜单中的所选项目,最终ListView
作为我们的左侧菜单,其中translateX
为Listview
,等于translateX
然后,当用户按下按钮时,您必须播放一个动画,其值为0
至prefWidth()
。“
您不应在两个动画的插值方法中使用AnchorPane
(折叠面板,展开窗格),因为子节点不会调整大小,边距排列是public class FXMLDocumentController implements Initializable {
@FXML
private Button menu;
@FXML
private AnchorPane navList;
@Override
public void initialize(URL url, ResourceBundle rb) {
//navList.setItems(FXCollections.observableArrayList("Red","Yellow","Blue"));
prepareSlideMenuAnimation();
}
private void prepareSlideMenuAnimation() {
TranslateTransition openNav=new TranslateTransition(new Duration(350), navList);
openNav.setToX(0);
TranslateTransition closeNav=new TranslateTransition(new Duration(350), navList);
menu.setOnAction((ActionEvent evt)->{
if(navList.getTranslateX()!=0){
openNav.play();
}else{
closeNav.setToX(-(navList.getWidth()));
closeNav.play();
}
});
}
}
具有的唯一约束。
看看我做的这个例子。
https://github.com/marconideveloper/leftsidemenuexample
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" id="AnchorPane" prefWidth="500" prefHeight="500" fx:controller="leftslidemenusample.FXMLDocumentController">
<children>
<ToolBar AnchorPane.topAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" minHeight="56.0" >
<Button text="menu" fx:id="menu" />
</ToolBar>
<StackPane fx:id="mainContent" style="-fx-background-color:rgba(0,0,0,0.30)" AnchorPane.bottomAnchor="0.0" AnchorPane.topAnchor="56.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" >
<children>
</children>
</StackPane>
<AnchorPane fx:id="navList" style="-fx-background-color:white" AnchorPane.topAnchor="56.0" AnchorPane.bottomAnchor="0.0" prefWidth="180.0" translateX="-180" >
<children>
<Label text="left side menu"/>
</children>
</AnchorPane>
</children>
</AnchorPane>
这是fxml:
LARGE_INTEGER
答案 1 :(得分:3)
最后,我完成了它。
他们的主要特点是:
以下是控制这些效果的源代码片段:
@Override
public void initialize(URL url, ResourceBundle rb) {
...
Rectangle clip = new Rectangle(rootPaneWidth, rootPaneHeight);
rootPane.setClip(clip);
rootPane.getChildren().add(setupShadowPane());
}
private Pane setupShadowPane() {
Pane shadowPane = new Pane();
shadowPane.setStyle(
"-fx-background-color: white;" +
"-fx-effect: dropshadow(gaussian, black, " + shadowSize + ", 0, 0, 0);" +
"-fx-background-insets: " + shadowSize + ";"
);
Rectangle innerBounds = new Rectangle();
Rectangle outerBounds = new Rectangle();
shadowPane.layoutBoundsProperty().addListener((observable, oldBounds, newBounds) -> {
innerBounds.relocate(newBounds.getMinX() + shadowSize, newBounds.getMinY() + shadowSize);
innerBounds.setWidth(newBounds.getWidth() - shadowSize * 2);
innerBounds.setHeight(newBounds.getHeight() - shadowSize * 2);
outerBounds.setWidth(newBounds.getWidth());
outerBounds.setHeight(newBounds.getHeight());
Shape clip = Shape.subtract(outerBounds, innerBounds);
shadowPane.setClip(clip);
});
return shadowPane;
}
半开幻灯片菜单
完全打开幻灯片菜单
幻灯片菜单已关闭