4

就像标题所说的那样,是否有定制bottomSheet(支持库23.x.x)处于STATE_EXPANDED状态时的大小/高度/偏移量?

自定义持久性底部表STATE_EXPANDED高度或偏移量

有一个类BottomSheetBehavior但我找不到有关高度或偏移量的任何内容。

我想要的是得到一个类似的行为像谷歌地图:

like you can see in this gif

+1

我可以知道为什么否决???你有答案吗?需要我一直在做的代码(一个大代码)?或者它是一个重复的问题?猜测不是 – MiguelHincapieC

回答

3

挖Android的代码后并搜索我得到它:

你可以修改默认BottomSheetBehavior添加一个更多的统计与以下步骤:

  1. 创建一个Java类,并从CoordinatorLayout.Behavior<V>
  2. 复制粘贴代码从默认BottomSheetBehavior文件扩展到您的新的。
  3. 修改方法clampViewPositionVertical用下面的代码:

    @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. 添加新状态

    公共静态最终诠释STATE_ANCHOR_POINT = X;

  5. 修改下一个方法:onLayoutChildonStopNestedScrollBottomSheetBehavior<V> from(V view)setState(可选)



我要添加这些改进方法和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; 
} 



你甚至可以使用回调与behavior.setBottomSheetCallback(new BottomSheetBehaviorGoogleMapsLike.BottomSheetCallback() {....

这里是如何的模样:
[CustomBottomSheetBehavior]

1

嗯,我不知道,但我想这就是你的答案:

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是答案,但这不是答案。上面的代码在您想要监听bottomSheet达到其某些状态但您不能在其中更改其行为时会有用。我发现如何做到这一点,但现在我有点小气,我会在几个小时内发布答案。 – MiguelHincapieC