{"id":18893547,"url":"https://github.com/anggrayudi/materialpreference","last_synced_at":"2025-04-15T00:31:49.437Z","repository":{"id":49563897,"uuid":"139258858","full_name":"anggrayudi/MaterialPreference","owner":"anggrayudi","description":"⚙️ A library designed to replace default preferences on Android framework with something beauty.","archived":false,"fork":false,"pushed_at":"2022-12-31T17:04:04.000Z","size":4182,"stargazers_count":116,"open_issues_count":0,"forks_count":19,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-28T12:51:13.537Z","etag":null,"topics":["android","android-library","android-preference","android-settings","kotlin","material-design","material-preference"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anggrayudi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["paypal.me/hardiannicko","saweria.co/hardiannicko"]}},"created_at":"2018-06-30T15:14:16.000Z","updated_at":"2024-10-20T19:08:58.000Z","dependencies_parsed_at":"2023-01-31T19:31:04.543Z","dependency_job_id":null,"html_url":"https://github.com/anggrayudi/MaterialPreference","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anggrayudi%2FMaterialPreference","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anggrayudi%2FMaterialPreference/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anggrayudi%2FMaterialPreference/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anggrayudi%2FMaterialPreference/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anggrayudi","download_url":"https://codeload.github.com/anggrayudi/MaterialPreference/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248984336,"owners_count":21193729,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-library","android-preference","android-settings","kotlin","material-design","material-preference"],"created_at":"2024-11-08T08:14:15.071Z","updated_at":"2025-04-15T00:31:47.582Z","avatar_url":"https://github.com/anggrayudi.png","language":"Kotlin","funding_links":["paypal.me/hardiannicko","saweria.co/hardiannicko"],"categories":[],"sub_categories":[],"readme":"# Material Preference\n\n![Maven Central](https://img.shields.io/maven-central/v/com.anggrayudi/materialpreference.svg)\n[![Build Status](https://github.com/anggrayudi/MaterialPreference/workflows/Android%20CI/badge.svg)](https://github.com/anggrayudi/MaterialPreference/actions?query=workflow%3A%22Android+CI%22)\n\nA library designed for people who love simplicity. Hate the old preference style? Try this library.\n\nIt combines libraries from `androidx.preference` and `net.xpece.android.support.preference`.\nAvailable from API 17.\n\n## Screenshots\n\n![Alt text](art/1-generic.png?raw=true \"Material Preference\")\n![Alt text](art/2-generic.png?raw=true \"Material Preference\")\n![Alt text](art/3-generic.png?raw=true \"DatePreference\")\n![Alt text](art/4-generic.png?raw=true \"ListPreference\")\n\n## Note\n\nEven though Material Preference is built in Kotlin, but you can use this library in Java with a little setup in your `build.gradle`. Read section [Java compatibility support](https://github.com/anggrayudi/MaterialPreference#java-compatibility-support).\n\n## Usage\n\n### Basic\n\n```gradle\nandroid {\n    // add these lines\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n}\ndependencies {\n    implementation 'com.anggrayudi:materialpreference:X.Y.Z'\n}\n```\n\nWhere `X.Y.Z` is the library version: ![Maven Central](https://img.shields.io/maven-central/v/com.anggrayudi/materialpreference.svg)\n\nSnapshots can be found [here](https://oss.sonatype.org/#nexus-search;quick~com.anggrayudi).\nTo use SNAPSHOT version, you need to add this URL to the root Gradle:\n\n```gradle\nallprojects {\n    repositories {\n        google()\n        // add this line\n        maven { url \"https://oss.sonatype.org/content/repositories/snapshots\" }\n    }\n}\n```\n\n**Note:** Since v3.5.0, we only distribute this library through [OSS Sonatype Maven](https://oss.sonatype.org/#nexus-search;quick~com.anggrayudi).\nDistributing it on Bintray became more difficult because Bintray seem lazy to maintain their [Gradle Plugin](https://github.com/bintray/gradle-bintray-plugin/).\n\nFrom your [`preferences.xml`](https://github.com/anggrayudi/MaterialPreference/blob/master/sample/src/main/res/xml/preferences.xml):\n\n```xml\n\u003cPreferenceScreen xmlns:android=\"http://schemas.android.com/apk/res/android\"\u003e\n\n    \u003c!-- To make Preferences floating, you must wrap them inside PreferenceCategory --\u003e\n    \u003cPreferenceCategory\u003e\n        \u003cPreference\n            android:key=\"about\"\n            android:title=\"About\"\n            android:icon=\"@drawable/...\"\n            app:tintIcon=\"?colorAccent\"\n            app:legacySummary=\"false\"/\u003e\n    \u003c/PreferenceCategory\u003e\n\u003c/PreferenceScreen\u003e\n```\n\nFrom your [`SettingsFragment`](https://github.com/anggrayudi/MaterialPreference/blob/master/sample/src/main/java/com/anggrayudi/materialpreference/sample/SettingsFragment.kt):\n\n```kotlin\nclass SettingsFragment : PreferenceFragmentMaterial() {\n\n    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\n        addPreferencesFromResource(R.xml.preferences)\n    }\n\n    companion object {\n        fun newInstance(rootKey: String?) = SettingsFragment().apply {\n            arguments = Bundle().also {\n                it.putString(PreferenceFragmentMaterial.ARG_PREFERENCE_ROOT, rootKey)\n            }\n        }\n    }\n}\n```\n\nFrom your [`SettingsActivity`](https://github.com/anggrayudi/MaterialPreference/blob/master/sample/src/main/java/com/anggrayudi/materialpreference/sample/SettingsActivity.kt):\n\n```kotlin\nclass SettingsActivity : PreferenceActivityMaterial() {\n\n    private var settingsFragment: SettingsFragment? = null\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_settings)\n        \n        if (savedInstanceState == null) {\n            settingsFragment = SettingsFragment.newInstance(null)\n            supportFragmentManager.beginTransaction().add(R.id.fragment_container, settingsFragment!!, TAG).commit()\n        } else {\n            onBackStackChanged()\n        }\n    }\n\n    override fun onBuildPreferenceFragment(rootKey: String?): PreferenceFragmentMaterial {\n        return SettingsFragment.newInstance(rootKey)\n    }\n\n    override fun onBackStackChanged() {\n        settingsFragment = supportFragmentManager.findFragmentByTag(TAG) as SettingsFragment\n        title = settingsFragment!!.preferenceFragmentTitle\n    }\n}\n```\n\n### Preference Migration\n\nDuring app development, you may encounter a condition where you need to modify your current `SharedPreferences`, such as renaming a preference's key.\nMaterial Preference v3.4.0 introduces a new feature called Preference Migration.\nDefine your migration plan by implementing `PreferenceMigration` interface:\n\n```kotlin\nclass MyPreferenceMigration : PreferenceMigration {\n\n    override fun migrate(plan: MigrationPlan, currentVersion: Int) {\n        // Implement your migration plan here.\n        // Read sample code in class App.kt for more information. \n    }\n\n    override fun onMigrationCompleted(preferences: SharedPreferences) {\n    }\n    \n    companion object {\n        const val PREFERENCE_VERSION = 3\n    }\n}\n```\n\nFinally, start the migration:\n\n```kotlin\nPreferenceMigration.setupMigration(MyPreferenceMigration(), preferences, PREFERENCE_VERSION)\n```\n\n### Preference Key Constants Generator\n\nMaterial Preference has a capability to auto-generate your preference keys in a constant class. By default, this class is named `PrefKey`. With this generator, you don't need to rewrite constant field each time you modify preference key from file `res/xml/preferences.xml`. It improves accuracy in writing constant values.\n\nTo enable this feature, simply add the following configuration to your `build.gradle`:\n\n````gradle\napply plugin: 'com.android.application'\napply plugin: 'kotlin-android'\napply plugin: 'kotlin-kapt' // Add this line\n\ndependencies {\n    implementation 'com.anggrayudi:materialpreference:3.x.x'\n    kapt 'com.anggrayudi:materialpreference-compiler:1.8'\n}\n````\n\nFrom your `SettingsFragment` class:\n\n````kotlin\n@PreferenceKeysConfig // Add this annotation\nclass SettingsFragment : PreferenceFragmentMaterial() {\n\n    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {\n        addPreferencesFromResource(R.xml.preferences)\n        // You can access the constant values with auto-generated class named PrefKey\n        findPreference(PrefKey.ABOUT)?.summary = BuildConfig.VERSION_NAME\n\n        val volume = findPreferenceAs\u003cSeekBarPreference\u003e(PrefKey.NOTIFICATION_VOLUME)\n        volume?.summaryFormatter = { \"$it%\" }\n    }\n}\n````\n\n**Note:**\n* If `PrefKey` does not update constant fields, click ![Alt text](art/make-project.png?raw=true \"Make Project\") Make Project in Android Studio.\n* This generator wont work with Android Studio 3.3.0 Stable, 3.4 Beta 3, and 3.5 Canary 3 because of [this bug](https://issuetracker.google.com/issues/122883561). The fixes are available in the next version of Android Studio.\n\n### SharedPreferencesHelper\n\nSince v3.5.0, the annotation processor will generate `SharedPreferencesHelper`, so you don't need to retrieve `SharedPreferences` value like this: `SharedPreferences.get\u003cDataType\u003e(key, defaultValue)`.\nTake advantage of using it with dependency injection such as [Dagger 2](https://github.com/google/dagger) and [Koin](https://github.com/InsertKoinIO/koin).\nPersonally, I would recommend you to use Koin because of its simplicity.\n\n```kotlin\nclass MainActivity : AppCompatActivity() {\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        // ...\n        val preferencesHelper = SharedPreferencesHelper(this)\n        setTitle(preferencesHelper.accountName)\n    }\n}\n```\n\nFrom above code, `accountName` is a generated method based on your configuration on `preferences.xml`.\nIt takes `android:defaultValue` if method `accountName` can't find any value stored in the `SharedPreferences`.\nYou can customize the method name via `app:helperMethodName=\"yourMethodName\"`. Read our sample code for more information.\n\n#### Example\n\nFrom your [`SettingsFragment.java`](https://github.com/anggrayudi/MaterialPreference/blob/master/sample/src/main/java/com/anggrayudi/materialpreference/sample/java/SettingsFragment.java):\n\n````java\n@PreferenceKeysConfig\npublic class SettingsFragment extends PreferenceFragmentMaterial {\n\n    @Override\n    public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {\n        addPreferencesFromResource(R.xml.preferences);\n\n        Preference preferenceAbout = findPreference(PrefKey.ABOUT);\n        preferenceAbout.setSummary(BuildConfig.VERSION_NAME);\n\n        SeekBarDialogPreference vibration = (SeekBarDialogPreference) findPreference(PrefKey.VIBRATE_DURATION);\n\n        // summary formatter example\n        vibration.setSummaryFormatter(new Function1\u003cInteger, String\u003e() {\n            @Override\n            public String invoke(Integer duration) {\n                return duration + \"ms\";\n            }\n        });\n\n        IndicatorPreference indicatorPreference = (IndicatorPreference) findPreference(PrefKey.ACCOUNT_STATUS);\n\n        // click listener example\n        indicatorPreference.setOnPreferenceClickListener(new Function1\u003cPreference, Boolean\u003e() {\n            @Override\n            public Boolean invoke(Preference preference) {\n                new MaterialDialog(getContext())\n                    .message(null, \"Your account has been verified.\", false, 1f)\n                    .positiveButton(android.R.string.ok, null, null)\n                    .show();\n                return true;\n            }\n        });\n\n        // long click listener example\n        indicatorPreference.setOnPreferenceLongClickListener(new Function1\u003cPreference, Boolean\u003e() {\n            @Override\n            public Boolean invoke(Preference preference) {\n                Toast.makeText(getContext(), \"onLogClick: \" + preference.getTitle(), Toast.LENGTH_SHORT).show();\n                return true;\n            }\n        });\n    }\n}\n````\n\nFrom your [`SettingsActivity.java`](https://github.com/anggrayudi/MaterialPreference/blob/master/sample/src/main/java/com/anggrayudi/materialpreference/sample/java/SettingsActivity.java):\n\n````java\npublic class SettingsActivity extends PreferenceActivityMaterial {\n\n    private static final String TAG = \"Settings\";\n\n    private SettingsFragment settingsFragment;\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_settings);\n        setSupportActionBar(findViewById(R.id.toolbar));\n        getSupportActionBar().setDisplayHomeAsUpEnabled(true);\n\n        if (savedInstanceState == null) {\n            settingsFragment = SettingsFragment.newInstance(null);\n            getSupportFragmentManager().beginTransaction()\n                .add(R.id.fragment_container, settingsFragment, TAG)\n                .commit();\n        } else {\n            onBackStackChanged();\n        }\n    }\n\n    @NotNull\n    @Override\n    protected PreferenceFragmentMaterial onBuildPreferenceFragment(@Nullable String rootKey) {\n        return SettingsFragment.newInstance(rootKey);\n    }\n\n    @Override\n    public void onBackStackChanged() {\n        settingsFragment = (SettingsFragment) getSupportFragmentManager().findFragmentByTag(TAG);\n        setTitle(settingsFragment.getPreferenceFragmentTitle());\n    }\n}\n````\n\n## Preferences\n\n- `Preference`\n- `CheckBoxPreference`\n- `SwitchPreference`\n- `EditTextPreference`\n- `ListPreference`\n- `IntegerListPreference`\n- `MultiSelectListPreference`\n- `SeekBarDialogPreference`\n- `SeekBarPreference`\n- `RingtonePreference`\n- `IndicatorPreference`\n- `FolderPreference`\n- `DatePreference`\n- `TimePreference`\n- `ColorPreference`\n\n### RingtonePreference\n\n`RingtonePreference` will show only system ringtone sounds by default.\nIf you want to include sounds from the external storage your app needs to request\n`android.permission.READ_EXTERNAL_STORAGE` permission in its manifest.\nDon't forget to check this runtime permission before opening ringtone picker on API 23.\n\n## License\n\n    Copyright 2018-2022 Anggrayudi Hardiannicko A.\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanggrayudi%2Fmaterialpreference","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanggrayudi%2Fmaterialpreference","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanggrayudi%2Fmaterialpreference/lists"}