2017-04-20 11 views
0

ListCellが表示されたら、アニメーション化しようとしています。 特に、新しいセルがリストに追加されたばかりのときに、そのセルをアニメーション化しようとしました。 今のところ、ListViewをスクロールするとインデックスがうまくいかず、間違ったセルがアニメーション化される場合を除き、かなりうまく動いています。 セルが新品のアイテムに使用されたときを検出するために、アイテムモデルにブール値のフラグ(入力)を使用します。JavaFXカスタムListCell

public class TimeListCell extends ListCell<MarkItem> { 

    private static final String BUTTON_GOTO_MARK_CLASS = "but-markgoto"; 
    private static final String LABEL_TIME_MARK_CLASS = "track-time"; 
    private static final String BUTTON_DELETE_MARK_CLASS = "but-markdel"; 
    private static final String MARK_HIGHLIGHT_CURRENT_CLASS = "highlighted"; 

    private Instant time; 

    private MarkItem markItem; 

    protected ListCellAnimation anim; 

    private HBox root = new HBox(); 
    private Button go = new Button(); 
    private Label track = new Label();; 
    private Button del = new Button(); 

    private ChangeListener<? super Boolean> highlightChange = (e, o, n) -> { setHighlighted(n); }; 

    public TimeListCell (Consumer<MarkItem> onGoto, Consumer<MarkItem> onDelete) { 

     root.setAlignment(Pos.CENTER); 

     go.getStyleClass().add(BUTTON_GOTO_MARK_CLASS); 
     go.setOnAction(e -> { 
      if (onGoto != null) { 
       // Trigger GOTO consumer function 
       onGoto.accept(markItem); 
      } 
     }); 
     track.getStyleClass().add(LABEL_TIME_MARK_CLASS); 
     del.getStyleClass().add(BUTTON_DELETE_MARK_CLASS); 
     del.setOnAction(e -> { 
      // First trigger exit animation then delete item 
      this.animateExit(onDelete); 
     }); 

     root.getChildren().add(go); 
     root.getChildren().add(track); 
     root.getChildren().add(del); 

    } 

    @Override 
    protected void updateItem (final MarkItem item, boolean empty) { 

     super.updateItem(item, empty); 

     if (markItem != null) { 
      markItem.highlightedProperty().removeListener(highlightChange); 
     } 

     if (!empty && item != null) { 
      markItem = item; 
      time = item.getTime(); 

      track.setText(DateUtil.format(time, DateUtil.Pattern.TIME)); 
      setGraphic(root); 

      item.highlightedProperty().addListener(highlightChange); 
      setHighlighted(item.isHighlighted()); 

      if (anim == null) { 
       //Adding Animation to the ListCell 
       anim = new ListCellAnimation(this); 
       //KeyFrame[] f = getKeyFrames(types); 
       KeyFrame[] frames = null; 
       if (anim.getKeyFrames().size() == 0) { 
        KeyFrame[] f = anim.getPopIn(frames); 
        if (f != null) { 
         anim.getKeyFrames().addAll(f); 
        } 
       } 
      } 

      if (item.isEntering()) { 
       //Checking when to play Animation 
       animateEnter(); 
       item.setEntering(false); 
      } 
     } else { 
      setGraphic(null); 
     } 
    } 

    /** 
    * Set/unset cell highlighted style for display. 
    * 
    * @param highlighted 
    *    Whether or not to highlight the cell 
    */ 
    public void setHighlighted (boolean highlighted) { 

     track.getStyleClass().remove(MARK_HIGHLIGHT_CURRENT_CLASS); 
     if (highlighted) 
      track.getStyleClass().add(MARK_HIGHLIGHT_CURRENT_CLASS); 
    } 

    /** 
    * Animate entering cell. 
    */ 
    private void animateEnter() { 
      if (anim != null && anim.getKeyFrames().size() >= 0 
        && (anim.getTimeline().getStatus() == Timeline.Status.STOPPED 
        || anim.getTimeline().getStatus() == Timeline.Status.PAUSED)) { 
        anim.getTimeline().playFromStart(); 
      } 
    } 

    /** 
    * Animate exiting cell. 
    * Trigger DELETE consumer function when animation is complete. 
    */ 
    private void animateExit (Consumer<MarkItem> onDelete) { 

     anim.getReversedTimeline().setOnFinished(t -> { 
      // Remove item from list 
      if (onDelete != null) { 
       onDelete.accept(markItem); 
      } 
      // Prepare cell for next item to use it 
      scaleXProperty().set(1); 
      scaleYProperty().set(1); 
      }); 
     anim.getReversedTimeline().playFromStart(); 
    } 

    public Instant getTime() { 

     return time; 
    } 
} 

セルのインデックス作成を台無しにする可能性のある人はいますか?おかげさまで

答えて

0

アニメーション化されたセルは、「入力」されていない項目を表示するために再利用されている場合、あなたは現在のアニメーションを停止する必要があります。一般的には

if (item.isEntering()) { 
     //Checking when to play Animation 
     animateEnter(); 
     item.setEntering(false); 
    } else { 
     anim.getTimeline().stop(); 
    } 

を、あなたは任意のことを想定しているように見えますセルは1つのアイテムにしか使用されていませんが、確かにそうではありません。あなたのコードには、この仮定の結果である他のバグがあるかもしれませんが、これは私が見ることができる主なものです。

+0

ありがとうございました。 – keuluu

+0

Jamesに感謝します。しかし、アニメーションの停止は、updateItemが "リフレッシュ"ごとに複数回呼び出されるため、うまくいっていません。アニメーションが停止するように、アイテムは後続の呼び出しでもう「入」しません。実際には、アイテムリストが長く、スクロールを開始する場合を除いて、今のように正常に機能しています。スクロールしてリストの最後に1つ以上の新しいセルが作成されると(セルが表示されているアイテムに再割り当てされることがわかっています)、リストに新しいアイテムを追加すると、ハイライト操作ターゲット右のセル... – keuluu

+0

すべてのスクロールする前に正常に動作します。しかし、下にスクロールしてセル(たとえば2つのセル)を表示すると、新しいアイテムを作成すると、作成されたアイテムを表すセルからアニメーションセルが2セル離れて表示されます。 – keuluu

関連する問題