Sliding layout below status bar in Umano SlidingPa

2019-02-25 15:22发布

I have implemented UmanoSlidingPanel using https://github.com/umano/AndroidSlidingUpPanel . Everything is working fine except that my sliding panel when expanded, the sliding content (sliding_view) is going below the status bar. How can I avoid that?I tried removing

 <item name="android:windowTranslucentStatus">true</item> 

from styles.xml but that makes the status bar non-tranlucent for the main content also. Any way to fix this?

<com.sothree.slidinguppanel.SlidingUpPanelLayout xmlns:sothree="http://schemas.android.com/apk/res-auto"
    android:id="@+id/sliding_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    sothree:umanoDragView="@+id/firstPanelDragArea"
    sothree:umanoPanelHeight="@dimen/bottom_panel_height"
    sothree:umanoShadowHeight="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include
            android:id="@+id/toolbar"
            layout="@layout/toolbar" />

        <FrameLayout
            android:id="@+id/frame_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

    <!-- SLIDING LAYOUT -->
    <LinearLayout
        android:id="@+id/firstPanelDragArea"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include layout="@layout/sliding_view" />

    </LinearLayout>

styles.xml

 <style name="AppTheme" parent="@style/Theme.AppCompat">
    <item name="windowActionBar">false</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <item name="android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="android:windowTranslucentStatus">true</item>
    <item name="windowNoTitle">true</item>
</style>

EDIT

  public void onPanelSlide(View panel, float slideOffset) {
              if (slideOffset > 0.5 && !flagTransparent) {
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                flagTransparent = true;
                Log.i(TAG, "onPanelSlide, offset " + slideOffset);
            } else if (slideOffset < 0.5 && flagTransparent){
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                flagTransparent = false;
                Log.i(TAG, "onPanelSlide, offset " + slideOffset);
  }

3条回答
甜甜的少女心
2楼-- · 2019-02-25 15:33

Found another solution to the problem by making changes in onMeasure method of SlidingUpPanelLayout.java . Posting the code for future readers.Need to add 4 lines of code.

SlidingPanelLayout.java

 @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    final int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    if (widthMode != MeasureSpec.EXACTLY) {
        throw new IllegalStateException("Width must have an exact value or MATCH_PARENT");
    } else if (heightMode != MeasureSpec.EXACTLY) {
        throw new IllegalStateException("Height must have an exact value or MATCH_PARENT");
    }

    final int childCount = getChildCount();

    if (childCount != 2) {
        throw new IllegalStateException("Sliding up panel layout must have exactly 2 children!");
    }

    mMainView = getChildAt(0);
    mSlideableView = getChildAt(1);
    if (mDragView == null) {
        setDragView(mSlideableView);
    }

    // If the sliding panel is not visible, then put the whole view in the hidden state
    if (mSlideableView.getVisibility() != VISIBLE) {
        mSlideState = PanelState.HIDDEN;
    }

    int layoutHeight = heightSize - getPaddingTop() - getPaddingBottom();
    int layoutWidth = widthSize - getPaddingLeft() - getPaddingRight();

    // First pass. Measure based on child LayoutParams width/height.
    for (int i = 0; i < childCount; i++) {
        final View child = getChildAt(i);
        final LayoutParams lp = (LayoutParams) child.getLayoutParams();

        // We always measure the sliding panel in order to know it's height (needed for show panel)
        if (child.getVisibility() == GONE && i == 0) {
            continue;
        }

        int height = layoutHeight;
        int width = layoutWidth;
        if (child == mMainView) {
            if (!mOverlayContent && mSlideState != PanelState.HIDDEN) {
                height -= mPanelHeight;
            }

            width -= lp.leftMargin + lp.rightMargin;
        } else if (child == mSlideableView) {
            // The slideable view should be aware of its top margin.
            // See https://github.com/umano/AndroidSlidingUpPanel/issues/412.
 //                height -= lp.topMargin;.
 // START OF CODE CHANGES
            if (height < SCREEN_HEIGHT) {  //SCREEN_HEIGHT = 900
                height = height - MARGIN_BOTTOM; //MARGIN_BOTTOM = 8
            } else {
                height = height - getStatusBarHeight();
            }
 // END OF CODE CHANGES
        }


  public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
    result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}
查看更多
太酷不给撩
3楼-- · 2019-02-25 15:39

Try android:fitsSystemWindows="true" in the parent layout. That should fix your problem.

Another solution I have implemented in the past is, in the activity that contains the slidingUpPanel, you can style it with a translucent status bar (API >= 19):

<item name="android:windowTranslucentStatus">true</item>

And then in onPanelSlide callback, you can modify the padding of your slidingUpPanel adding progressively until the panel is fully up. In that moment the amount of added extra padding should be the status bar dimensions.

查看更多
Evening l夕情丶
4楼-- · 2019-02-25 15:46

1) Have a look at the following Gist I created.

The file sliding_up_activity.xml could be the activity layout that will include your sliding up panel view. It is in there where you should set android:fitsSystemWindows="true" so that any children is inset properly not o fall behind the action bar or nav bar.

The file sliding_view.xml could be your sliding up view.

You should not need to do anything else in any of the panel callbacks.

You can safely remove the translucent style and the code inside the onPanelSlide(). This should result with a sliding panel properly inset such that never goes behind the status or nav bars.

Alternatively, if you don't have the same architecture, you could forget about the sliding_up_activity.xml and set android:fitsSystemWindows="true" in the CoordinatorLayout instead, in sliding_view.xml.

2) The second thing we were talking, is making the status bar translucent, letting the sliding up panel fall behind the status bar and then smoothly add padding to properly inset the contents. For that, set android:fitsSystemWindows="false" or remove it from any possible parent your sliding up panel has. Then in onPanelSlide you could do something like this

    if (slideOffset >= ANCHOR_POINT) {
        // adjust the span of the offset
        float offset = (slideOffset - ANCHOR_POINT) / (1 - ANCHOR_POINT);
        // the padding top will be the base original padding plus a percentage of the status
        // bar height
        float paddingTop = mSlidePanelBasePadding + offset * mStatusBarInset;
        // apply the padding to the header container
        mContainer.setPadding(0, (int) paddingTop, 0, 0);
    }

where:

  • mSlidePanelBasePadding would be the initial padding of you sliding up panel
  • mStatusBarInset would be the status bar height.

That should add padding to your slidingUp panel progressively when it gets past the anchor point.

You can get the status bar height like this:

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

I hope this helps a bit.

查看更多
登录 后发表回答