2016-02-25 7 views
22

Chcę spróbować BottomSheetDialog wprowadzono w bibliotece pomocy technicznej systemu Android 23.2, ale wydaje się, że nie działa poprawnie. Oto co mówi doc:Jak korzystać z BottomSheetDialog?

Podczas BottomSheetBehavior oddaje uporczywy dolną część obudowy arkuszy, ta wersja oferuje także BottomSheetDialog i BottomSheetDialogFragment wypełnić arkusze modalne dolne używać sprawy. Po prostu zastąp AppCompatDialog lub AppCompatDialogFragment z ich odpowiednikami w dolnej części , aby Twoje okno dialogowe było w stylu dolnego arkusza . "

Więc zmieniłem AppCompatDialog do BottomSheetDialog:

package my.package.ui.dialog; 

import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.support.design.widget.BottomSheetDialog; 

import my.package.R; 

public class AccountActionsDialog extends BottomSheetDialog { 
    public AccountActionsDialog(Context context) { 
     super(context); 

     if (context instanceof Activity) { 
      setOwnerActivity((Activity) context); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(getLayoutInflater().inflate(R.layout.dialog_account_actions, null)); 
    } 
} 

Oto mój plik układ:

<?xml version="1.0" encoding="utf-8"?> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical"> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:background="#ff0000" 
     android:padding="16dp" 
     android:text="Delete account" 
     android:textColor="#ffffff" /> 

</LinearLayout> 

Następnie używam następujący kod w mojej działalności:

new AccountActionsDialog(this).show(); 

Mój ekran zostaje przyciemniony, ale zawartość mojego okna dialogowego nie jest widoczna. Jakieś myśli o tym, czego może brakować? Działa to dobrze, gdy używam zamiast tego AppCompatDialog.

+0

Czy istnieje szczególny powód nie używasz 'setContentView (R.layout.dialog_account_actions)'? – ianhanniballake

+0

Tak. Początkowo najpierw nadpisałem widok główny i użyłem findViewById(), aby znaleźć wszystkie subviews, których potrzebuję i ustawić dla nich odpowiednie detektory. Uprośniłem kod tego przykładu i zapomniałem zmienić tę część. Problem pozostaje bez względu na to, jak układ jest ustawiony. –

+0

To zdecydowanie jest błąd w bibliotece pomocy technicznej - zrób jeden plik na b.android.com z małym przykładowym projektem i umieść w nim link, dzięki czemu mogę go przekazać zespołowi - aby uzyskać jeszcze bardziej szalone zachowanie - ustaw twoje " LinearLayout' do wysokości ~ 250dp. – ianhanniballake

Odpowiedz

2

To jest plik układu BottomSheetDialog.

<android.support.design.widget.CoordinatorLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:soundEffectsEnabled="false"> 

<FrameLayout 
     android:id="@+id/design_bottom_sheet" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_horizontal" 
     app:layout_behavior="@string/bottom_sheet_behavior" 
     style="?attr/bottomSheetStyle"/> 

</android.support.design.widget.CoordinatorLayout> 

Państwa zdanie treść jest wewnątrz widoku design_bottom_sheet, zostanie on umieszczony pionowo przez środek CoordinatorLayout i BottomSheetBehavior będzie to przesunięcie.

mParentHeight = parent.getHeight(); 
mMinOffset = Math.max(0, mParentHeight - child.getHeight()); 
mMaxOffset = mParentHeight - mPeekHeight; 
if (mState == STATE_EXPANDED) { 
    ViewCompat.offsetTopAndBottom(child, mMinOffset); 
} else if (mHideable && mState == STATE_HIDDEN) { 
    ViewCompat.offsetTopAndBottom(child, mParentHeight); 
} else if (mState == STATE_COLLAPSED) { 
    ViewCompat.offsetTopAndBottom(child, mMaxOffset); 
} 

To odnie do Positon design_bottom_sheet na mMaxOffset, ale faktycznie początkowa getTop zdania dziecko nie 0, ale (mParentHeight - childHeight)/2 jest więc zobaczyć, czy przesunięcie ponad pożądane przesunięcie.

Znajdź widok design_bottom_sheet i ustaw jego siłę grawitacji na Gravity.TOP | Gravity.CENTER_HORIZONTAL. Jeśli jednak wysokość dziecka jest mniejsza niż mPeekHeight, pod widokiem treści będzie pusty obszar.

Jednak, jeśli peekHeight > childHeight, mMaxOffset będzie mniejszy niż mMinOffset, co spowoduje dziwne zachowanie.

Może kod powinien zostać zmieniony na

mMaxOffset = Math.max((mParentHeight - mPeekHeight), mMinOffset); 

insted

mMaxOffset = mParentHeight - child.getHeight(); 
+0

Ten problem też widzę. Framelayout, który otacza twój widok treści, jest wyśrodkowany pionowo z jakiegoś powodu. Kiedy BottomSheetBehavior następnie układa Framelayout, zaczyna się od wartości Y> 0. Cała matematyka w tym zachowaniu ma działać poprzez przesunięcie widoku z góry rodzica, co powoduje, że zawartość jest znacznie niższa niż oczekiwano (poza ekranem) –

+0

@Edward Kimmel FrameLayout sprawdzi, czy ustawiłeś grawitację na górze, na dole lub center_vertical, jeśli żadna z nich nie jest ustawiona, FrameLayout ułoży dziecko na wierzchu. Jednak 'CoordinatorLayout.layoutChild' używa' Gravity.apply' do układania swoich dzieci, w 'Gravity.apply', jeśli żadna z tych grawitacji nie jest ustawiona, to ułoży widok dziecka w centrum rodzica. Zobacz [Gravity.apply] (http://androidxref.com/6.0.1_r10/xref/frameworks/base/core/java/android/view/Gravity.java#231) –

2

byłem expriencing ten sam problem, przyciemnione tło i treść nie jest widoczna. Oto sposób, w jaki udało mi się go obejść, ustawiając widok ukryty w metodzie ukrytej w setupDialog().

public class CustomBottomSheetDialogFragment extends BottomSheetDialogFragment { 

    private TextView mOffsetText; 
    private TextView mStateText; 
    private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() { 

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

     } 

     @Override 
     public void onSlide(@NonNull View bottomSheet, float slideOffset) { 
      setOffsetText(slideOffset); 
     } 
    }; 
    private LinearLayoutManager mLinearLayoutManager; 
    private ApplicationAdapter mAdapter; 

    @Override 
    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     return super.onCreateDialog(savedInstanceState); 
    } 

