Скользящая раскладка под строкой состояния в Umano SlidingPanel

Я реализовал UmanoSlidingPanel, используя https://github.com/umano/AndroidSlidingUpPanel. Все работает нормально, за исключением того, что моя раздвижная панель, когда она развернута, скользящий контент (slide_view) идет ниже строки состояния. Как я могу избежать этого? Я пытался удалить

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

из styles.xml, но это делает строку состояния непрозрачной и для основного контента. Есть ли способ это исправить?

<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>

РЕДАКТИРОВАТЬ

  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 ответа

Решение

Нашел другое решение проблемы, внеся изменения в метод onMeasure в SlidingUpPanelLayout.java . Размещение кода для будущих читателей. Нужно добавить 4 строки кода.

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;
}

1) Посмотрите на следующий Gist, который я создал.

Файл sliding_up_activity.xml может быть макет активности, который будет включать в себя вид скользящей панели. Это там, где вы должны установить android:fitsSystemWindows="true" так что любые дети правильно вставлены, чтобы не отставать от панели действий или навигационной панели.

Файл sliding_view.xml может быть ваш скользящий вид.

Вам не нужно делать что-либо еще в любом из обратных вызовов панели.

Вы можете безопасно удалить полупрозрачный стиль и код внутри onPanelSlide(), Это должно привести к тому, что скользящая панель будет правильно вставлена ​​так, что она никогда не будет выходить за строки состояния или навигации.

Кроме того, если у вас нет той же архитектуры, вы можете забыть о sliding_up_activity.xml и установить android:fitsSystemWindows="true" в CoordinatorLayout вместо этого в sliding_view.xml,

2) Второе, о чем мы говорили, - это сделать полупрозрачной строку состояния, позволяя скользящей панели упасть позади строки состояния, а затем плавно добавить отступы для правильной вставки содержимого. Для этого установите android:fitsSystemWindows="false" или удалите его из любого возможного родителя, который имеет ваша выдвижная панель. Затем в onPanelSlide Вы могли бы сделать что-то вроде этого

    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);
    }

где:

  • mSlidePanelBasePadding будет начальным дополнением вашей скользящей панели
  • mStatusBarInset будет высота строки состояния.

Это должно постепенно добавлять отступы к вашей скользящей панели, когда она проходит точку привязки.

Вы можете получить высоту строки состояния следующим образом:

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

Надеюсь, это немного поможет.

Пытаться android:fitsSystemWindows="true" в родительском макете. Это должно исправить вашу проблему.

Другое решение, которое я реализовал в прошлом, заключается в том, что в действии, содержащем slideUpPanel, вы можете оформить его с помощью полупрозрачной строки состояния (API >= 19):

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

А потом в onPanelSlide с помощью функции обратного вызова вы можете постепенно изменять отступы вашего элемента slideUpPanel до тех пор, пока панель не будет полностью поднята. В этот момент количество добавляемого дополнительного отступа должно быть размерами строки состояния.

Другие вопросы по тегам