Implement 7.1_FIX_UX_BUTTON: Restructured timeline selection & bottom control panels, integrated zoom group inside bottom ControlPanel, updated Play button to Gallery Image icon and customized orange circle shutter button background

This commit is contained in:
2026-07-05 17:34:37 +07:00
parent 4a33140c67
commit 424ca4b419
5 changed files with 256 additions and 79 deletions
+156
View File
@@ -0,0 +1,156 @@
# 🛠️ KẾ HOẠCH FIX BUG: TÁI CẤU TRÚC PHÂN TẦNG TIMELINE & CONTROL PANEL
Mục tiêu: Loại bỏ dải nền xám chứa các nút zoom. Di chuyển các nút zoom tích hợp chung vào khu vực điều khiển camera phía dưới (cùng hàng với nút Shutter và nút Xem lại). Thay đổi biểu tượng nút Play thành biểu tượng Image (Thư viện).
---
## 📐 1. Phác Thảo Cấu Trúc Giao Diện Mới (Sau khi chỉnh sửa)
Giao diện từ cạnh dưới kính ngắm camera trở xuống sẽ được tối giản thành đúng 2 khối:
```
[ Kính ngắm Camera chính (Tỉ lệ 3:4) ]
--------------------------------------------------
[ Khối 1: TIMELINE CONTAINER ]
- Nút Neo cố định ở cạnh trái (Frame / Palette)
- Thanh RecyclerView trượt ngang lướt dưới nút Neo
--------------------------------------------------
[ Khối 2: BOTTOM CONTROL PANEL ] (Không nền phụ, tối giản)
- Hàng trên: Các cụm văn bản Zoom thuần (0.5x, 1x, 3x) - Text trắng/cam
- Hàng dưới: [Icon Image/Gallery] ➔ [Nút Shutter Trắng/Cam] ➔ [Khoảng trống]
```
---
## 🛠️ 2. Chi Tiết Thay Đổi Trong Tệp Cấu Hình XML (`activity_main.xml`)
Bạn hãy thay thế toàn bộ khu vực phía dưới `cameraContainer` bằng đoạn mã tối ưu bằng `ConstraintLayout` dưới đây để giải quyết triệt để lỗi đè nền hiển thị trong ảnh `image_2afaba.png`.
```xml
<!-- ================= KHỐI 1: TIMELINE FRAMES & PRESETS ================= -->
<!-- Đặt ngay phía dưới Camera và không bị ai đè lên nữa -->
<FrameLayout
android:id="@+id/panelSelectionContainer"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#000000"
app:layout_constraintTop_toBottomOf="@id/cameraContainer"
app:layout_constraintBottom_toTopOf="@id/bottomControlPanel">
<!-- Danh sách cuộn ngang -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvHorizontalTimeline"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:clipToPadding="false"
android:paddingStart="75dp"
android:paddingEnd="16dp" />
<!-- Nút chức năng chính (Góc trái làm điểm Neo đè lên RecyclerView) -->
<ImageView
android:id="@+id/btnMainAnchor"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="left|center_vertical"
android:layout_marginStart="16dp"
android:src="@drawable/ic_palette_default"
android:background="@null" />
</FrameLayout>
<!-- ================= KHỐI 2: BOTTOM CONTROL PANEL (ĐIỀU KHIỂN CAMERA) ================= -->
<!-- Khối này gom gọn cả nút Zoom, Shutter và nút Xem ảnh, xóa bỏ các dải nền thừa -->
<ConstraintLayout
android:id="@+id/bottomControlPanel"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#000000"
app:layout_constraintTop_toBottomOf="@id/panelSelectionContainer"
app:layout_constraintBottom_toBottomOf="parent">
<!-- CỤM ZOOM THUẦN (Xóa bỏ dải nền cũ trong image_2afaba.png) -->
<LinearLayout
android:id="@+id/layoutZoomGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="12dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView
android:id="@+id/tvZoom05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.5x"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:padding="8dp" />
<TextView
android:id="@+id/tvZoom1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1x"
android:textColor="#FF9800" <!-- Mc đnh màu cam cho 1x -->
android:textStyle="bold"
android:padding="8dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />
<TextView
android:id="@+id/tvZoom3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="3x"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:padding="8dp" />
</LinearLayout>
<!-- NÚT XEM ẢNH (Thay thế nút mũi tên Play cũ thành biểu tượng Image/Gallery) -->
<ImageButton
android:id="@+id/btnGalleryReview"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@null"
android:src="@drawable/ic_image_gallery" <!-- Đi sang icon bc nh hình vuông/thư vin -->
app:layout_constraintTop_toTopOf="@id/btnShutterCapture"
app:layout_constraintBottom_toBottomOf="@id/btnShutterCapture"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="32dp" />
<!-- NÚT SHUTTER CHỤP ẢNH (Giữ cố định vị trí vàng ở giữa dưới cùng) -->
<ImageButton
android:id="@+id/btnShutterCapture"
android:layout_width="72dp"
android:layout_height="72dp"
android:background="@drawable/bg_shutter_orange_circle" <!-- Vin cam rut trng -->
android:layout_marginBottom="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/layoutZoomGroup"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintLayout>
```
---
## 📅 3. Các Đầu Việc Cần Cập Nhật Trong Mã Nguồn Kotlin
Sau khi cập nhật lại cây thư mục giao diện XML, bạn cần thực hiện ánh xạ lại ID trong `MainActivity.kt`:
1. **Thay đổi sự kiện Nút Xem Ảnh:** Đổi tên ánh xạ từ nút mũi tên Play cũ sang nút mới:
```kotlin
binding.btnGalleryReview.setOnClickListener {
// Thực hiện logic mở thư viện xem lại ảnh đã chụp
}
```
2. **Kiểm tra độ cao vùng chạm:** Vì chúng ta loại bỏ phần nền chứa các nút zoom cũ, `RecyclerView` của Timeline giờ đây có toàn bộ diện tích `80dp` rõ ràng. Các item hiển thị hiển thị trọn vẹn, không sợ bị các nút zoom bấm đè đứt đoạn nữa.
@@ -286,7 +286,7 @@ class MainActivity : AppCompatActivity() {
} }
// Play Gallery Button // Play Gallery Button
binding.btnReviewGallery.setOnClickListener { binding.btnGalleryReview.setOnClickListener {
try { try {
val intent = android.content.Intent(android.content.Intent.ACTION_VIEW).apply { val intent = android.content.Intent(android.content.Intent.ACTION_VIEW).apply {
type = "image/*" type = "image/*"
@@ -299,7 +299,7 @@ class MainActivity : AppCompatActivity() {
} }
// Shutter Button // Shutter Button
binding.btnCapture.setOnClickListener { binding.btnShutterCapture.setOnClickListener {
onCaptureClick() onCaptureClick()
} }
} }
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#40FF9800">
<item>
<shape android:shape="oval">
<solid android:color="#FFFFFF" />
<stroke
android:width="4dp"
android:color="#FF9800" />
</shape>
</item>
</ripple>
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/theme_white"
android:pathData="M19,3H5C3.9,3 3,3.9 3,5v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5C21,3.9 20.1,3 19,3zm0,16H5V5h14v14zm-5.04,-6.71l-2.75,3.54 -1.96,-2.36L6.5,17h11l-3.54,-4.71z" />
</vector>
@@ -103,23 +103,24 @@
android:text="3" /> android:text="3" />
</FrameLayout> </FrameLayout>
<!-- ================= 3. KHU VỰC ĐIỀU KHIỂN DÒNG (CHỒNG LỚP CUỘN ĐÈ) ================= --> <!-- ================= KHỐI 1: TIMELINE FRAMES & PRESETS ================= -->
<!-- Đặt ngay phía dưới Camera và không bị ai đè lên nữa -->
<FrameLayout <FrameLayout
android:id="@+id/panelSelectionContainer" android:id="@+id/panelSelectionContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="70dp" android:layout_height="80dp"
android:background="#000000" android:background="#000000"
app:layout_constraintTop_toBottomOf="@id/cameraContainer" app:layout_constraintTop_toBottomOf="@id/cameraContainer"
app:layout_constraintBottom_toTopOf="@id/zoomControls"> app:layout_constraintBottom_toTopOf="@id/bottomControlPanel">
<!-- LỚP ĐÁY: Danh sách cuộn ngang dùng chung cho cả Frame và Preset --> <!-- Danh sách cuộn ngang -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvHorizontalTimeline" android:id="@+id/rvHorizontalTimeline"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal" android:orientation="horizontal"
android:clipToPadding="false" android:clipToPadding="false"
android:paddingStart="80dp" android:paddingStart="75dp"
android:paddingEnd="16dp" android:paddingEnd="16dp"
android:visibility="gone" /> android:visibility="gone" />
@@ -160,84 +161,83 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout> </FrameLayout>
<!-- ================= 4. CỤM NÚT ĐIỀU KHIỂN ZOOM (TEXTVIEW) ================= --> <!-- ================= KHỐI 2: BOTTOM CONTROL PANEL (ĐIỀU KHIỂN CAMERA) ================= -->
<!-- Khối này gom gọn cả nút Zoom, Shutter và nút Xem ảnh, xóa bỏ các dải nền thừa -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bottomControlPanel"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="#000000"
app:layout_constraintTop_toBottomOf="@id/panelSelectionContainer"
app:layout_constraintBottom_toBottomOf="parent">
<!-- CỤM ZOOM THUẦN (Xóa bỏ dải nền cũ) -->
<LinearLayout <LinearLayout
android:id="@+id/zoomControls" android:id="@+id/layoutZoomGroup"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:background="@color/theme_transparent" android:layout_marginTop="12dp"
android:padding="4dp" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@id/panelSelectionContainer" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/controlPanel" app:layout_constraintStart_toStartOf="parent">
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<TextView <TextView
android:id="@+id/tvZoom05" android:id="@+id/tvZoom05"
android:layout_width="50dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:text="0.5x"
android:textColor="@color/theme_white" android:textColor="#FFFFFF"
android:text="@string/zoom_05x"
android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
android:padding="6dp" /> android:padding="8dp" />
<TextView <TextView
android:id="@+id/tvZoom1" android:id="@+id/tvZoom1"
android:layout_width="50dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:text="1x"
android:textColor="@color/theme_primary" android:textColor="@color/theme_primary"
android:text="@string/zoom_1x"
android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
android:padding="6dp" /> android:padding="8dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp" />
<TextView <TextView
android:id="@+id/tvZoom3" android:id="@+id/tvZoom3"
android:layout_width="50dp" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:text="3x"
android:textColor="@color/theme_white" android:textColor="#FFFFFF"
android:text="@string/zoom_3x"
android:textSize="14sp"
android:textStyle="bold" android:textStyle="bold"
android:padding="6dp" /> android:padding="8dp" />
</LinearLayout> </LinearLayout>
<!-- ================= 5. CONTROL PANEL CHỤP ẢNH (PLAY + SHUTTER) ================= --> <!-- NÚT XEM ẢNH (Biểu tượng Image/Gallery) -->
<RelativeLayout
android:id="@+id/controlPanel"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/theme_panel_dark"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/zoomControls">
<!-- Nút Play (Xem lại ảnh) -->
<ImageButton <ImageButton
android:id="@+id/btnReviewGallery" android:id="@+id/btnGalleryReview"
android:layout_width="56dp" android:layout_width="48dp"
android:layout_height="56dp" android:layout_height="48dp"
android:layout_alignParentStart="true" android:background="@null"
android:layout_centerVertical="true" android:src="@drawable/ic_image_gallery"
android:layout_marginStart="24dp" app:layout_constraintTop_toTopOf="@id/btnShutterCapture"
android:background="@color/theme_transparent" app:layout_constraintBottom_toBottomOf="@id/btnShutterCapture"
android:src="@drawable/ic_play_gallery" app:layout_constraintStart_toStartOf="parent"
app:tint="@color/theme_white" android:layout_marginStart="32dp"
android:contentDescription="Review Gallery" /> android:contentDescription="Review Gallery" />
<!-- Nút Chụp (Ở giữa) --> <!-- NÚT SHUTTER CHỤP ẢNH (Viền cam ruột trắng) -->
<ImageButton <ImageButton
android:id="@+id/btnCapture" android:id="@+id/btnShutterCapture"
android:layout_width="64dp" android:layout_width="72dp"
android:layout_height="64dp" android:layout_height="72dp"
android:layout_centerInParent="true" android:background="@drawable/bg_shutter_orange_circle"
android:background="@drawable/bg_capture_button" android:layout_marginBottom="24dp"
android:src="@drawable/ic_camera_white" app:layout_constraintBottom_toBottomOf="parent"
android:contentDescription="@string/btn_capture_desc" /> app:layout_constraintTop_toBottomOf="@id/layoutZoomGroup"
</RelativeLayout> app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:contentDescription="Shutter Button" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>