animateLayoutChanges=”true” in BottomSheetView toont onverwacht gedrag

Ik heb een BottomSheetViewmet animateLayoutChanges="true". In eerste instantie komt het goed over. Maar als de visibilityvan een weergave (in BottomSheetView) wordt gewijzigd van GONEin VISIBLE, verprutst de app de berekeningen en mijn BottomSheetViewgaat naar de bovenkant van het scherm. ik heb geprobeerd layout_gravity=bottomin te stellen in de hoofdmap van de lay-out BottomSheetView. Maar geen succes.

Hier heb ik de afbeelding van mijn BottomSheetViewvoordat ik de zichtbaarheid van een weergave verander. (Klik op afbeelding voor volledige grootte)

voer hier de afbeeldingsbeschrijving in

Nadat ik de zichtbaarheid van een weergave heb gewijzigd (GONEin VISIBLEof VISIBLEin GONE), wordt mijn BottomSheetView gaat naar boven. (Klik op afbeelding voor volledige grootte)

voer hier de afbeeldingsbeschrijving in

Ik denk dat Android aan het verknoeien is bij het maken van berekeningen over de meting van de weergave widthen height. Is er een manier om dit op te lossen??

Ik heb ook geprobeerd om mijn BottomSheetView volledig uit te breiden om overeen te komen met de bovenliggende weergave, maar op de een of andere manier maakt dat de heightvan de BottomSheetViewlanger dan het telefoonscherm en in- tun het creëren van scrollproblemen.

Verwachte oplossingen:

1> Voorkom dat BottomSheetViewzijn positie verandert, zelfs wanneer de visibilityvan een weergave wordt gewijzigd.

OF

2>Zorg ervoor dat de BottomSheetViewovereenkomt met de ouder, zodat het er niet slecht uitziet na het verknoeien van de berekeningen.


Antwoord 1, autoriteit 100%

Het BottomSheetBehavior werkt voorlopig niet goed met LayoutTransition(animateLayoutChanges="true"). Ik zal aan een oplossing werken.

Voorlopig kun je in plaats daarvan Transitiongebruiken. Zoiets vervaagt het zicht binnenin en animeert het formaat van het onderste vel.

ViewGroup bottomSheet = ...;
View hidingView = ...;
TransitionManager.beginDelayedTransition(bottomSheet);
hidingView.setVisibility(View.GONE);

Je kunt Een transitie toepassenraadplegen voor meer informatie, waaronder het aanpassen de animatie.


Antwoord 2, autoriteit 38%

Ik liep tegen hetzelfde probleem aan en was vastbesloten om een ​​oplossing te vinden. Ik heb de onderliggende oorzaak kunnen vinden, maar helaas zie ik momenteel geen goede oplossing.

De oorzaak:
Het probleem doet zich voor tussen het gedrag van het onderblad en de LayoutTransition. Wanneer de LayoutTransition is gemaakt, wordt een OnLayoutChangeListener in de weergave gemaakt, zodat deze de eindwaarden kan vastleggen en een animator met de juiste waarden kan instellen. Deze OnLayoutChangeListener wordt geactiveerd in de onLayout()-aanroep van bottomSheetBehavior wanneer deze voor het eerst parent.onLayout(child)aanroept. De ouder zal het kind indelen zoals het normaal zou doen, en negeert eventuele verschuivingen die het gedrag later zou veranderen. Het probleem ligt hier. De waarden van de weergave op dit punt worden vastgelegd door de OnLayoutChangeListener en opgeslagen in de animator. Wanneer de animatie wordt uitgevoerd, wordt deze geanimeerd naar deze waarden, niet naar waar uw gedrag definieert. Helaas geeft de klasse LayoutTransition ons geen toegang tot de animators om het bijwerken van de eindwaarden mogelijk te maken.

De oplossing:
Momenteel zie ik geen elegante oplossing voor LayoutTransitions. Ik ga een bug indienen voor een manier om LayoutTransition-animators te openen en bij te werken. Voor nu kun je elke layoutTransition op de bovenliggende container uitschakelen met layoutTransition.setAnimateParentHierarchy(false). Vervolgens kunt u de wijziging zelf animeren. Ik zal mijn antwoord zo snel mogelijk bijwerken met een werkend voorbeeld.


Antwoord 3, autoriteit 25%

De vraag is meer dan twee jaar geleden gesteld, maar helaas blijft het probleem bestaan.

Ik heb eindelijk een oplossing om de aanroep van de functies addViewen removeViewin een BottomSheet te houden, terwijl ik animateLayoutChanges="true"heb .

