Как создать BottomBar в виде StickyBottomCaptureLayout в Camera2 Android API?

Контекст:

в android-7.1.1_r12 API, android.hardware.camera2 использует StickyBottomCaptureLayout как "BottomBar"для отображения кнопок действий (таких как кнопки переключения камеры, затвора и недавних изображений). Независимо от ориентации устройства, это StickyBottomCaptureLayout всегда отображается над / рядом с системной панелью (на которой есть кнопки "Назад", "Домой" и "Другие").

Например, это то, что выглядит, когда степень вращения 0 или же 180:

Камера API с липким нижним слоем захвата и нижней нижней панели

И, ориентируя устройство и получить степень вращения как 90 или же 270, StickyBottomCaptureLayout сейчас возле системной панели:

Камера api с наклейкой внизу и снизу справа

Как правило, этот скриншот должен иметь полоску слева и камеру справа...

Пытается:

  1. Сначала я попытался установить другой макет с layout-land, но не повезло! Я не могу изменить стандартную ориентацию слева направо и привязать нижнюю панель к системной панели Android на 270 градусов.

  2. Я не могу расширить эти виджеты, но я попытался воспроизвести случай. Например, я получил два макета:

    <FrameLayout>
        <ViewGroup .../> // containing the upper views
    
        <StickyBottomBar .../> // same behavior as StickyBottomCaptureLayout
    </FrameLayout>
    

    При каждом изменении ориентации я получаю устройство вращения и устанавливаю правильную гравитацию для верхнего макета и липкой панели, что-то вроде следующего:

    if (rotation == 0) {
        // views gravity = TOP
        // sticky gravity = BOTTOM
    } else if (rotation == 90) {
        // views gravity = LEFT
        // sticky gravity = RIGHT
    } else if (rotation == 180) { 
        // views gravity = BOTTOM
        // sticky gravity = TOP
    } else if (rotation == 270) { 
        // views gravity = RIGHT
        // sticky gravity = LEFT
    }
    

Тем не менее, это не работает вообще. Я не знаю, как эти виджеты заставляют это работать должным образом.

Вопрос:

У кого-нибудь есть решение воспроизвести случай нижней панели при изменении ориентации устройства (всегда выше или около системной панели Android)? Помня, что мой минимальный SDK ниже 21 так что у меня нет доступа к android.hardware.camera2 апи.

1 ответ

Решение

Я только что нашел решение: мне нужно установить RectFдля каждого макета и установите их с правильными координатами. Из исходного класса мне удается сделать это:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    // rotation from context Surface.ROTATION
    int degrees = getDeviceRotation(getContext());
    // size of the sticky bottom bar
    int offsetSize = (int) getResources().getDimension(R.dimen.sticky_bar_default_size);

    // layout sticky bottom bar
    RectF bottomBarRect = getStickyBarRect(degrees, offsetSize);
    mBottomBar.layout((int) bottomBarRect.left, (int) bottomBarRect.top,
            (int) bottomBarRect.right, (int) bottomBarRect.bottom);

    // layout upper view
    RectF upperViewRect = getUpperViewRect(degrees, offsetSize);
    mUpperView.layout(...); // same logic as above

    invalidate();
}

// Gets the coordinates positions to set the Sticky Bottom Bar
private RectF getStickyBarRect(int degrees, int offsetSize) {
    float left = 0, top = 0, right = 0, bottom = 0;
    int width = getWidth();
    int height = getHeight();

    if (degrees == 0) { // stickybar at bottom
        top = height - offsetSize;
        right = width;
        bottom = height;
    } else if (degrees == 90) { // stickybar at right
        left = width - offsetSize;
        right = width;
        bottom = height;
    } else if (degrees == 180) { // stickybar at top
        right = width;
        bottom = height - offsetSize;
    } else if (degrees == 270) { // stickybar at left
        right = offsetSize;
        bottom = height;
    }

    return new RectF(left, top, right, bottom);
}

// Gets the coordinates positions to set the upper views
private RectF getUpperViewRect(int degrees, int offsetSize) {
    // same logic as getStickyBarRect()
}

И это работает как ожидалось!


Я нашел способ воспроизвести плавную ориентацию, как родная camera2 приложение с этим ответом. Использование слушателя ориентации и configChanges Я могу реорганизовать виды без анимации вращения по умолчанию. Я установил правильные позиции в onLayout() и позвонить invalidate(),;)

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