如何在 camera2 Android api 中创建一个 BottomBar 作为 StickyBottomCaptureLayout?

How to create a BottomBar as StickyBottomCaptureLayout in camera2 Android api?

上下文:

android-7.1.1_r12 api 中,android.hardware.camera2 使用 StickyBottomCaptureLayout as a "BottomBar" 来显示操作按钮(如切换相机、快门和最近的图片按钮)。无论设备方向如何,此 StickyBottomCaptureLayout 始终显示 above/near 系统栏(具有返回、主页和其他应用程序按钮)。

例如旋转度数为0180时的样子:

并且,通过定位设备并获得 90270 的旋转角度,StickyBottomCaptureLayout 现在靠近系统栏:

通常情况下,上面的截图应该左边是粘性条,右边是摄像头...

尝试次数:

  1. 我首先尝试使用 layout-land 设置不同的布局,但没有成功!我无法更改默认的从左到右的方向,并使底部栏以 270 度固定在 Android 系统栏上。

  2. 我无法扩展 these widgets,但我尝试重现该案例。比如我有两个布局:

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

我刚刚找到解决方案:我需要为每个布局设置一个 RectF 并使用正确的坐标 设置它们。 From the source class,我做到了:

@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()
}

这按预期工作!


我找到了一种方法,可以像使用 this answer 的本机 camera2 应用一样重现平滑的方向。使用方向侦听器和 configChanges 选项,我可以在没有默认旋转动画的情况下重新组织视图。我在 onLayout() 中设置适当的位置并调用 invalidate()。 ;)