BottomSheetBehaviorkan de juiste hoogte niet berekenen wanneer deze verandert, dus de hoogte moet hetzelfde blijven. Om dit te doen, stel ik de hoogte van de BottomSheetin op match_parenten verdeel het in twee onderliggende items: de inhoud en een Spacedie van hoogte verandert naargelang tot de hoogte van de inhoud.

Om het ware gedrag van een BottomSheetzo goed mogelijk na te bootsen, moet je ook een TouchToDismiss-weergave toevoegen die de achtergrond donkerder maakt wanneer de BottomSheetwordt verlengd, maar ook om de BottomSheetwanneer de gebruiker buiten de inhoud drukt.

Hier is de code:

activiteit.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/show_bottom_sheet"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show bottom sheet"/>
    <View
        android:id="@+id/touch_to_dismiss"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:background="#9000"/>
    <LinearLayout
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
        <Space
            android:id="@+id/space"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1"/>
        <LinearLayout
            android:id="@+id/bottom_sheet_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:animateLayoutChanges="true">
            <Button
                android:id="@+id/add_or_remove_another_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Add another view"/>
            <TextView
                android:id="@+id/another_view"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Another view"/>
        </LinearLayout>
    </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

activiteit.java

BottomSheetBehavior bottomSheetBehavior;
View touchToDismiss;
LinearLayout bottomSheet;
Button showBottomSheet;
Space space;
LinearLayout bottomSheetContent;
Button addOrRemoveAnotherView;
TextView anotherView;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    touchToDismiss = findViewById(R.id.touch_to_dismiss);
    touchToDismiss.setVisibility(View.GONE);
    touchToDismiss.setOnClickListener(this);
    bottomSheet = findViewById(R.id.bottom_sheet);
    bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet);
    bottomSheetBehavior.setPeekHeight(0);
    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
    bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
        @Override
        public void onStateChanged(@NonNull View bottomSheet, int newState) {
            if (newState == BottomSheetBehavior.STATE_HIDDEN || newState == BottomSheetBehavior.STATE_COLLAPSED) {
                touchToDismiss.setVisibility(View.GONE);
            }else {
                touchToDismiss.setVisibility(View.VISIBLE);
            }
        }
        @Override
        public void onSlide(@NonNull View bottomSheet, float slideOffset) {
            touchToDismiss.setAlpha(getRealOffset());
        }
    });
    showBottomSheet = findViewById(R.id.show_bottom_sheet);
    showBottomSheet.setOnClickListener(this);
    space = findViewById(R.id.space);
    bottomSheetContent = findViewById(R.id.bottom_sheet_content);
    addOrRemoveAnotherView = findViewById(R.id.add_or_remove_another_view);
    addOrRemoveAnotherView.setOnClickListener(this);
    anotherView = findViewById(R.id.another_view);
    bottomSheetContent.removeView(anotherView);
}
@Override
public void onClick(View v) {
    if (v == showBottomSheet)
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
    else if (v == addOrRemoveAnotherView) {
        if (anotherView.getParent() == null)
            bottomSheetContent.addView(anotherView);
        else
            bottomSheetContent.removeView(anotherView);
    }
    else if (v == touchToDismiss)
        bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
/**
 * Since the height does not change and remains at match_parent, it is required to calculate the true offset.
 * @return Real offset of the BottomSheet content.
 */
public float getRealOffset() {
    float num = (space.getHeight() + bottomSheetContent.getHeight()) - (bottomSheet.getY() + space.getHeight());
    float den = bottomSheetContent.getHeight();
    return (num / den);
}

Dit is het resultaat verkregen met deze code:
eindresultaat

Hopelijk zal iemand er iets aan hebben, aangezien het probleem er nog steeds is!


Antwoord 4, autoriteit 6%

In de standaardlay-out van BottomSheetDialog (design_bottom_sheet_dialog ) er is een TOPzwaartekracht op de design_bottom_sheetFrameLayout van het dialoogvenster:

android:layout_gravity="center_horizontal|top"

Ik weet niet echt waarom op BottomSheetDialog de zwaartekracht bovenaan is.

U moet hetzelfde lay-outbestand (dezelfde inhoud en naam) in uw project maken en deze regel vervangen door:

android:layout_gravity="center_horizontal|bottom"

Antwoord 5

In ons geval gaven we een voortgangsbalk weer op een knoponderdeel. Dit was het verbergen van de knoptekst en het weergeven van de voortgangsbalk. Dit veroorzaakte een sprong in het onderste bladfragment. Het gebruik van Invisible in plaats van Gone loste het probleem op.


Antwoord 6

Als je zicht het toelaat, maak dan de zichtbaarheid ONZICHTBAAR in plaats van GEGAAN.

Other episodes