Feat: Complete 14 sliders integration, remove pen button and implement custom 3-second long press (10_FIX_SLIDER.md)
This commit is contained in:
@@ -0,0 +1,221 @@
|
|||||||
|
Dưới đây là kế hoạch hoàn thiện toàn bộ danh sách các thanh kéo (Sliders) trong bảng Floating Card mờ cho tệp cấu hình JSON đầy đủ của bạn. Chúng ta sẽ đưa tất cả 14 thông số chia theo đúng 4 nhóm cấu trúc của tệp cấu hình vào trong giao diện cuộn dọc của `ScrollView`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📐 1. Cấu Trúc Đầy Đủ Cho Layout XML (`activity_main.xml`)
|
||||||
|
|
||||||
|
Thay thế phần nội dung bên trong `LinearLayout` của bảng Floating Card (nằm dưới tiêu đề) để bổ sung đầy đủ tất cả các thanh kéo, phân chia theo từng nhóm trực quan giúp người dùng dễ thao tác.
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- Đặt bên trong LinearLayout của bảng Floating Card mờ (Lớp 3 của cameraContainer) -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 1: CƠ BẢN (BASIC ADJUSTMENTS) ================= -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="ĐIỀU CHỈNH CƠ BẢN"
|
||||||
|
android:textColor="#FF9800"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Brightness -->
|
||||||
|
<TextView android:id="@+id/tvLabelBrightness" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Brightness (Độ sáng): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderBrightness" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Contrast -->
|
||||||
|
<TextView android:id="@+id/tvLabelContrast" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Contrast (Tương phản): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderContrast" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Saturation -->
|
||||||
|
<TextView android:id="@+id/tvLabelSaturation" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Saturation (Bão hòa màu): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderSaturation" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Vibrance -->
|
||||||
|
<TextView android:id="@+id/tvLabelVibrance" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Vibrance (Bão hòa thông minh): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderVibrance" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Temperature -->
|
||||||
|
<TextView android:id="@+id/tvLabelTemperature" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Temperature (Nhiệt màu): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderTemperature" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Tint -->
|
||||||
|
<TextView android:id="@+id/tvLabelTint" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Tint (Sắc độ hồng/xanh): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderTint" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 2: NÂNG CAO (ADVANCED EFFECTS) ================= -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="HIỆU ỨNG NÂNG CAO"
|
||||||
|
android:textColor="#FF9800"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Clarity -->
|
||||||
|
<TextView android:id="@+id/tvLabelClarity" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Clarity (Độ rõ nét vùng trung tính): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderClarity" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Dehaze -->
|
||||||
|
<TextView android:id="@+id/tvLabelDehaze" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Dehaze (Độ trong suốt / Sương mù): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderDehaze" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Vignette Amount -->
|
||||||
|
<TextView android:id="@+id/tvLabelVignetteAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Vignette Amount (Bo tối góc): 0.00"/>
|
||||||
|
<!-- Hiệu ứng bo tối góc đi từ 0.0 (Không bo) đến 1.0 (Bo đen tối đa) -->
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderVignetteAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 3: GIẢ LẬP ĐƯỜNG CONG MÀU (TONE CURVE EMULATION) ================= -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="GIẢ LẬP TONE CURVE & MÀU VÙNG TỐI"
|
||||||
|
android:textColor="#FF9800"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Faded Black Level -->
|
||||||
|
<TextView android:id="@+id/tvLabelFadedBlack" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Faded Black Level (Độ mờ vùng đen): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderFadedBlack" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Shadows Tint R -->
|
||||||
|
<TextView android:id="@+id/tvLabelShadowsTintR" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint R (Sắc Đỏ vùng tối): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintR" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Shadows Tint G -->
|
||||||
|
<TextView android:id="@+id/tvLabelShadowsTintG" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint G (Sắc Lục vùng tối): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintG" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Shadows Tint B -->
|
||||||
|
<TextView android:id="@+id/tvLabelShadowsTintB" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint B (Sắc Lam vùng tối): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintB" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 4: HẠT NHIỄU PHIM (FILM GRAIN) ================= -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="HẠT NHIỄU PHIM"
|
||||||
|
android:textColor="#FF9800"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Grain Amount -->
|
||||||
|
<TextView android:id="@+id/tvLabelGrainAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Grain Amount (Mật độ hạt): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderGrainAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
<!-- Grain Size -->
|
||||||
|
<TextView android:id="@+id/tvLabelGrainSize" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Grain Size (Kích thước hạt): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderGrainSize" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💻 2. Logic Khởi Tạo & Đồng Bộ Giá Trị (Kotlin trong `MainActivity.kt`)
|
||||||
|
|
||||||
|
Khi người dùng mở bảng chỉnh sửa cho preset, hàm `openAdvancedSliders` sẽ thực hiện gán các giá trị ban đầu từ tệp JSON lên các thanh Slider phần cứng đồng thời thiết lập lắng nghe cử chỉ:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun openAdvancedSliders(selectedPreset: ColorPreset) {
|
||||||
|
editingPreset = selectedPreset.deepCopy() // Nhân bản dữ liệu để tránh ghi đè bản gốc
|
||||||
|
|
||||||
|
binding.tvEditPresetName.text = "Chỉnh sửa: ${editingPreset!!.name}"
|
||||||
|
|
||||||
|
// 1. Nạp dữ liệu Nhóm Basic
|
||||||
|
binding.sliderBrightness.value = editingPreset!!.basic.brightness
|
||||||
|
binding.sliderContrast.value = editingPreset!!.basic.contrast
|
||||||
|
binding.sliderSaturation.value = editingPreset!!.basic.saturation
|
||||||
|
binding.sliderVibrance.value = editingPreset!!.basic.vibrance
|
||||||
|
binding.sliderTemperature.value = editingPreset!!.basic.temperature
|
||||||
|
binding.sliderTint.value = editingPreset!!.basic.tint
|
||||||
|
|
||||||
|
// 2. Nạp dữ liệu Nhóm Advanced
|
||||||
|
binding.sliderClarity.value = editingPreset!!.advanced.clarity
|
||||||
|
binding.sliderDehaze.value = editingPreset!!.advanced.dehaze
|
||||||
|
binding.sliderVignetteAmount.value = editingPreset!!.advanced.vignetteAmount
|
||||||
|
|
||||||
|
// 3. Nạp dữ liệu Nhóm Tone Curve Emulation
|
||||||
|
binding.sliderFadedBlack.value = editingPreset!!.toneCurve.fadedBlackLevel
|
||||||
|
binding.sliderShadowsTintR.value = editingPreset!!.toneCurve.shadowsTintR
|
||||||
|
binding.sliderShadowsTintG.value = editingPreset!!.toneCurve.shadowsTintG
|
||||||
|
binding.sliderShadowsTintB.value = editingPreset!!.toneCurve.shadowsTintB
|
||||||
|
|
||||||
|
// 4. Nạp dữ liệu Nhóm Film Grain
|
||||||
|
binding.sliderGrainAmount.value = editingPreset!!.grain.grainAmount
|
||||||
|
binding.sliderGrainSize.value = editingPreset!!.grain.grainSize
|
||||||
|
|
||||||
|
// Gọi hàm thiết lập sự kiện lắng nghe chuyển động cho toàn bộ Sliders
|
||||||
|
setupSliderListeners()
|
||||||
|
|
||||||
|
// Hiển thị Card mờ floating lọt lòng màn hình camera như ảnh image_2be399.jpg
|
||||||
|
binding.cardAdvancedSliders.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 3. Cơ Chế Cập Nhật Giá Trị Thời Gian Thực (Real-time Pipeline)
|
||||||
|
|
||||||
|
Viết một hàm tập trung gán sự kiện thay đổi (`addOnChangeListener`) cho tất cả các thanh kéo. Khi con trỏ dịch chuyển, chữ số nhãn text sẽ đổi ngay lập tức và đẩy cấu trúc Object mới sang GPU xử lý trực tiếp trên kính ngắm.
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
private fun setupSliderListeners() {
|
||||||
|
|
||||||
|
// Ví dụ gán cho Brightness
|
||||||
|
binding.sliderBrightness.addOnChangeListener { _, value, _ ->
|
||||||
|
binding.tvLabelBrightness.text = String.format("Brightness (Độ sáng): %.2f", value)
|
||||||
|
editingPreset?.basic?.brightness = value
|
||||||
|
applyLiveFilterToCamera(editingPreset) // Đẩy ma trận màu sang GPU render
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ví dụ gán cho Vibrance
|
||||||
|
binding.sliderVibrance.addOnChangeListener { _, value, _ ->
|
||||||
|
binding.tvLabelVibrance.text = String.format("Vibrance (Bão hòa thông minh): %.2f", value)
|
||||||
|
editingPreset?.basic?.vibrance = value
|
||||||
|
applyLiveFilterToCamera(editingPreset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ví dụ gán cho Clarity (Nhóm Advanced)
|
||||||
|
binding.sliderClarity.addOnChangeListener { _, value, _ ->
|
||||||
|
binding.tvLabelClarity.text = String.format("Clarity (Độ rõ nét vùng trung tính): %.2f", value)
|
||||||
|
editingPreset?.advanced?.clarity = value
|
||||||
|
applyLiveFilterToCamera(editingPreset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ví dụ gán cho Faded Black Level (Nhóm Tone Curve)
|
||||||
|
binding.sliderFadedBlack.addOnChangeListener { _, value, _ ->
|
||||||
|
binding.tvLabelFadedBlack.text = String.format("Faded Black Level (Độ mờ vùng đen): %.2f", value)
|
||||||
|
editingPreset?.toneCurve?.fadedBlackLevel = value
|
||||||
|
applyLiveFilterToCamera(editingPreset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ví dụ gán cho Grain Amount (Nhóm Film Grain)
|
||||||
|
binding.sliderGrainAmount.addOnChangeListener { _, value, _ ->
|
||||||
|
binding.tvLabelGrainAmount.text = String.format("Grain Amount (Mật độ hạt): %.2f", value)
|
||||||
|
editingPreset?.grain?.grainAmount = value
|
||||||
|
applyLiveFilterToCamera(editingPreset)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thực hiện viết gán tương tự cho toàn bộ các thanh Sliders còn lại trong danh sách...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Bảng cấu trúc 14 thông số này sẽ tạo ra khả năng tùy biến bộ lọc ảnh mạnh mẽ không thua kém gì các bộ công cụ chỉnh ảnh phim chuyên nghiệp như VSCO hay Lightroom Mobile.
|
||||||
@@ -136,19 +136,30 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val contrast = extractJsonDoubleField(content, "contrast").toFloat()
|
val contrast = extractJsonDoubleField(content, "contrast").toFloat()
|
||||||
val saturation = extractJsonDoubleField(content, "saturation").toFloat()
|
val saturation = extractJsonDoubleField(content, "saturation").toFloat()
|
||||||
val vibrance = extractJsonDoubleField(content, "vibrance").toFloat()
|
val vibrance = extractJsonDoubleField(content, "vibrance").toFloat()
|
||||||
|
val temperature = extractJsonDoubleField(content, "temperature").toFloat()
|
||||||
|
val tint = extractJsonDoubleField(content, "tint").toFloat()
|
||||||
|
|
||||||
val clarity = extractJsonDoubleField(content, "clarity").toFloat()
|
val clarity = extractJsonDoubleField(content, "clarity").toFloat()
|
||||||
val dehaze = extractJsonDoubleField(content, "dehaze").toFloat()
|
val dehaze = extractJsonDoubleField(content, "dehaze").toFloat()
|
||||||
|
val vignetteAmount = extractJsonDoubleField(content, "vignette_amount").toFloat()
|
||||||
|
|
||||||
|
val fadedBlackLevel = extractJsonDoubleField(content, "faded_black_level").toFloat()
|
||||||
|
val shadowsTintR = extractJsonDoubleField(content, "shadows_tint_r").toFloat()
|
||||||
|
val shadowsTintG = extractJsonDoubleField(content, "shadows_tint_g").toFloat()
|
||||||
|
val shadowsTintB = extractJsonDoubleField(content, "shadows_tint_b").toFloat()
|
||||||
|
|
||||||
|
val grainAmount = extractJsonDoubleField(content, "grain_amount").toFloat()
|
||||||
|
val grainSize = extractJsonDoubleField(content, "grain_size").toFloat()
|
||||||
|
|
||||||
val preset = ColorPreset(
|
val preset = ColorPreset(
|
||||||
id = id,
|
id = id,
|
||||||
name = name,
|
name = name,
|
||||||
themeCategory = category,
|
themeCategory = category,
|
||||||
isEditable = true,
|
isEditable = true,
|
||||||
basic = BasicAdjustments(brightness, contrast, saturation, vibrance, 0f, 0f),
|
basic = BasicAdjustments(brightness, contrast, saturation, vibrance, temperature, tint),
|
||||||
advanced = AdvancedEffects(clarity, dehaze, 0f),
|
advanced = AdvancedEffects(clarity, dehaze, vignetteAmount),
|
||||||
toneCurve = ToneCurveEmulation(0f, 0f, 0f, 0f),
|
toneCurve = ToneCurveEmulation(fadedBlackLevel, shadowsTintR, shadowsTintG, shadowsTintB),
|
||||||
grain = FilmGrain(0f, 0f)
|
grain = FilmGrain(grainAmount, grainSize)
|
||||||
)
|
)
|
||||||
customList.add(preset)
|
customList.add(preset)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -213,11 +224,22 @@ class MainActivity : AppCompatActivity() {
|
|||||||
"instax_bw_cool" -> android.graphics.Color.argb(80, 128, 128, 128)
|
"instax_bw_cool" -> android.graphics.Color.argb(80, 128, 128, 128)
|
||||||
"instax_cool_summer" -> android.graphics.Color.argb(45, 0, 188, 212)
|
"instax_cool_summer" -> android.graphics.Color.argb(45, 0, 188, 212)
|
||||||
else -> {
|
else -> {
|
||||||
// Map user configured RGB overlay incorporating Vibrance, Clarity, and Dehaze
|
// Sophisticated ARGB mapping to simulate film filters using adjustment parameters
|
||||||
val alpha = ((preset.basic.vibrance + 1.0f) * 45 + 15).toInt().coerceIn(10, 110)
|
// Vibrance and Saturation increase opacity of the filter color
|
||||||
val r = ((preset.advanced.clarity + 1.0f) * 115 + 20).toInt().coerceIn(0, 255)
|
val alpha = (((preset.basic.vibrance + preset.basic.saturation) / 2f + 1.0f) * 40 + 20).toInt().coerceIn(10, 120)
|
||||||
val g = ((preset.basic.contrast + 1.0f) * 100 + 20).toInt().coerceIn(0, 255)
|
|
||||||
val b = ((preset.advanced.dehaze + 1.0f) * 95 + 15).toInt().coerceIn(0, 255)
|
// Temperature (+ is warm/red-yellow), Brightness, Clarity, and ShadowsTintR affect red
|
||||||
|
val tempWarmth = if (preset.basic.temperature > 0) preset.basic.temperature * 50f else 0f
|
||||||
|
val r = (((preset.advanced.clarity + preset.basic.brightness) / 2f + 1.0f) * 100 + 30 + tempWarmth + (preset.toneCurve.shadowsTintR * 30)).toInt().coerceIn(0, 255)
|
||||||
|
|
||||||
|
// Contrast, Tint (- is green), and ShadowsTintG affect green
|
||||||
|
val tintGreen = if (preset.basic.tint < 0) -preset.basic.tint * 50f else 0f
|
||||||
|
val g = ((preset.basic.contrast + 1.0f) * 90 + 20 + tintGreen + (preset.toneCurve.shadowsTintG * 30)).toInt().coerceIn(0, 255)
|
||||||
|
|
||||||
|
// Dehaze, cool Temperature (- is blue), and ShadowsTintB affect blue
|
||||||
|
val tempCoolness = if (preset.basic.temperature < 0) -preset.basic.temperature * 60f else 0f
|
||||||
|
val b = (((preset.advanced.dehaze + 1.0f) * 80) + 20 + tempCoolness + (preset.toneCurve.shadowsTintB * 30)).toInt().coerceIn(0, 255)
|
||||||
|
|
||||||
android.graphics.Color.argb(alpha, r, g, b)
|
android.graphics.Color.argb(alpha, r, g, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,6 +330,27 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Advanced Sliders listeners
|
// Advanced Sliders listeners
|
||||||
|
binding.sliderBrightness.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.basic.brightness = value
|
||||||
|
binding.tvLabelBrightness.text = "Brightness (Độ sáng): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderContrast.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.basic.contrast = value
|
||||||
|
binding.tvLabelContrast.text = "Contrast (Tương phản): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderSaturation.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.basic.saturation = value
|
||||||
|
binding.tvLabelSaturation.text = "Saturation (Bão hòa màu): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
binding.sliderVibrance.addOnChangeListener { _, value, _ ->
|
binding.sliderVibrance.addOnChangeListener { _, value, _ ->
|
||||||
editingPreset?.let { preset ->
|
editingPreset?.let { preset ->
|
||||||
preset.basic.vibrance = value
|
preset.basic.vibrance = value
|
||||||
@@ -315,6 +358,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
applyPresetFilter(preset)
|
applyPresetFilter(preset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.sliderTemperature.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.basic.temperature = value
|
||||||
|
binding.tvLabelTemperature.text = "Temperature (Nhiệt màu): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderTint.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.basic.tint = value
|
||||||
|
binding.tvLabelTint.text = "Tint (Sắc độ hồng/xanh): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
binding.sliderClarity.addOnChangeListener { _, value, _ ->
|
binding.sliderClarity.addOnChangeListener { _, value, _ ->
|
||||||
editingPreset?.let { preset ->
|
editingPreset?.let { preset ->
|
||||||
preset.advanced.clarity = value
|
preset.advanced.clarity = value
|
||||||
@@ -329,6 +386,55 @@ class MainActivity : AppCompatActivity() {
|
|||||||
applyPresetFilter(preset)
|
applyPresetFilter(preset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.sliderVignetteAmount.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.advanced.vignetteAmount = value
|
||||||
|
binding.tvLabelVignetteAmount.text = "Vignette Amount (Bo tối góc): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderFadedBlack.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.toneCurve.fadedBlackLevel = value
|
||||||
|
binding.tvLabelFadedBlack.text = "Faded Black Level (Độ mờ vùng đen): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderShadowsTintR.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.toneCurve.shadowsTintR = value
|
||||||
|
binding.tvLabelShadowsTintR.text = "Shadows Tint R (Sắc Đỏ vùng tối): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderShadowsTintG.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.toneCurve.shadowsTintG = value
|
||||||
|
binding.tvLabelShadowsTintG.text = "Shadows Tint G (Sắc Lục vùng tối): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderShadowsTintB.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.toneCurve.shadowsTintB = value
|
||||||
|
binding.tvLabelShadowsTintB.text = "Shadows Tint B (Sắc Lam vùng tối): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderGrainAmount.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.grain.grainAmount = value
|
||||||
|
binding.tvLabelGrainAmount.text = "Grain Amount (Mật độ hạt): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.sliderGrainSize.addOnChangeListener { _, value, _ ->
|
||||||
|
editingPreset?.let { preset ->
|
||||||
|
preset.grain.grainSize = value
|
||||||
|
binding.tvLabelGrainSize.text = "Grain Size (Kích thước hạt): ${String.format("%.2f", value)}"
|
||||||
|
applyPresetFilter(preset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.btnCancelEdit.setOnClickListener {
|
binding.btnCancelEdit.setOnClickListener {
|
||||||
closeAdvancedSliders()
|
closeAdvancedSliders()
|
||||||
@@ -433,14 +539,38 @@ class MainActivity : AppCompatActivity() {
|
|||||||
binding.tvEditPresetName.text = "Chỉnh sửa: ${selectedPreset.name}"
|
binding.tvEditPresetName.text = "Chỉnh sửa: ${selectedPreset.name}"
|
||||||
|
|
||||||
// Update Sliders visual values
|
// Update Sliders visual values
|
||||||
|
binding.sliderBrightness.value = editingPreset!!.basic.brightness
|
||||||
|
binding.sliderContrast.value = editingPreset!!.basic.contrast
|
||||||
|
binding.sliderSaturation.value = editingPreset!!.basic.saturation
|
||||||
binding.sliderVibrance.value = editingPreset!!.basic.vibrance
|
binding.sliderVibrance.value = editingPreset!!.basic.vibrance
|
||||||
|
binding.sliderTemperature.value = editingPreset!!.basic.temperature
|
||||||
|
binding.sliderTint.value = editingPreset!!.basic.tint
|
||||||
binding.sliderClarity.value = editingPreset!!.advanced.clarity
|
binding.sliderClarity.value = editingPreset!!.advanced.clarity
|
||||||
binding.sliderDehaze.value = editingPreset!!.advanced.dehaze
|
binding.sliderDehaze.value = editingPreset!!.advanced.dehaze
|
||||||
|
binding.sliderVignetteAmount.value = editingPreset!!.advanced.vignetteAmount
|
||||||
|
binding.sliderFadedBlack.value = editingPreset!!.toneCurve.fadedBlackLevel
|
||||||
|
binding.sliderShadowsTintR.value = editingPreset!!.toneCurve.shadowsTintR
|
||||||
|
binding.sliderShadowsTintG.value = editingPreset!!.toneCurve.shadowsTintG
|
||||||
|
binding.sliderShadowsTintB.value = editingPreset!!.toneCurve.shadowsTintB
|
||||||
|
binding.sliderGrainAmount.value = editingPreset!!.grain.grainAmount
|
||||||
|
binding.sliderGrainSize.value = editingPreset!!.grain.grainSize
|
||||||
|
|
||||||
// Update text labels
|
// Update text labels
|
||||||
|
binding.tvLabelBrightness.text = "Brightness (Độ sáng): ${String.format("%.2f", editingPreset!!.basic.brightness)}"
|
||||||
|
binding.tvLabelContrast.text = "Contrast (Tương phản): ${String.format("%.2f", editingPreset!!.basic.contrast)}"
|
||||||
|
binding.tvLabelSaturation.text = "Saturation (Bão hòa màu): ${String.format("%.2f", editingPreset!!.basic.saturation)}"
|
||||||
binding.tvLabelVibrance.text = "Vibrance (Bão hòa thông minh): ${String.format("%.2f", editingPreset!!.basic.vibrance)}"
|
binding.tvLabelVibrance.text = "Vibrance (Bão hòa thông minh): ${String.format("%.2f", editingPreset!!.basic.vibrance)}"
|
||||||
|
binding.tvLabelTemperature.text = "Temperature (Nhiệt màu): ${String.format("%.2f", editingPreset!!.basic.temperature)}"
|
||||||
|
binding.tvLabelTint.text = "Tint (Sắc độ hồng/xanh): ${String.format("%.2f", editingPreset!!.basic.tint)}"
|
||||||
binding.tvLabelClarity.text = "Clarity (Độ rõ nét vùng trung tính): ${String.format("%.2f", editingPreset!!.advanced.clarity)}"
|
binding.tvLabelClarity.text = "Clarity (Độ rõ nét vùng trung tính): ${String.format("%.2f", editingPreset!!.advanced.clarity)}"
|
||||||
binding.tvLabelDehaze.text = "Dehaze (Độ trong suốt / Sương mù): ${String.format("%.2f", editingPreset!!.advanced.dehaze)}"
|
binding.tvLabelDehaze.text = "Dehaze (Độ trong suốt / Sương mù): ${String.format("%.2f", editingPreset!!.advanced.dehaze)}"
|
||||||
|
binding.tvLabelVignetteAmount.text = "Vignette Amount (Bo tối góc): ${String.format("%.2f", editingPreset!!.advanced.vignetteAmount)}"
|
||||||
|
binding.tvLabelFadedBlack.text = "Faded Black Level (Độ mờ vùng đen): ${String.format("%.2f", editingPreset!!.toneCurve.fadedBlackLevel)}"
|
||||||
|
binding.tvLabelShadowsTintR.text = "Shadows Tint R (Sắc Đỏ vùng tối): ${String.format("%.2f", editingPreset!!.toneCurve.shadowsTintR)}"
|
||||||
|
binding.tvLabelShadowsTintG.text = "Shadows Tint G (Sắc Lục vùng tối): ${String.format("%.2f", editingPreset!!.toneCurve.shadowsTintG)}"
|
||||||
|
binding.tvLabelShadowsTintB.text = "Shadows Tint B (Sắc Lam vùng tối): ${String.format("%.2f", editingPreset!!.toneCurve.shadowsTintB)}"
|
||||||
|
binding.tvLabelGrainAmount.text = "Grain Amount (Mật độ hạt): ${String.format("%.2f", editingPreset!!.grain.grainAmount)}"
|
||||||
|
binding.tvLabelGrainSize.text = "Grain Size (Kích thước hạt): ${String.format("%.2f", editingPreset!!.grain.grainSize)}"
|
||||||
|
|
||||||
// Scale animation from center
|
// Scale animation from center
|
||||||
binding.cardAdvancedSliders.apply {
|
binding.cardAdvancedSliders.apply {
|
||||||
@@ -503,13 +633,32 @@ class MainActivity : AppCompatActivity() {
|
|||||||
name = newName,
|
name = newName,
|
||||||
themeCategory = "Custom",
|
themeCategory = "Custom",
|
||||||
isEditable = true,
|
isEditable = true,
|
||||||
basic = BasicAdjustments(tempPreset.basic.brightness, tempPreset.basic.contrast, tempPreset.basic.saturation, tempPreset.basic.vibrance, 0f, 0f),
|
basic = BasicAdjustments(
|
||||||
advanced = AdvancedEffects(tempPreset.advanced.clarity, tempPreset.advanced.dehaze, 0f),
|
tempPreset.basic.brightness,
|
||||||
toneCurve = ToneCurveEmulation(0f, 0f, 0f, 0f),
|
tempPreset.basic.contrast,
|
||||||
grain = FilmGrain(0f, 0f)
|
tempPreset.basic.saturation,
|
||||||
|
tempPreset.basic.vibrance,
|
||||||
|
tempPreset.basic.temperature,
|
||||||
|
tempPreset.basic.tint
|
||||||
|
),
|
||||||
|
advanced = AdvancedEffects(
|
||||||
|
tempPreset.advanced.clarity,
|
||||||
|
tempPreset.advanced.dehaze,
|
||||||
|
tempPreset.advanced.vignetteAmount
|
||||||
|
),
|
||||||
|
toneCurve = ToneCurveEmulation(
|
||||||
|
tempPreset.toneCurve.fadedBlackLevel,
|
||||||
|
tempPreset.toneCurve.shadowsTintR,
|
||||||
|
tempPreset.toneCurve.shadowsTintG,
|
||||||
|
tempPreset.toneCurve.shadowsTintB
|
||||||
|
),
|
||||||
|
grain = FilmGrain(
|
||||||
|
tempPreset.grain.grainAmount,
|
||||||
|
tempPreset.grain.grainSize
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Serialize to JSON format manually
|
// Serialize to JSON format manually (incorporating all 14 parameters)
|
||||||
val jsonString = """
|
val jsonString = """
|
||||||
{
|
{
|
||||||
"id": "$customId",
|
"id": "$customId",
|
||||||
@@ -521,23 +670,23 @@ class MainActivity : AppCompatActivity() {
|
|||||||
"contrast": ${customPreset.basic.contrast},
|
"contrast": ${customPreset.basic.contrast},
|
||||||
"saturation": ${customPreset.basic.saturation},
|
"saturation": ${customPreset.basic.saturation},
|
||||||
"vibrance": ${customPreset.basic.vibrance},
|
"vibrance": ${customPreset.basic.vibrance},
|
||||||
"temperature": 0.0,
|
"temperature": ${customPreset.basic.temperature},
|
||||||
"tint": 0.0
|
"tint": ${customPreset.basic.tint}
|
||||||
},
|
},
|
||||||
"advanced_effects": {
|
"advanced_effects": {
|
||||||
"clarity": ${customPreset.advanced.clarity},
|
"clarity": ${customPreset.advanced.clarity},
|
||||||
"dehaze": ${customPreset.advanced.dehaze},
|
"dehaze": ${customPreset.advanced.dehaze},
|
||||||
"vignette_amount": 0.0
|
"vignette_amount": ${customPreset.advanced.vignetteAmount}
|
||||||
},
|
},
|
||||||
"tone_curve_emulation": {
|
"tone_curve_emulation": {
|
||||||
"faded_black_level": 0.0,
|
"faded_black_level": ${customPreset.toneCurve.fadedBlackLevel},
|
||||||
"shadows_tint_r": 0.0,
|
"shadows_tint_r": ${customPreset.toneCurve.shadowsTintR},
|
||||||
"shadows_tint_g": 0.0,
|
"shadows_tint_g": ${customPreset.toneCurve.shadowsTintG},
|
||||||
"shadows_tint_b": 0.0
|
"shadows_tint_b": ${customPreset.toneCurve.shadowsTintB}
|
||||||
},
|
},
|
||||||
"film_grain": {
|
"film_grain": {
|
||||||
"grain_amount": 0.0,
|
"grain_amount": ${customPreset.grain.grainAmount},
|
||||||
"grain_size": 0.0
|
"grain_size": ${customPreset.grain.grainSize}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|||||||
@@ -18,13 +18,11 @@ class PresetAdapter(
|
|||||||
) : RecyclerView.Adapter<PresetAdapter.ViewHolder>() {
|
) : RecyclerView.Adapter<PresetAdapter.ViewHolder>() {
|
||||||
|
|
||||||
private var selectedPosition = 0
|
private var selectedPosition = 0
|
||||||
private var editingPosition = -1
|
|
||||||
|
|
||||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||||
val cardPreset: MaterialCardView = view.findViewById(R.id.cardPreset)
|
val cardPreset: MaterialCardView = view.findViewById(R.id.cardPreset)
|
||||||
val viewPresetColor: View = view.findViewById(R.id.viewPresetColor)
|
val viewPresetColor: View = view.findViewById(R.id.viewPresetColor)
|
||||||
val txtPresetName: TextView = view.findViewById(R.id.txtPresetName)
|
val txtPresetName: TextView = view.findViewById(R.id.txtPresetName)
|
||||||
val btnSmallEdit: ImageButton = view.findViewById(R.id.btnSmallEdit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
@@ -55,13 +53,6 @@ class PresetAdapter(
|
|||||||
holder.viewPresetColor.background = circleDrawable
|
holder.viewPresetColor.background = circleDrawable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show edit button on long press
|
|
||||||
if (position == editingPosition && preset.isEditable) {
|
|
||||||
holder.btnSmallEdit.visibility = View.VISIBLE
|
|
||||||
} else {
|
|
||||||
holder.btnSmallEdit.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Highlight selection
|
// Highlight selection
|
||||||
val strokeWidthPx = (3 * holder.itemView.context.resources.displayMetrics.density).toInt()
|
val strokeWidthPx = (3 * holder.itemView.context.resources.displayMetrics.density).toInt()
|
||||||
if (position == selectedPosition) {
|
if (position == selectedPosition) {
|
||||||
@@ -72,30 +63,53 @@ class PresetAdapter(
|
|||||||
holder.cardPreset.strokeWidth = 0
|
holder.cardPreset.strokeWidth = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.itemView.setOnClickListener {
|
// Setup custom 3-second long press detector with touch slop cancellation
|
||||||
val previousSelected = selectedPosition
|
val handler = android.os.Handler(android.os.Looper.getMainLooper())
|
||||||
selectedPosition = position
|
var isLongPressTriggered = false
|
||||||
notifyItemChanged(previousSelected)
|
var startX = 0f
|
||||||
notifyItemChanged(selectedPosition)
|
var startY = 0f
|
||||||
onPresetSelected(preset)
|
val touchSlop = 15f // pixels
|
||||||
|
|
||||||
|
val longPressRunnable = Runnable {
|
||||||
|
if (preset.isEditable) {
|
||||||
|
isLongPressTriggered = true
|
||||||
|
holder.itemView.performHapticFeedback(android.view.HapticFeedbackConstants.LONG_PRESS)
|
||||||
|
onEditClicked(preset)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.itemView.setOnLongClickListener {
|
holder.itemView.setOnTouchListener { view, event ->
|
||||||
if (preset.isEditable) {
|
when (event.action) {
|
||||||
val prevEditing = editingPosition
|
android.view.MotionEvent.ACTION_DOWN -> {
|
||||||
editingPosition = if (editingPosition == position) -1 else position
|
isLongPressTriggered = false
|
||||||
notifyItemChanged(prevEditing)
|
startX = event.x
|
||||||
if (editingPosition != -1) {
|
startY = event.y
|
||||||
notifyItemChanged(editingPosition)
|
handler.postDelayed(longPressRunnable, 3000)
|
||||||
|
}
|
||||||
|
android.view.MotionEvent.ACTION_MOVE -> {
|
||||||
|
if (Math.abs(event.x - startX) > touchSlop || Math.abs(event.y - startY) > touchSlop) {
|
||||||
|
handler.removeCallbacks(longPressRunnable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
android.view.MotionEvent.ACTION_UP -> {
|
||||||
|
handler.removeCallbacks(longPressRunnable)
|
||||||
|
if (!isLongPressTriggered) {
|
||||||
|
val previousSelected = selectedPosition
|
||||||
|
selectedPosition = holder.adapterPosition
|
||||||
|
if (selectedPosition != RecyclerView.NO_POSITION) {
|
||||||
|
notifyItemChanged(previousSelected)
|
||||||
|
notifyItemChanged(selectedPosition)
|
||||||
|
onPresetSelected(preset)
|
||||||
|
view.performClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
android.view.MotionEvent.ACTION_CANCEL -> {
|
||||||
|
handler.removeCallbacks(longPressRunnable)
|
||||||
}
|
}
|
||||||
holder.itemView.performHapticFeedback(android.view.HapticFeedbackConstants.LONG_PRESS)
|
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.btnSmallEdit.setOnClickListener {
|
|
||||||
onEditClicked(preset)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = presets.size
|
override fun getItemCount(): Int = presets.size
|
||||||
@@ -108,7 +122,6 @@ class PresetAdapter(
|
|||||||
fun resetSelection() {
|
fun resetSelection() {
|
||||||
val previousSelected = selectedPosition
|
val previousSelected = selectedPosition
|
||||||
selectedPosition = 0
|
selectedPosition = 0
|
||||||
editingPosition = -1
|
|
||||||
notifyItemChanged(previousSelected)
|
notifyItemChanged(previousSelected)
|
||||||
notifyItemChanged(selectedPosition)
|
notifyItemChanged(selectedPosition)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,65 +151,112 @@
|
|||||||
android:contentDescription="Cancel Edit" />
|
android:contentDescription="Cancel Edit" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<!-- ================= DANH SÁCH CÁC CỤM SLIDERS ĐỂ CUỘN ================= -->
|
<!-- ================= NHÓM 1: CƠ BẢN (BASIC ADJUSTMENTS) ================= -->
|
||||||
<!-- 1. VIBRANCE -->
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvLabelVibrance"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Vibrance (Bão hòa thông minh): 0.0"
|
android:text="ĐIỀU CHỈNH CƠ BẢN"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FF9800"
|
||||||
android:textSize="12sp" />
|
android:textStyle="bold"
|
||||||
<com.google.android.material.slider.Slider
|
android:textSize="11sp"
|
||||||
android:id="@+id/sliderVibrance"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_marginBottom="4dp"/>
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:valueFrom="-1.0"
|
|
||||||
android:valueTo="1.0"
|
|
||||||
android:value="0.0"
|
|
||||||
app:thumbColor="#FF9800"
|
|
||||||
app:trackColorActive="#FF9800"
|
|
||||||
app:trackColorInactive="#333333" />
|
|
||||||
|
|
||||||
<!-- 2. CLARITY -->
|
<!-- Brightness -->
|
||||||
<TextView
|
<TextView android:id="@+id/tvLabelBrightness" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Brightness (Độ sáng): 0.00"/>
|
||||||
android:id="@+id/tvLabelClarity"
|
<com.google.android.material.slider.Slider android:id="@+id/sliderBrightness" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Clarity (Độ rõ nét vùng trung tính): 0.0"
|
|
||||||
android:textColor="#FFFFFF"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:layout_marginTop="8dp" />
|
|
||||||
<com.google.android.material.slider.Slider
|
|
||||||
android:id="@+id/sliderClarity"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:valueFrom="-1.0"
|
|
||||||
android:valueTo="1.0"
|
|
||||||
android:value="0.0"
|
|
||||||
app:thumbColor="#FF9800"
|
|
||||||
app:trackColorActive="#FF9800"
|
|
||||||
app:trackColorInactive="#333333" />
|
|
||||||
|
|
||||||
<!-- 3. DEHAZE -->
|
<!-- Contrast -->
|
||||||
|
<TextView android:id="@+id/tvLabelContrast" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Contrast (Tương phản): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderContrast" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Saturation -->
|
||||||
|
<TextView android:id="@+id/tvLabelSaturation" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Saturation (Bão hòa màu): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderSaturation" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Vibrance -->
|
||||||
|
<TextView android:id="@+id/tvLabelVibrance" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Vibrance (Bão hòa thông minh): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderVibrance" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Temperature -->
|
||||||
|
<TextView android:id="@+id/tvLabelTemperature" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Temperature (Nhiệt màu): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderTemperature" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Tint -->
|
||||||
|
<TextView android:id="@+id/tvLabelTint" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Tint (Sắc độ hồng/xanh): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderTint" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 2: NÂNG CAO (ADVANCED EFFECTS) ================= -->
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvLabelDehaze"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Dehaze (Độ trong suốt / Sương mù): 0.0"
|
android:text="HIỆU ỨNG NÂNG CAO"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FF9800"
|
||||||
android:textSize="12sp"
|
android:textStyle="bold"
|
||||||
android:layout_marginTop="8dp" />
|
android:textSize="11sp"
|
||||||
<com.google.android.material.slider.Slider
|
android:layout_marginTop="12dp"
|
||||||
android:id="@+id/sliderDehaze"
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Clarity -->
|
||||||
|
<TextView android:id="@+id/tvLabelClarity" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Clarity (Độ rõ nét vùng trung tính): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderClarity" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Dehaze -->
|
||||||
|
<TextView android:id="@+id/tvLabelDehaze" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Dehaze (Độ trong suốt / Sương mù): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderDehaze" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="-1.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Vignette Amount -->
|
||||||
|
<TextView android:id="@+id/tvLabelVignetteAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Vignette Amount (Bo tối góc): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderVignetteAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 3: GIẢ LẬP ĐƯỜNG CONG MÀU (TONE CURVE EMULATION) ================= -->
|
||||||
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:valueFrom="-1.0"
|
android:text="GIẢ LẬP TONE CURVE & MÀU VÙNG TỐI"
|
||||||
android:valueTo="1.0"
|
android:textColor="#FF9800"
|
||||||
android:value="0.0"
|
android:textStyle="bold"
|
||||||
app:thumbColor="#FF9800"
|
android:textSize="11sp"
|
||||||
app:trackColorActive="#FF9800"
|
android:layout_marginTop="12dp"
|
||||||
app:trackColorInactive="#333333" />
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Faded Black Level -->
|
||||||
|
<TextView android:id="@+id/tvLabelFadedBlack" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Faded Black Level (Độ mờ vùng đen): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderFadedBlack" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Shadows Tint R -->
|
||||||
|
<TextView android:id="@+id/tvLabelShadowsTintR" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint R (Sắc Đỏ vùng tối): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintR" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Shadows Tint G -->
|
||||||
|
<TextView android:id="@+id/tvLabelShadowsTintG" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint G (Sắc Lục vùng tối): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintG" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Shadows Tint B -->
|
||||||
|
<TextView android:id="@+id/tvLabelShadowsTintB" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Shadows Tint B (Sắc Lam vùng tối): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderShadowsTintB" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ================= NHÓM 4: HẠT NHIỄU PHIM (FILM GRAIN) ================= -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="HẠT NHIỄU PHIM"
|
||||||
|
android:textColor="#FF9800"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:layout_marginTop="12dp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<!-- Grain Amount -->
|
||||||
|
<TextView android:id="@+id/tvLabelGrainAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Grain Amount (Mật độ hạt): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderGrainAmount" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
|
<!-- Grain Size -->
|
||||||
|
<TextView android:id="@+id/tvLabelGrainSize" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#FFFFFF" android:textSize="11sp" android:text="Grain Size (Kích thước hạt): 0.00"/>
|
||||||
|
<com.google.android.material.slider.Slider android:id="@+id/sliderGrainSize" android:layout_width="match_parent" android:layout_height="wrap_content" android:valueFrom="0.0" android:valueTo="1.0" android:value="0.0" app:thumbColor="#FF9800" app:trackColorActive="#FF9800" app:trackColorInactive="#333333"/>
|
||||||
|
|
||||||
<!-- NÚT LƯU THÀNH PRESET MỚI -->
|
<!-- NÚT LƯU THÀNH PRESET MỚI -->
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -41,16 +41,4 @@
|
|||||||
android:text="Preset" />
|
android:text="Preset" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
<!-- Nút edit nhỏ ở góc trên bên phải, hiển thị đè đục lên card -->
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/btnSmallEdit"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_gravity="top|end"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:src="@drawable/ic_edit_small"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:tint="@color/theme_primary"
|
|
||||||
android:contentDescription="Edit Preset" />
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user