mirror of
https://github.com/alesimula/Murine-launcher.git
synced 2026-10-28 09:43:42 +00:00
SETTINGS - test SegmentedButton
This commit is contained in:
1 parent
e5fab3d3b4
commit
50f3e2c05e
12 files changed
+497
-2
No files matched your search
@@ -0,0 +1,31 @@
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "frameworks_base_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["frameworks_base_license"],
|
||||
}
|
||||
|
||||
android_library {
|
||||
name: "SettingsLibSegmentedButtonPreference",
|
||||
use_resource_processor: true,
|
||||
defaults: [
|
||||
"SettingsLibApexDefaults",
|
||||
"SettingsLintDefaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"src/**/*.java",
|
||||
"src/**/*.kt",
|
||||
],
|
||||
resource_dirs: ["res"],
|
||||
|
||||
static_libs: [
|
||||
"SettingsLibSettingsTheme",
|
||||
"androidx.annotation_annotation",
|
||||
"androidx.preference_preference",
|
||||
],
|
||||
sdk_version: "system_current",
|
||||
min_sdk_version: "23",
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.settingslib.widget.preference.segmentedbutton">
|
||||
|
||||
<uses-sdk android:minSdkVersion="21" />
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,35 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.android.settingslib.widget.preference.segmentedbutton"
|
||||
compileSdk = 36
|
||||
|
||||
defaultConfig {
|
||||
minSdk = 26
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
getByName("main") {
|
||||
java.srcDirs("src")
|
||||
res.srcDirs("res")
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "21"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api project(':SettingsLib-SettingsTheme')
|
||||
implementation(libs.annotation)
|
||||
implementation(libs.androidx.preference)
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2024 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/settingslib_expressive_space_extrasmall4"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
|
||||
android:importantForAccessibility="no">
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:theme="@style/Theme.Material3.DynamicColors.DayNight"
|
||||
android:id="@+id/button_group"
|
||||
style="@style/Widget.Material3Expressive.MaterialButtonGroup.Connected"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:singleSelection="true"
|
||||
app:selectionRequired="true"
|
||||
app:checkedButton="@id/button_1">
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_1"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
app:iconPadding="0dp"
|
||||
app:iconGravity="textStart"
|
||||
style="@style/SettingsLibButtonStyle.Expressive.Tonal.Large"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_2"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
app:iconPadding="0dp"
|
||||
app:iconGravity="textStart"
|
||||
style="@style/SettingsLibButtonStyle.Expressive.Tonal.Large"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_3"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
app:iconPadding="0dp"
|
||||
app:iconGravity="textStart"
|
||||
style="@style/SettingsLibButtonStyle.Expressive.Tonal.Large"/>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_4"
|
||||
android:layout_weight="1"
|
||||
android:visibility="gone"
|
||||
app:iconPadding="0dp"
|
||||
app:iconGravity="textStart"
|
||||
style="@style/SettingsLibButtonStyle.Expressive.Tonal.Large"/>
|
||||
</com.google.android.material.button.MaterialButtonToggleGroup>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/button_group_text"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:paddingTop="@dimen/settingslib_expressive_space_extrasmall4">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_1_text"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.SettingsLib.TitleSmall.Emphasized"
|
||||
android:textColor="@color/settingslib_materialColorOnSurface"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_2_text"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.SettingsLib.TitleSmall.Emphasized"
|
||||
android:textColor="@color/settingslib_materialColorOnSurface"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_3_text"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.SettingsLib.TitleSmall.Emphasized"
|
||||
android:textColor="@color/settingslib_materialColorOnSurface"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_4_text"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textAppearance="@style/TextAppearance.SettingsLib.TitleSmall.Emphasized"
|
||||
android:textColor="@color/settingslib_materialColorOnSurface"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2024 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settingslib.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.view.isGone
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import com.android.settingslib.widget.preference.segmentedbutton.R
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
|
||||
class SegmentedButtonPreference @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : Preference(context, attrs, defStyleAttr, defStyleRes), GroupSectionDividerMixin {
|
||||
private var buttonGroup: MaterialButtonToggleGroup? = null
|
||||
private var buttonLabels: MutableList<TextView> = mutableListOf()
|
||||
private var buttonCheckedListener: MaterialButtonToggleGroup.OnButtonCheckedListener? = null
|
||||
|
||||
// Data to be applied during onBindViewHolder
|
||||
private val buttonSetupData =
|
||||
mutableMapOf<Int, Pair<String, SegmentedButtonIcon>>() // (index, text, icon)
|
||||
private val buttonVisibilityData = mutableMapOf<Int, Boolean>() // (index, visibility)
|
||||
private val buttonEnableData = mutableMapOf<Int, Boolean>() // (index, enable)
|
||||
|
||||
// Default checked button
|
||||
private var checkedIndex: Int = -1
|
||||
|
||||
init {
|
||||
layoutResource = R.layout.settingslib_expressive_preference_segmentedbutton
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: PreferenceViewHolder) {
|
||||
super.onBindViewHolder(holder)
|
||||
holder.isDividerAllowedBelow = false
|
||||
holder.isDividerAllowedAbove = false
|
||||
|
||||
buttonGroup = holder.findViewById(R.id.button_group) as MaterialButtonToggleGroup?
|
||||
buttonLabels.add(0, holder.findViewById(R.id.button_1_text) as TextView)
|
||||
buttonLabels.add(1, holder.findViewById(R.id.button_2_text) as TextView)
|
||||
buttonLabels.add(2, holder.findViewById(R.id.button_3_text) as TextView)
|
||||
buttonLabels.add(3, holder.findViewById(R.id.button_4_text) as TextView)
|
||||
|
||||
// Apply stored data
|
||||
applyButtonSetupData()
|
||||
applyButtonVisibilityData()
|
||||
applyButtonEnableData()
|
||||
buttonGroup?.apply {
|
||||
clearOnButtonCheckedListeners()
|
||||
applyCheckIndex(checkedIndex)
|
||||
buttonCheckedListener?.let { listener ->
|
||||
addOnButtonCheckedListener(listener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun setUpButton(index: Int, text: String, @DrawableRes icon: Int) {
|
||||
buttonSetupData.put(index, Pair(text, SegmentedButtonIcon.ResourceIcon(icon)))
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
fun setUpButton(index: Int, text: String, icon: Drawable) {
|
||||
buttonSetupData.put(index, Pair(text, SegmentedButtonIcon.DrawableIcon(icon)))
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
fun setButtonVisibility(index: Int, visible: Boolean) {
|
||||
buttonVisibilityData.put(index, visible)
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
fun setButtonEnabled(index: Int, enabled: Boolean) {
|
||||
buttonEnableData.put(index, enabled)
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
fun setCheckedIndex(index: Int) {
|
||||
checkedIndex = index
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
fun getCheckedIndex(): Int {
|
||||
val checkedButtonId = buttonGroup?.checkedButtonId ?: return -1
|
||||
return buttonGroup?.indexOfChild(buttonGroup?.findViewById(checkedButtonId)) ?: -1
|
||||
}
|
||||
|
||||
fun setOnButtonClickListener(listener: MaterialButtonToggleGroup.OnButtonCheckedListener) {
|
||||
buttonCheckedListener = listener
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
fun removeOnButtonClickListener() {
|
||||
buttonCheckedListener = null
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
private fun applyButtonSetupData() {
|
||||
// The button group is default gone to avoid NullPointerException
|
||||
// if all children's visibility are GONE.
|
||||
if(buttonSetupData.isNotEmpty()) {
|
||||
buttonGroup?.isGone = false
|
||||
}
|
||||
for ((index, config) in buttonSetupData) {
|
||||
applyButtonSetupData(index, config.first, config.second)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyButtonVisibilityData() {
|
||||
for ((index, visible) in buttonVisibilityData) {
|
||||
applyButtonVisibilityData(index, visible)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyButtonEnableData() {
|
||||
for ((index, enable) in buttonEnableData) {
|
||||
applyButtonEnableData(index, enable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyButtonSetupData(index: Int, text: String, icon: SegmentedButtonIcon) {
|
||||
when (icon) {
|
||||
is SegmentedButtonIcon.ResourceIcon ->
|
||||
(buttonGroup?.getChildAt(index) as? MaterialButton)?.setIconResource(icon.resId)
|
||||
|
||||
is SegmentedButtonIcon.DrawableIcon ->
|
||||
(buttonGroup?.getChildAt(index) as? MaterialButton)?.icon = icon.drawable
|
||||
}
|
||||
buttonLabels[index].text = text
|
||||
}
|
||||
|
||||
private fun applyButtonVisibilityData(index: Int, visible: Boolean) {
|
||||
buttonGroup?.getChildAt(index)?.isGone = !visible
|
||||
buttonLabels[index].isGone = !visible
|
||||
}
|
||||
|
||||
private fun applyButtonEnableData(index: Int, enabled: Boolean) {
|
||||
buttonGroup?.getChildAt(index)?.isEnabled = enabled
|
||||
}
|
||||
|
||||
private fun applyCheckIndex(index: Int) {
|
||||
val button = buttonGroup?.getChildAt(index) ?: run {
|
||||
buttonGroup?.clearChecked()
|
||||
return
|
||||
}
|
||||
if (button.id == View.NO_ID || button.isGone) {
|
||||
buttonGroup?.clearChecked()
|
||||
return
|
||||
}
|
||||
|
||||
buttonGroup?.check(button.id)
|
||||
}
|
||||
|
||||
private sealed interface SegmentedButtonIcon {
|
||||
data class DrawableIcon(val drawable: Drawable) : SegmentedButtonIcon
|
||||
|
||||
data class ResourceIcon(@DrawableRes val resId: Int) : SegmentedButtonIcon
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,6 @@ android {
|
||||
|
||||
dependencies {
|
||||
api(project(":flags"))
|
||||
api(libs.material)
|
||||
implementation(libs.androidx.preference)
|
||||
implementation(libs.material)
|
||||
}
|
||||
@@ -32,6 +32,5 @@ dependencies {
|
||||
api project(':SettingsLib-Preference')
|
||||
api project(':SettingsLib-SettingsTheme')
|
||||
implementation(libs.annotation)
|
||||
implementation(libs.material)
|
||||
implementation(libs.androidx.preference)
|
||||
}
|
||||
@@ -290,6 +290,7 @@ dependencies {
|
||||
implementation project(':SettingsLib-SliderPreference')
|
||||
implementation project(':SettingsLib-SelectorWithWidgetPreference')
|
||||
implementation project(':SettingsLib-ExpandablePreference')
|
||||
implementation project(':SettingsLib-SegmentedButtonPreference')
|
||||
withQuickstepCompileOnly project(':HiddenApi')
|
||||
|
||||
// Include all compat libs
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import os
|
||||
|
||||
path = r"C:\Users\Alex\StudioProjects\Murine-launcher\src\app\murinelauncher\settings\SettingsHomeFragment.kt"
|
||||
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
|
||||
old = " // Explicitly hide the remaining unused slots in the layout"
|
||||
new = """ // Make configured buttons visible (all start as gone in layout)
|
||||
setButtonVisibility(0, true)
|
||||
setButtonVisibility(1, true)
|
||||
|
||||
// Explicitly hide the remaining unused slots in the layout"""
|
||||
|
||||
if old in content:
|
||||
content = content.replace(old, new)
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
f.write(content)
|
||||
print("SUCCESS: File updated.")
|
||||
else:
|
||||
print("ERROR: Target string not found in file.")
|
||||
# Debug: print surrounding context
|
||||
idx = content.find("Explicitly")
|
||||
if idx >= 0:
|
||||
print(f"Found 'Explicitly' at index {idx}")
|
||||
print(repr(content[idx-50:idx+80]))
|
||||
else:
|
||||
print("'Explicitly' not found at all")
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2015 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<androidx.preference.PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:launcher="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.android.settingslib.widget.SegmentedButtonPreference
|
||||
android:key="pref_drawer_type"
|
||||
android:title="Screen Mode" />
|
||||
</androidx.preference.PreferenceScreen>
|
||||
@@ -74,6 +74,8 @@ include ':SettingsLib-SelectorWithWidgetPreference'
|
||||
project(':SettingsLib-SelectorWithWidgetPreference').projectDir = new File(rootDir, 'SettingsLib/SelectorWithWidgetPreference')
|
||||
include ':SettingsLib-ExpandablePreference'
|
||||
project(':SettingsLib-ExpandablePreference').projectDir = new File(rootDir, 'SettingsLib/ExpandablePreference')
|
||||
include ':SettingsLib-SegmentedButtonPreference'
|
||||
project(':SettingsLib-SegmentedButtonPreference').projectDir = new File(rootDir, 'SettingsLib/SegmentedButtonPreference')
|
||||
|
||||
include ':compatLib'
|
||||
include ':compatLib:compatLibVQ'
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package app.murinelauncher.settings
|
||||
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.util.Log
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.preference.Preference
|
||||
import com.android.launcher3.BuildConfig
|
||||
import com.android.launcher3.Flags
|
||||
import com.android.launcher3.InvariantDeviceProfile
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.states.RotationHelper
|
||||
import com.android.launcher3.util.DisplayController
|
||||
import com.android.settingslib.widget.SegmentedButtonPreference
|
||||
|
||||
public final class SettingsDrawerFragment: AbstractSettingsFragment() {
|
||||
|
||||
companion object {
|
||||
const val DRAWER_TYPE: String = "pref_drawer_type"
|
||||
}
|
||||
|
||||
override fun getPreferenceScreenResId() = R.xml.murine_prefs_drawer
|
||||
|
||||
override fun getPreferenceTitle(): Int? = R.string.pref_category_drawer_title
|
||||
|
||||
override fun initPreference(preference: Preference, info: DisplayController.Info): Boolean {
|
||||
when (preference.key) {
|
||||
DRAWER_TYPE -> {
|
||||
preference as SegmentedButtonPreference
|
||||
preference.apply {
|
||||
// Configure the visible buttons (0-indexed)
|
||||
setUpButton(0, "Option 1", R.drawable.ic_setting)
|
||||
setUpButton(1, "Option 2", R.drawable.ic_setting)
|
||||
|
||||
// Explicitly hide the remaining unused slots in the layout
|
||||
setButtonVisibility(0, true)
|
||||
setButtonVisibility(1, true)
|
||||
setButtonVisibility(2, false)
|
||||
setButtonVisibility(3, false)
|
||||
|
||||
// Set initial state (e.g., from saved settings)
|
||||
setCheckedIndex(0)
|
||||
|
||||
// Use the custom listener provided by the class
|
||||
setOnButtonClickListener { _, _, _ ->
|
||||
val selectedIndex = getCheckedIndex()
|
||||
// Handle your logic based on the 0, 1 index
|
||||
Log.d("Settings", "Selected index: $selectedIndex")
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> return true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user