0

The following code is from CameraXBasic project Github

The CameraFragment.kt loads fragment_camera.xml first, then loads camera_ui_container.xml.

I find it strange that CameraXBasic project doesn't merge the two layout files both fragment_camera.xml and camera_ui_container.xml into one, and CameraFragment.kt only loads the merged layout file.

CameraFragment.kt

class CameraFragment : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?): View? =
            inflater.inflate(R.layout.fragment_camera, container, false)

    private fun updateCameraUi() {

        // Remove previous UI if any
        container.findViewById<ConstraintLayout>(R.id.camera_ui_container)?.let {
            container.removeView(it)
        }

        // Inflate a new view containing all UI for controlling the camera
        val controls = View.inflate(requireContext(), R.layout.camera_ui_container, container)
        ..
   }
}

fragment_camera.xml

 <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/camera_container"
        android:background="@android:color/black"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextureView
            android:id="@+id/view_finder"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>

camera_ui_container.xml

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/camera_ui_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Camera control and gallery buttons -->
    <ImageButton
        android:id="@+id/camera_switch_button"
        android:layout_width="@dimen/round_button_medium"
        android:layout_height="@dimen/round_button_medium"
        android:layout_marginBottom="@dimen/margin_xlarge"
        android:layout_marginLeft="@dimen/margin_small"
        android:padding="@dimen/spacing_small"
        android:scaleType="fitCenter"
        android:background="@android:color/transparent"
        app:srcCompat="@drawable/ic_switch"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/switch_camera_button_alt" />

    <ImageButton
        android:id="@+id/camera_capture_button"
        android:layout_width="@dimen/round_button_large"
        android:layout_height="@dimen/round_button_large"
        android:layout_marginBottom="@dimen/shutter_button_margin"
        android:scaleType="fitCenter"
        android:background="@drawable/ic_shutter"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/capture_button_alt" />

    <ImageButton
        android:id="@+id/photo_view_button"
        android:layout_width="@dimen/round_button_medium"
        android:layout_height="@dimen/round_button_medium"
        android:layout_marginBottom="@dimen/margin_xlarge"
        android:layout_marginRight="@dimen/margin_small"
        android:padding="@dimen/spacing_large"
        android:scaleType="fitCenter"
        android:background="@drawable/ic_outer_circle"
        app:srcCompat="@drawable/ic_photo"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/gallery_button_alt" />

</androidx.constraintlayout.widget.ConstraintLayout>

Added Content

I test the merged layout (Normal and landsacpe), it works well, and I think the speed of both original and mine are almost the same.

CameraFragment.kt (New)

private fun updateCameraUi() {

        // Remove previous UI if any
       // container.findViewById<ConstraintLayout>(R.id.camera_ui_container)?.let {
        //    container.removeView(it)
        //}

        // Inflate a new view containing all UI for controlling the camera
        //val controls = View.inflate(requireContext(), R.layout.camera_ui_container, container)

        // Listener for button used to capture photo
         ...
}

fragment_camera.xml (New)

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/camera_container"
    android:background="@android:color/black"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextureView
        android:id="@+id/view_finder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Camera control and gallery buttons -->
    <ImageButton
        android:id="@+id/camera_switch_button"
        android:layout_width="@dimen/round_button_medium"
        android:layout_height="@dimen/round_button_medium"
        android:layout_marginBottom="@dimen/margin_xlarge"
        android:layout_marginLeft="@dimen/margin_small"
        android:padding="@dimen/spacing_small"
        android:scaleType="fitCenter"
        android:background="@android:color/transparent"
        app:srcCompat="@drawable/ic_switch"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/switch_camera_button_alt" />

    <ImageButton
        android:id="@+id/camera_capture_button"
        android:layout_width="@dimen/round_button_large"
        android:layout_height="@dimen/round_button_large"
        android:layout_marginBottom="@dimen/shutter_button_margin"
        android:scaleType="fitCenter"
        android:background="@drawable/ic_shutter"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/capture_button_alt" />

    <ImageButton
        android:id="@+id/photo_view_button"
        android:layout_width="@dimen/round_button_medium"
        android:layout_height="@dimen/round_button_medium"
        android:layout_marginBottom="@dimen/margin_xlarge"
        android:layout_marginRight="@dimen/margin_small"
        android:padding="@dimen/spacing_large"
        android:scaleType="fitCenter"
        android:background="@drawable/ic_outer_circle"
        app:srcCompat="@drawable/ic_photo"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/gallery_button_alt" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment_camera.xml (New land)

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/camera_container"
    android:background="@android:color/black"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextureView
        android:id="@+id/view_finder"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- Camera control and gallery buttons -->
    <ImageButton
        android:id="@id/camera_switch_button"
        android:layout_width="@dimen/round_button_medium"
        android:layout_height="@dimen/round_button_medium"
        android:layout_marginRight="@dimen/margin_xlarge"
        android:layout_marginBottom="@dimen/margin_small"
        android:padding="@dimen/spacing_small"
        android:scaleType="fitXY"
        android:background="@android:color/transparent"
        app:srcCompat="@drawable/ic_switch"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:contentDescription="@string/gallery_button_alt" />

    <ImageButton
        android:id="@id/camera_capture_button"
        android:layout_width="@dimen/round_button_large"
        android:layout_height="@dimen/round_button_large"
        android:layout_marginRight="@dimen/shutter_button_margin"
        android:background="@drawable/ic_shutter"
        android:contentDescription="@string/capture_button_alt"
        android:scaleType="fitXY"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageButton
        android:id="@id/photo_view_button"
        android:layout_width="@dimen/round_button_medium"
        android:layout_height="@dimen/round_button_medium"
        android:layout_marginRight="@dimen/margin_xlarge"
        android:layout_marginTop="@dimen/margin_small"
        android:padding="@dimen/spacing_large"
        android:scaleType="fitXY"
        android:background="@drawable/ic_outer_circle"
        app:srcCompat="@drawable/ic_photo"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:contentDescription="@string/switch_camera_button_alt" />
</androidx.constraintlayout.widget.ConstraintLayout>
HelloCW
  • 843
  • 22
  • 125
  • 310

2 Answers2

1

Their idea is to recreate UI every time the configuration changes, while the TextureView persists.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Thanks, Would you please to see my added content in the question? – HelloCW Sep 26 '19 at 02:20
  • 1. I test the merged layout (Normal and landsacpe), it works well, and I think the speed of both original and mine are almost the same. right? – HelloCW Sep 26 '19 at 02:20
  • 2. I think that TextureView will not persists even if in original code, and TextureView always recreate when I rotate phone, right? – HelloCW Sep 26 '19 at 02:24
  • 3. Is the cost huge when the system recreate TextureView ? – HelloCW Sep 26 '19 at 02:26
  • It's not about the cost, but rather about code duplication and separation of responsibilities. – Alex Cohn Sep 26 '19 at 03:32
1

Did you noticed that there are two XML camera_ui_container.xml files one for portrait and one for landscape orientation to achieve different UI on rotation. and the line

// Remove previous UI if any

container.findViewById(R.id.camera_ui_container)?.let { container.removeView(it) }

is actually doing the recreation part of Camera UI @Alex Cohn is right, on same point.

You can do it with single layout if you are only handling single orientation.

Waheed Nazir
  • 584
  • 7
  • 11