2016-08-06 5 views
14

BottomSheetDialogの動作についてはかなり興味があります。ユーザがそれを隠すためにドラッグすると、後でbottomSheetDialog#show()が呼び出されても非表示のままです。これは、ユーザーが外に触れるとき、またはbottomSheetDialog#dismiss()がプログラムで呼び出されたときではなく、ドラッグされたときにのみ発生します。BottomSheetDialogは、下にドラッグして消されたままになっています

bottomSheetDialogの内部にはrecyclerviewがあり、bottomSheetDialogを表示するたびに新しいものを作成する必要があるため、実際は迷惑です。

ので、代わりにちょうどこれを行うには:

if(bottomSheetDialog != null){ 
    bottomSheetDialog.show(); 
else{ 
    createNewBottomSheetDialog(); 
} 

私は1つを毎回作成する必要があります。

何かが欠落していますか、それとも正常な動作ですか? (私はappcompat-v7:23.2.1を使用します)

答えて

6

は、だから私は最終的に直接見ることで、この問題を解決するために管理BottomSheetDialogの実装に入りましたが、それは単なるDialogのような単純なものであることがわかりました。BottomSheet
問題がBottomSheetCallBackにあった:

@Override 
    public void onStateChanged(@NonNull View bottomSheet, 
      @BottomSheetBehavior.State int newState) { 
     if (newState == BottomSheetBehavior.STATE_HIDDEN) { 
      dismiss(); 
     } 
    } 

状態HIDDENは、ダイアログが引きずられることによって却下されたときにたまたま到達したときに問題が発生します。その後、bottomSheetDialog.show()が呼び出されても、ダイアログは隠れたままです。私が見つけた最も簡単な修正は、この状態を取り除き、それをCOLLAPSED状態に置き換えることでした。

私は全体BottomSheetDialogクラスをコピーして、問題を解決するために、単一の行を追加して、classCustomBottomSheetDialogを作成します。

public class CustomBottomSheetDialog extends AppCompatDialog { 

    public CustomBottomSheetDialog (@NonNull Context context) { 
     this(context, 0); 
    } 

    public CustomBottomSheetDialog (@NonNull Context context, @StyleRes int theme) { 
     super(context, getThemeResId(context, theme)); 
     // We hide the title bar for any style configuration. Otherwise, there will be a gap 
     // above the bottom sheet when it is expanded. 
     supportRequestWindowFeature(Window.FEATURE_NO_TITLE); 
    } 

    protected CustomBottomSheetDialog (@NonNull Context context, boolean cancelable, 
      OnCancelListener cancelListener) { 
     super(context, cancelable, cancelListener); 
     supportRequestWindowFeature(Window.FEATURE_NO_TITLE); 
    } 

    @Override 
    public void setContentView(@LayoutRes int layoutResId) { 
     super.setContentView(wrapInBottomSheet(layoutResId, null, null)); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     getWindow().setLayout(
       ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 
    } 

    @Override 
    public void setContentView(View view) { 
     super.setContentView(wrapInBottomSheet(0, view, null)); 
    } 

    @Override 
    public void setContentView(View view, ViewGroup.LayoutParams params) { 
     super.setContentView(wrapInBottomSheet(0, view, params)); 
    } 

    private View wrapInBottomSheet(int layoutResId, View view, ViewGroup.LayoutParams params) { 
     final CoordinatorLayout coordinator = (CoordinatorLayout) View.inflate(getContext(), 
       R.layout.design_bottom_sheet_dialog, null); 
     if (layoutResId != 0 && view == null) { 
      view = getLayoutInflater().inflate(layoutResId, coordinator, false); 
     } 
     FrameLayout bottomSheet = (FrameLayout) coordinator.findViewById(R.id.design_bottom_sheet); 
     BottomSheetBehavior.from(bottomSheet).setBottomSheetCallback(mBottomSheetCallback); 
     if (params == null) { 
      bottomSheet.addView(view); 
     } else { 
      bottomSheet.addView(view, params); 
     } 
     // We treat the CoordinatorLayout as outside the dialog though it is technically inside 
     if (shouldWindowCloseOnTouchOutside()) { 
      coordinator.findViewById(R.id.touch_outside).setOnClickListener(
        new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          if (isShowing()) { 
           cancel(); 
          } 
         } 
        }); 
     } 
     return coordinator; 
    } 

    private boolean shouldWindowCloseOnTouchOutside() { 
     if (Build.VERSION.SDK_INT < 11) { 
      return true; 
     } 
     TypedValue value = new TypedValue(); 
     //noinspection SimplifiableIfStatement 
     if (getContext().getTheme() 
       .resolveAttribute(android.R.attr.windowCloseOnTouchOutside, value, true)) { 
      return value.data != 0; 
     } 
     return false; 
    } 

    private static int getThemeResId(Context context, int themeId) { 
     if (themeId == 0) { 
      // If the provided theme is 0, then retrieve the dialogTheme from our theme 
      TypedValue outValue = new TypedValue(); 
      if (context.getTheme().resolveAttribute(
        R.attr.bottomSheetDialogTheme, outValue, true)) { 
       themeId = outValue.resourceId; 
      } else { 
       // bottomSheetDialogTheme is not provided; we default to our light theme 
       themeId = R.style.Theme_Design_Light_BottomSheetDialog; 
      } 
     } 
     return themeId; 
    } 

    private BottomSheetBehavior.BottomSheetCallback mBottomSheetCallback 
      = new BottomSheetBehavior.BottomSheetCallback() { 
     @Override 
     public void onStateChanged(@NonNull View bottomSheet, 
       @BottomSheetBehavior.State int newState) { 
      if (newState == BottomSheetBehavior.STATE_HIDDEN) { 
       dismiss(); 
       bottomSheetBehavior.setState(CustomBottomSheetBehavior.STATE_COLLAPSED); 
      } 
     } 

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

} 
+0

ありがとう:D –

+0

状態を設定しているときにbottomSheetBehaviorへの参照がないので、このコードをコピー&ペーストできませんでした。 –

1

私はサンプルデモがあります。

public class BottomListMenu extends BottomSheetDialog { 
    private List<MenuDTO> menuList; 
    private OnMenuItemTapped menuTapListener; 

    public BottomListMenu(@NonNull Context context, List<MenuDTO> menuList, OnMenuItemTapped menuTapListener) { 
     super(context); 
     this.menuList = menuList; 
     this.menuTapListener = menuTapListener; 
    } 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.dialog_menu_list); 
     RecyclerView rcvList = (RecyclerView) findViewById(R.id.rcv_menu_list); 
     rcvList.setLayoutManager(new LinearLayoutManager(getContext())); 
     BottomSheetMenuListAdapter adapter = new BottomSheetMenuListAdapter(getContext(), this, menuList, menuTapListener); 
     rcvList.setAdapter(adapter); 
    } 
} 

