9

次のような Android サポート ライブラリの Bottom Sheet を使用しています。

XML:

<LinearLayout
    android:id="@+id/bottomSheetLinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/fourth_white"
    android:orientation="vertical"
    app:layout_behavior="android.support.design.widget.BottomSheetBehavior" />

子ビューを LinearLayout に追加します。

bottomSheet.addView(actionButtonView);

子ビューの追加が完了したら、BottomSheetBehavior を初期化して展開します。

BottomSheetBehavior sheetBehavior = BottomSheetBehavior.from(bottomSheet);
sheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);

これはうまくいきません。何も表示されません。XML 内で LinearLayout の高さを事前に設定しても、すべて白です。

XML で LinearLayout 内にすべての子ビューを追加すると、すべて正常に動作します。プログラムでビューを動的に追加しようとすると、うまくいきません。

誰にも同様の問題がありましたか?

4

2 に答える 2

3

拡張サイズ計算の実装に関連する BottomSheetBehavior の動的コンテンツに関する問題。BottomSheetBehavior は onLayoutChild メソッドで展開サイズを計算します。ただし、シート レイアウト プロセスのコンテンツを変更すると、非同期で起動します。RequestLayout などを呼び出しても。したがって、呼び出しの結果は次のようになります。

  1. BottomSheetBehavior には古い拡張サイズがあります (あなたの場合はゼロだと思います)
  2. BottomSheet にコンテンツを追加します。拡張サイズはまだ古いです。
  3. SetState を EXPANDED に呼び出します。BottomSheetBehavior は古い拡張サイズを記憶しており、アニメーションをそのサイズで起動します。状態が STATE_SETTRING に変更されました!
  4. onLayoutChild が呼び出され、BottomSheetBehavior が新しい拡張サイズを計算します。ただし、アニメーションは既に進行中であり、状態は STATE_SETTING であるため、BottomSheetBehavior はサイズを変更しません。
  5. アニメーション終了。BottomSheet のサイズが古いです。状態は EXPANDED に変更されましたが、BottomSheetBehavior は、アニメーション中に拡張サイズが変更されたことを「忘れて」いました。

間違いなく BottomSheetBehaviour 実装のバグです。

私のプロジェクトでは、そのような回避策を見つけました:

private void showPanel(final View panelContent) {
    if (panelBehavior.getState()!=BottomSheetBehavior.STATE_EXPANDED) {
        panelBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(final View bottomSheet, int newState) {
                if (newState==BottomSheetBehavior.STATE_EXPANDED) {
                    panelBehavior.setBottomSheetCallback(null);
                    contentView.removeAllViews();
                    contentView.addView(panelContent);
                    panelView.setVisibility(View.VISIBLE);

                }
            }

            @Override
            public void onSlide(View bottomSheet, float slideOffset) {

            }
        });
        panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
        return;
    }
    contentView.removeAllViews();
    contentView.addView(panelContent);
    panelView.setVisibility(View.VISIBLE);
}

private void hidePanel() {
    panelBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    panelView.setVisibility(View.GONE);
    contentView.removeAllViews();
}

したがって、新しいコンテンツで BottomSheet を表示する必要がある場合は、ShowPanel を呼び出します。BottomSheet を完全に非表示にする必要がある場合は、hidePanel を呼び出します (プロジェクトで非表示にする必要がある場合。そうでない場合は、メソッドから setVisibility を削除できます)。

BottomSheetBehavior が展開状態でない場合、BottomSheet の内容を決して変更しないという回避策があります。状態が展開されていない場合は、展開された状態に変更し、アニメーションが終了するまで待ってからコンテンツを変更してください。

于 2017-11-19T05:32:26.660 に答える