Summary

JPanelで作成したサイドメニューをJLayeredPaneのモーダルレイヤーに追加し、その展開および折りたたみをアニメーション付きで実行します。

Source Code Examples

private void initLayeredPane() {
  JLayeredPane layeredPane = getRootPane().getLayeredPane();
  layeredPane.add(mainContent, JLayeredPane.DEFAULT_LAYER);
  layeredPane.add(overlay, JLayeredPane.PALETTE_LAYER);
  layeredPane.add(drawer, JLayeredPane.MODAL_LAYER);
  layeredPane.addComponentListener(new ComponentAdapter() {
    @Override public void componentResized(ComponentEvent e) {
      updateLayoutSizes();
    }
  });
}

private void toggleDrawer() {
  if (!timer.isRunning()) {
    isOpen = !isOpen;
    int w = getRootPane().getContentPane().getWidth();
    startX = drawer.getX();
    targetX = isOpen ? getOpenX(w) : getClosedX(w);
    overlay.setVisible(isOpen);
    startTime = System.currentTimeMillis();
    timer.start();
  }
}

private void animate() {
  long elapsed = System.currentTimeMillis() - startTime;
  double progress = Math.min(1d, (double) elapsed / DURATION);
  double easedProgress = 1 - Math.pow(1 - progress, 3);
  int currentX = (int) (startX + (targetX - startX) * easedProgress);
  drawer.setLocation(currentX, 0);
  boolean stop = progress >= 1d;
  if (stop) {
    timer.stop();
    if (!isOpen) {
      overlay.setVisible(false);
    }
  }
}
View in GitHub: Java, Kotlin

Description

  • JLayeredPaneJRootPaneからgetLayeredPane()で取得して利用する
    • JFrameに合わせてJLayeredPaneがリサイズされると内部のオーバーレイJPanelやドロワーJPanelの幅、高さも更新されるようComponentListenerを設定
  • JRootPane#getContentPane()で取得したコンテンツペインにメインコンテンツを追加
    • このサンプルのメインコンテンツは展開用JButtonや展開開始サイド選択のJRadioButtonを配置したJPanel
    • JLayeredPaneJLayeredPane.DEFAULT_LAYERにメインコンテンツを追加する方法もあり、その場合コンテンツペインが奥、JLayeredPane.DEFAULT_LAYERに配置したコンテンツが手前に表示される
  • JLayeredPaneJLayeredPane.PALETTE_LAYERにドロワー展開時にメインコンテンツへの入力をブロックする半透明のオーバーレイJPanelを追加
    • ドロワーが折りたたまれて非表示の場合はこのオーバーレイJPanelsetVisible(false)で非表示にする
    • オーバーレイJPanelにはMouseListenerを追加して、クリックされるとドロワーJPanelを折りたたむよう設定
  • JLayeredPaneJLayeredPane.MODAL_LAYERにサイドメニューとしてJButtonを配置したドロワーJPanelを追加
    • このサンプルではドロワーJPanelJScrollPaneでラップしてメニューがあふれる場合はスクロール可能にしている
    • ドロワーJPanelの展開・折りたたみアニメーションはTimerでキーフレームを作成し、イーズアウトで速度変化しながらx座標を変更することで実施

Reference

Comment