2016-10-25 18 views
-1

RecyclerViewcustom layout managerを作成しました。 RecyclerViewlayout_heightこのプロパティLayoutManagerwrap_contentに設定されているが、その中のアイテムに応じてRecyclerViewの高さを測定することができるときに私はsetAutoMeasureEnabled(true)カスタムRecyclerViewのLayoutManager。アニメーションが完了した後の自動計測アイテムの削除

を経由して、私のマネージャーのコンストラクタで自動測定を有効にしています。それは完全に動作しますが、最後の項目を削除すると、その時点で削除アニメーションが再生されているため、アニメーションが終了する前に高さを測定するのがRecyclerViewになります。

このgifを見てください。その場合には、コンテナは、私がRecyclerViewを処理するために、このような状況に対処するにはどうすればよいのアニメーション

前に測定する必要があるので、あなたは、この動作を推測しているよう緑色の背景はRecyclerView

ある enter image description here は、項目を追加するための正しいですアニメーション終了後の自動測定? 私はonLayoutChildrenにすべての子ポジショニングロジックを持っていますが、この質問には必須ではなく、広範かつ不明瞭である可能性があります。

おそらく、私はlayoutManagerのonMeasureインターセプタを手動で処理する必要があります(アイテムが削除された時(onItemsRemoved呼び出しの前に1回))。

@Override 
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { 
    super.onMeasure(recycler, state, widthSpec, heightSpec); 
    requestSimpleAnimationsInNextLayout(); 
    if (!isAutoMeasureEnabled()) { 
     setMeasuredDimension(getWidth(), preHeight); 
    } 
} 

@Override 
public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) { 
    super.onItemsRemoved(recyclerView, positionStart, itemCount); 
    setAutoMeasureEnabled(false); 

    new Handler(Looper.myLooper()).postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      setAutoMeasureEnabled(true); 
      requestSimpleAnimationsInNextLayout(); 
      requestLayout(); 
     } 
    }, 400); 

    preHeight = //calculate height before deletion 
} 

を見てわかるように、私は、アニメーションが終了後に自動測定を実行し、およそ遅れ400ms値、とのハンドラを提供:だから私は、削除が開始された時に受信され、高さに基づいて、そこに測定した高さを設定することができますこれは必要な結果につながる可能性がありますが、アニメーションの時間は静的ではなく、アニメーションの終了イベントを聞く可能性はありません。

ので、望ましい行動:あなたはそれは次のようになり、アルゴリズムの単なるテキスト記述で、正しい方向に私を指摘した場合

enter image description here

LinearLayoutManagerの道の自動測定することで、同じよう

で動作します十分な。

+0

コメントなしで私をdownvotedしたので私は私の質問の質を向上させることができません – Beloo

答えて

0

私は最後にそれを理解しました。 それで、私の解決策:

dataChangesイベントにonAdapterChangedメソッドを購読し、自動測定を無効にします。ケースの自動測定無効対策でonMeasure

@Override 
public void onAdapterChanged(RecyclerView.Adapter oldAdapter, 
          RecyclerView.Adapter newAdapter) { 
    newAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { 
     @Override 
     public void onItemRangeRemoved(int positionStart, int itemCount) { 
      // on api 16 this is invoked before onItemsRemoved 
      super.onItemRangeRemoved(positionStart, itemCount); 
      /** we detected removing event, so should process measuring manually 
      */ 
      setAutoMeasureEnabled(false); 
     } 
    }); 
    //Completely scrap the existing layout 
    removeAllViews(); 
} 

手動で、現在のサイズを使用します。アニメーションが終了した後

@Override 
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { 
    super.onMeasure(recycler, state, widthSpec, heightSpec); 

    if (!isAutoMeasureEnabled()) { 
     // we should perform measuring manually 
     // so request animations 
     requestSimpleAnimationsInNextLayout(); 
     //keep size until remove animation will be completed 
     setMeasuredDimension(getWidth(), getHeight()); 
    } 
} 

が自動測定を実行します。

@Override 
public void onItemsRemoved(final RecyclerView recyclerView, int positionStart, int itemCount) { 
    super.onItemsRemoved(recyclerView, positionStart, itemCount); 
    //subscribe to next animations tick 
    postOnAnimation(new Runnable() { 
     @Override 
     public void run() { 
      //listen removing animation 
      recyclerView.getItemAnimator().isRunning(new RecyclerView.ItemAnimator.ItemAnimatorFinishedListener() { 
       @Override 
       public void onAnimationsFinished() { 
        //when removing animation finished return auto-measuring back 
        setAutoMeasureEnabled(true); 
        // and process onMeasure again 
        requestLayout(); 
       } 
      }); 
     } 
    }); 

をこのコールバックチェーンは安全であるが、レイアウトマネージャがデタッチされている場合にpostOnAnimationの実行可能ファイルが実行されないため、RecyclerView

関連する問題