2016-08-06 4 views
14

Ich bin ziemlich gespannt auf das Verhalten der BottomSheetDialog, wenn es entlassen wird: Wenn der Benutzer es nach unten zieht, wird es ausgeblendet, auch wenn bottomSheetDialog#show() nach aufgerufen wird. Dies geschieht nur, wenn es nach unten gezogen wird, nicht wenn der Benutzer außerhalb berührt oder wenn bottomSheetDialog#dismiss() programmatisch aufgerufen wird.BottomSheetDialog bleibt nach dem Ablehnen durch Ziehen versteckt

Es ist wirklich ärgerlich, weil ich eine ziemlich große bottomSheetDialog mit einer recyclerview innen habe, und ich muss ein neues jedes Mal erstellen, das ich die bottomSheetDialog zeigen möchte.

Anstatt also nur dies zu tun:

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

Ich habe ein jedes Mal zu erstellen.

Fehle ich etwas oder ist es das normale Verhalten? (Btw verwende ich appcompat-v7:23.2.1)

Antwort

6

So gelang es mir schließlich, dieses Problem zu lösen, indem sie direkt suchen in die BottomSheetDialog Implementierung, und ich entdeckte, dass es nichts anderes als eine einfache Dialog in einem regulärengewickelt war 210.
Das Problem war in den BottomSheetCallBack:

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

Das Problem tritt auf, wenn der Zustand HIDDEN erreicht wird, das geschieht, wenn der Dialog, indem sie nach unten gezogen wird zurückgewiesen. Danach bleibt der Dialog verborgen, auch wenn bottomSheetDialog.show() aufgerufen wird. Die einfachste Lösung, die ich gefunden habe, war, diesen Zustand zu entfernen und ihn durch den Zustand COLLAPSED zu ersetzen.

ich erstellen classCustomBottomSheetDialog, kopiert die gesamte BottomSheetDialog Klasse und hat eine einzige Zeile das Problem zu beheben:

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

     if (newState == CustomBottomSheetBehavior.STATE_HIDDEN) { 

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

Hier ist der endgültige Code:

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

Daumen hoch für diese Lösung danke: D –

+0

Ich konnte diesen Code nicht kopieren und einfügen, weil es keinen Bezug zu BottomSheetBehavior gibt, wenn Sie den Status festlegen. –

1

Ich habe Beispiel-Demo Ich hoffe, dass das nützlich ist.

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); 
    } 
} 

--- Anwendung ---

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(); 

- Full Beispielcode verfügbar Hier -

https://github.com/bita147/BottomSheetDialog

+0

Danke aber, wie diese meine Frage nicht beantworten? –

7

Update: Das Problem wurde in einigen Versionen der Support-Bibliothek behoben. Ich weiß nicht genau die genaue Version, die es behebt, aber in 27.0.2 ist es behoben.

Hinweis: Die URL bezieht sich nicht mehr auf das beschriebene Problem aufgrund einiger Änderungen am URL-Schema von Google.

Eine Abhilfe besser als die ganze Klasse Kopieren nur eine einzige Zeile

// 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); 
     } 
    }); 

siehe hinzuzufügen: https://code.google.com/p/android/issues/detail?id=202396#c7

+0

Wenn Sie den Status in onShow auf expanded setzen, wird nichts gelöst. Sie müssen sich in bottomSheetcallback begeben, um den ausgeblendeten Zustand zu entfernen, wenn er gesetzt ist. –

+1

@DavidSeroussi Ich habe es selbst getestet und es funktioniert gut. – Kh5

Verwandte Themen