--- ---使用

BottomListMenu menu = new BottomListMenu(MainActivity.this, MenuUtils.getListMenu(MainActivity.this), new OnMenuItemTapped() { 
    @Override 
    public void onClickMenuItem(MenuDTO menu) { 
     if (menu.getMenuTitle().equals(getString(R.string.menu_edit))) { 
      Toast.makeText(MainActivity.this, "Edit Clicked", Toast.LENGTH_SHORT).show(); 
     } else if (menu.getMenuTitle().equals(getString(R.string.menu_delete))) { 
      Toast.makeText(MainActivity.this, "Delete Clicked", Toast.LENGTH_SHORT).show(); 
     } else if (menu.getMenuTitle().equals(getString(R.string.menu_attach))) { 
      Toast.makeText(MainActivity.this, "Attach Clicked", Toast.LENGTH_SHORT).show(); 
     } 
    } 
}); 
menu.show(); 

- ここで利用可能な完全なサンプルコード -

https://github.com/bita147/BottomSheetDialog

+0

はありがとうが、どのように、これは私の質問に答えていますか? –

7

更新:問題ここ

@Override 
    public void onStateChanged(@NonNull View bottomSheet, 
           @BottomSheetBehavior.State int newState) { 

     if (newState == CustomBottomSheetBehavior.STATE_HIDDEN) { 

      dismiss(); 
      bottomSheetBehavior.setState(CustomBottomSheetBehavior.STATE_COLLAPSED); 
     } 
    } 

は、最終的なコードですサポートライブラリの一部のバージョンで解決されました。私は実際にそれを修正する正確なバージョンを知らないが、27.0.2では修正されている。

注: URLは、GoogleのURLスキーマの一部の変更により、記載されている問題を参照しなくなりました。ただ

// Fix BottomSheetDialog not showing after getting hidden when the user drags it down 
    myBottomSheetDialog.setOnShowListener(new DialogInterface.OnShowListener() { 
     @Override 
     public void onShow(DialogInterface dialogInterface) { 
      BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface; 
      FrameLayout bottomSheet = (FrameLayout) bottomSheetDialog 
        .findViewById(android.support.design.R.id.design_bottom_sheet); 
      BottomSheetBehavior.from(bottomSheet).setState(BottomSheetBehavior.STATE_COLLAPSED); 
     } 
    }); 

単一の行を追加するためにクラス全体をコピーするよりも

回避策をより良い参照してください。https://code.google.com/p/android/issues/detail?id=202396#c7

+0

onShowで状態をexpandedに設定しても問題が解決しない場合は、bottomSheetcallbackに入り、状態が設定されているときに非表示にする必要があります。 –

+1

@DavidSeroussi私はそれを自分でテストし、それはうまく動作します。 – Kh5

関連する問題