4

Wie die Titel gesagt, gibt es sowieso die Größe/Höhe/Offset des offiziellen BottomSheet anpassen (Support-Bibliothek 23.x.x), wenn es im Zustand STATE_EXPANDED ist?

Anpassen persistenter Bottom Sheet STATE_EXPANDED Höhe oder Offset

Es gibt eine Klasse BottomSheetBehavior, aber ich kann nichts über Höhe oder Offset finden.

Was ich will, ist ein ähnliches Verhalten wie Google Maps erhalten:

like you can see in this gif

+1

Kann ich weiß, warum niederstimmen ??? hast du die antwort?, brauchst du den code, an dem ich gearbeitet habe (ein großer)? oder ist es eine doppelte Frage? Raten Sie nicht – MiguelHincapieC

Antwort

3

Nach dem Einschalten Android Code Graben und die Suche habe ich es:

Sie können es Standard Modifizieren tun BottomSheetBehavior Hinzufügen eines weiteren stat mit folgenden Schritten:

  1. Erstellen Sie eine Java-Klasse und erweitern sie von CoordinatorLayout.Behavior<V>
  2. Copy-Paste-Code aus Standard BottomSheetBehavior Datei auf Ihrem neuen.
  3. Ändern der Methode clampViewPositionVertical mit dem folgenden Code:

    @Override 
    public int clampViewPositionVertical(View child, int top, int dy) { 
        return constrain(top, mMinOffset, mHideable ? mParentHeight : mMaxOffset); 
    } 
    
    int constrain(int amount, int low, int high) { 
        return amount < low ? low : (amount > high ? high : amount); 
    } 
    
  4. Hinzufügen eines neuen Zustand

    public static final int STATE_ANCHOR_POINT = X;

  5. Ändern Sie die nächsten Methoden: onLayoutChild, onStopNestedScroll, BottomSheetBehavior<V> from(V view) und setState (optional)



ich diese modifizierten Verfahren und ein link to the example project

public boolean onLayoutChild(CoordinatorLayout parent, V child, int layoutDirection) { 
    // First let the parent lay it out 
    if (mState != STATE_DRAGGING && mState != STATE_SETTLING) { 
     if (ViewCompat.getFitsSystemWindows(parent) && 
       !ViewCompat.getFitsSystemWindows(child)) { 
      ViewCompat.setFitsSystemWindows(child, true); 
     } 
     parent.onLayoutChild(child, layoutDirection); 
    } 
    // Offset the bottom sheet 
    mParentHeight = parent.getHeight(); 
    mMinOffset = Math.max(0, mParentHeight - child.getHeight()); 
    mMaxOffset = Math.max(mParentHeight - mPeekHeight, mMinOffset); 

    //if (mState == STATE_EXPANDED) { 
    // ViewCompat.offsetTopAndBottom(child, mMinOffset); 
    //} else if (mHideable && mState == STATE_HIDDEN... 
    if (mState == STATE_ANCHOR_POINT) { 
     ViewCompat.offsetTopAndBottom(child, mAnchorPoint); 
    } else 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); 
    } 
    if (mViewDragHelper == null) { 
     mViewDragHelper = ViewDragHelper.create(parent, mDragCallback); 
    } 
    mViewRef = new WeakReference<>(child); 
    mNestedScrollingChildRef = new WeakReference<>(findScrollingChild(child)); 
    return true; 
} 


public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target) { 
    if (child.getTop() == mMinOffset) { 
     setStateInternal(STATE_EXPANDED); 
     return; 
    } 
    if (target != mNestedScrollingChildRef.get() || !mNestedScrolled) { 
     return; 
    } 
    int top; 
    int targetState; 
    if (mLastNestedScrollDy > 0) { 
     //top = mMinOffset; 
     //targetState = STATE_EXPANDED; 
     int currentTop = child.getTop(); 
     if (currentTop > mAnchorPoint) { 
      top = mAnchorPoint; 
      targetState = STATE_ANCHOR_POINT; 
     } 
     else { 
      top = mMinOffset; 
      targetState = STATE_EXPANDED; 
     } 
    } else if (mHideable && shouldHide(child, getYVelocity())) { 
     top = mParentHeight; 
     targetState = STATE_HIDDEN; 
    } else if (mLastNestedScrollDy == 0) { 
     int currentTop = child.getTop(); 
     if (Math.abs(currentTop - mMinOffset) < Math.abs(currentTop - mMaxOffset)) { 
      top = mMinOffset; 
      targetState = STATE_EXPANDED; 
     } else { 
      top = mMaxOffset; 
      targetState = STATE_COLLAPSED; 
     } 
    } else { 
     //top = mMaxOffset; 
     //targetState = STATE_COLLAPSED; 
     int currentTop = child.getTop(); 
     if (currentTop > mAnchorPoint) { 
      top = mMaxOffset; 
      targetState = STATE_COLLAPSED; 
     } 
     else { 
      top = mAnchorPoint; 
      targetState = STATE_ANCHOR_POINT; 
     } 
    } 
    if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) { 
     setStateInternal(STATE_SETTLING); 
     ViewCompat.postOnAnimation(child, new SettleRunnable(child, targetState)); 
    } else { 
     setStateInternal(targetState); 
    } 
    mNestedScrolled = false; 
} 