    @Override 
    public void onViewCreated(View contentView, @Nullable Bundle savedInstanceState) { 
     super.onViewCreated(contentView, savedInstanceState); 
    } 

    @Override 
    public void setupDialog(Dialog dialog, int style) { 
     super.setupDialog(dialog, style); 
     View contentView = View.inflate(getContext(), R.layout.bottom_sheet_dialog_content_view, null); 
     dialog.setContentView(contentView); 
     mBottomSheetBehavior = BottomSheetBehavior.from(((View) contentView.getParent())); 
     if (mBottomSheetBehavior != null) { 
      mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetBehaviorCallback); 
     } 
     mOffsetText = (TextView) contentView.findViewById(R.id.offsetText); 
     mStateText = (TextView) contentView.findViewById(R.id.stateText); 
    } 

} 

I układ:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical"> 


    <TextView 
     android:id="@+id/offsetText" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:textColor="@android:color/black" /> 

    <TextView 
     android:id="@+id/stateText" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:textColor="@android:color/black" /> 

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 
</LinearLayout> 
+0

dla uzyskania zachowania możesz również użyć BottomSheetBehavior.from (Zobacz v) mimo, że wyrzuca wyjątki –

2

Oto problem na code.google.com https://code.google.com/p/android/issues/detail?id=201793

Problem niektórzy użytkownicy widzą sprowadza się do FrameLayout że otacza nasz pogląd zawartość jest wyśrodkowany pionowo. BottomSheetBehavior działa tylko wtedy, gdy ten widok jest wyrównany do góry. I nie zorientowali się, co powoduje, że FrameLayout aby stać skupione jeszcze pionowo, ale tutaj jest to możliwe obejście:

View contentView = ... 
// You may have to measure your content view first. 
dialog.setContentView(contentView); 

// Change this to a percentage or a constant, whatever you want to do. 
// The default is 1024 - any views smaller than this will be pulled off 
// the bottom of the screen. 
float peekHeight = contentView.getMeasuredHeight(); 

View parent = (View)contentView.getParent(); 
BottomSheetBehavior behavior = BottomSheetBehavior.from(parent); 
behavior.setPeekHeight(peekHeight); 
CoordinatorLayout.LayoutParams layoutParams = 
    (CoordinatorLayout.LayoutParams)parent.getLayoutParams(); 
layoutParams.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; 
+0

To niczego nie naprawi. – 0101100101

0

zaczęło pracować kiedy ustawić stałą wysokość dla mojego TextView (200dp), chociaż dla niektórych wartości wysokości nadal zachowuje się niepoprawnie. Oczywiście jest to kwestia wsparcia lib. Istnieje już kilka raportów związanych BottomSheetDialog w śledzenia błędów:

https://code.google.com/p/android/issues/detail?id=201793&sort=-opened&colspec=ID%20Status%20Priority%20Owner%20Summary%20Stars%20Reporter%20Opened

https://code.google.com/p/android/issues/detail?id=201826