public final void setState(@State int state) { 
    if (state == mState) { 
     return; 
    } 
    if (mViewRef == null) { 
     // The view is not laid out yet; modify mState and let onLayoutChild handle it later 
     /** 
     * New behavior (added: state == STATE_ANCHOR_POINT ||) 
     */ 
     if (state == STATE_COLLAPSED || state == STATE_EXPANDED || 
       state == STATE_ANCHOR_POINT || 
       (mHideable && state == STATE_HIDDEN)) { 
      mState = state; 
     } 
     return; 
    } 
    V child = mViewRef.get(); 
    if (child == null) { 
     return; 
    } 
    int top; 
    if (state == STATE_COLLAPSED) { 
     top = mMaxOffset; 
    } else if (state == STATE_ANCHOR_POINT) { 
     top = mAnchorPoint; 
    } else if (state == STATE_EXPANDED) { 
     top = mMinOffset; 
    } else if (mHideable && state == STATE_HIDDEN) { 
     top = mParentHeight; 
    } else { 
     throw new IllegalArgumentException("Illegal state argument: " + state); 
    } 
    setStateInternal(STATE_SETTLING); 
    if (mViewDragHelper.smoothSlideViewTo(child, child.getLeft(), top)) { 
     ViewCompat.postOnAnimation(child, new SettleRunnable(child, state)); 
    } 
} 


public static <V extends View> BottomSheetBehaviorGoogleMapsLike<V> from(V view) { 
    ViewGroup.LayoutParams params = view.getLayoutParams(); 
    if (!(params instanceof CoordinatorLayout.LayoutParams)) { 
     throw new IllegalArgumentException("The view is not a child of CoordinatorLayout"); 
    } 
    CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params) 
      .getBehavior(); 
    if (!(behavior instanceof BottomSheetBehaviorGoogleMapsLike)) { 
     throw new IllegalArgumentException(
       "The view is not associated with BottomSheetBehaviorGoogleMapsLike"); 
    } 
    return (BottomSheetBehaviorGoogleMapsLike<V>) behavior; 
} 

hinzufügen werde

Sie können sogar Rückrufe verwenden mit behavior.setBottomSheetCallback(new BottomSheetBehaviorGoogleMapsLike.BottomSheetCallback() {....

Und hier ist, wie sein Aussehen wie:
[CustomBottomSheetBehavior]

1

Nun, ich bin nicht sicher, aber ich denke, das ist Ihre Antwort:

View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet); 
    final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); 
    behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { 
     @Override 
     public void onStateChanged(@NonNull View bottomSheet, int newState) { 
      // React to state change 
      Log.e("onStateChanged", "onStateChanged:" + newState); 
      if (newState == BottomSheetBehavior.STATE_EXPANDED) { 
       //do something 
      } else { 
       //do something 
      } 
     } 

     //Here is what you want 
     @Override 
     public void onSlide(@NonNull View bottomSheet, float slideOffset) { 
      // React to dragging events 
      Log.e("onSlide", "the offset "+ slideOffset); 
     } 
    }); 
+0

Ty für die Antwort, aber das ist nicht die Antwort. Der obige Code ist nützlich, wenn Sie zuhören möchten, wenn das BottomSheet einige seiner Zustände erreicht hat, aber Sie sein Verhalten nicht ändern können. Ich habe herausgefunden, wie es geht, aber ich bin jetzt ein wenig bussy, ich werde die Antwort in einigen Stunden veröffentlichen. – MiguelHincapieC