{"id":15623848,"url":"https://github.com/skydoves/needs","last_synced_at":"2025-04-05T01:06:28.860Z","repository":{"id":47474443,"uuid":"173936383","full_name":"skydoves/Needs","owner":"skydoves","description":":closed_umbrella: An easy way to implement modern permission instructions popup. ","archived":false,"fork":false,"pushed_at":"2021-08-30T10:12:59.000Z","size":468,"stargazers_count":613,"open_issues_count":1,"forks_count":52,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-29T00:08:35.627Z","etag":null,"topics":["android","instructions","needs","permission","popup","popup-window","skydoves"],"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/skydoves.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":".github/CODEOWNERS","security":null,"support":null},"funding":{"github":"skydoves","custom":["https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"]}},"created_at":"2019-03-05T11:46:35.000Z","updated_at":"2024-09-26T10:46:14.000Z","dependencies_parsed_at":"2022-08-30T06:11:16.778Z","dependency_job_id":null,"html_url":"https://github.com/skydoves/Needs","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FNeeds","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FNeeds/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FNeeds/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FNeeds/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skydoves","download_url":"https://codeload.github.com/skydoves/Needs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247271528,"owners_count":20911587,"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","instructions","needs","permission","popup","popup-window","skydoves"],"created_at":"2024-10-03T09:59:06.623Z","updated_at":"2025-04-05T01:06:28.829Z","avatar_url":"https://github.com/skydoves.png","language":"Kotlin","readme":"# Needs\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![API](https://img.shields.io/badge/API-16%2B-brightgreen.svg?style=flat)](https://android-arsenal.com/api?level=16) \n[![Build Status](https://github.com/skydoves/Needs/workflows/Android%20CI/badge.svg)](https://github.com/skydoves/Needs/actions)\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Needs-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/7569)\n[![Android Weekly](https://img.shields.io/badge/Android%20Weekly-%23358-orange.svg)](https://androidweekly.net/issues/issue-358)\n[![Javadoc](https://img.shields.io/badge/Javadoc-Needs-yellow.svg)](https://skydoves.github.io/libraries/needs/javadoc/needs/com.skydoves.needs/index.html)\u003cbr\u003e\nAn easy way to implement modern permission instructions popup. \u003cbr\u003e\nNeeds can be fully customized and showing with animations. \u003cbr\u003e\n\n![img0](https://user-images.githubusercontent.com/24237865/54251761-9ab78580-458b-11e9-9db0-7bd6684ce0f2.png)\n![img1](https://user-images.githubusercontent.com/24237865/54251764-9ab78580-458b-11e9-86eb-794861fb9f75.png)\n\n## Download\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/needs.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22needs%22)\n[![JitPack](https://jitpack.io/v/skydoves/Needs.svg)](https://jitpack.io/#skydoves/Needs)\n\n### Gradle\nAdd below codes to your **root** `build.gradle` file (not your module build.gradle file).\n```gradle\nallprojects {\n    repositories {\n        mavenCentral()\n    }\n}\n```\nAnd add a dependency code to your **module**'s `build.gradle` file.\n```gradle\ndependencies {\n    implementation \"com.github.skydoves:needs:1.1.2\"\n}\n```\n\n## Usage\n\n### Basic example\nThis is a basic example on a screenshot. Here is how to create `Needs` using `Needs.Builder`.\n```java\nNeeds needs = new Needs.Builder(context)\n      .setTitle(\"Permission instructions for using this Android app.\")\n      .addNeedsItem(new NeedsItem(null, \"· SD Card\", \"(Required)\", \"Access photos, media, and files on device.\"))\n      .addNeedsItem(new NeedsItem(null, \"· Location\", \"(Required)\", \"Access this device's location.\"))\n      .addNeedsItem(new NeedsItem(null, \"· Camera\", \"(Optional)\", \"Take pictures and record video.\"))\n      .addNeedsItem(new NeedsItem(null, \"· Contact\", \"(Optional)\", \"Access this device's contacts.\"))\n      .addNeedsItem(new NeedsItem(null, \"· SMS\", \"(Optional)\", \"Send and view SMS messages.\"))\n      .setDescription(\"The above accesses are used to better serve you.\")\n      .setConfirm(\"Confirm\")\n      .setBackgroundAlpha(0.6f)\n      .setLifecycleOwner(lifecycleOwner)\n      .build();\n```\n### Create using kotlin dsl\nThis is how to create `Needs`'s instance using kotlin dsl.\n```kotlin\nval needs = createNeeds(baseContext) {\n      titleIcon = iconDrawable\n      title = \"Permission instructions \\nfor using this Android app.\"\n      titleTextForm = titleForm\n      addNeedsItem(NeedsItem(drawable_sd, \"SD Card\", \"(Required)\", \"Access photos, media, and files on device.\"))\n      addNeedsItem(NeedsItem(drawable_location, \"Location\", \"(Required)\", \"Access this device's location.\"))\n      addNeedsItem(NeedsItem(drawable_camera, \"Camera\", \"(Optional)\", \"Take pictures and record video.\"))\n      addNeedsItem(NeedsItem(drawable_contact, \"Contact\", \"(Optional)\", \"Access this device's contacts.\"))\n      addNeedsItem(NeedsItem(drawable_sms, \"SMS\", \"(Optional)\", \"Send and view SMS messages.\"))\n      description = \"The above accesses are used to better serve you.\"\n      confirm = \"Confirm\"\n      backgroundAlpha = 0.6f\n      lifecycleOwner = lifecycle\n      needsTheme = theme\n      needsItemTheme = itemTheme\n      needsAnimation = NeedsAnimation.CIRCULAR\n    }\n```\n\n### OnConfirmListener\nWe can listen to the confirm button is clicked using `OnConfirmListener`.\n```java\nneeds.setOnConfirmListener(new OnConfirmListener() {\n  @Override\n  public void onConfirm() {\n      // confirmed\n  }\n});\n```\n\n### Show and dismiss\nHere is how to show needs popup and dismiss easily.\n```java\nneeds.show(layout); // shows the popup menu to the center. \nneeds.dismiss(); // dismiss the popup menu.\n```\n\n### TextForm\nTextFrom is an attribute class that has some attributes about TextView for customizing popup texts.\n\n```java\nTextForm textForm = new TextForm.Builder()\n          .setTextColor(R.color.colorPrimary)\n          .setTextSize(14)\n          .setTextStyle(Typeface.BOLD)\n          .build();\n\nbuilder.setTitleTextForm(titleTextForm);\nbuilder.setDescriptionTextForm(descriptionTextForm);\nbuilder.setConfirmTextForm(confirmTextForm);\n```\n\nHere is how to create `TextForm` using kotlin dsl.\n```kotlin\nval titleForm = textForm {\n  textSize = 18\n  textStyle = Typeface.BOLD\n  textColor = ContextCompat.getColor(baseContext, R.color.black)\n}\n```\n\n### NeedsTheme\nNeedsTheme is an attribute class for changing `Needs` popup theme easily.\n\n```java\nNeedsTheme needsTheme = new NeedsTheme.Builder(context)\n           .setBackgroundColor(ContextCompat.getColor(context, R.color.background))\n           .setTitleTextForm(titleTextForm)\n           .setDescriptionTextForm(descriptionTextForm)\n           .setConfirmTextForm(confirmTextForm)\n           .build();\n\nbuilder.setNeedsTheme(needsTheme);           \n```\n\nHere is how to create `NeedsTheme` using kotlin dsl.\n```kotlin\nval theme = needsTheme(baseContext) {\n      backgroundColor = ContextCompat.getColor(baseContext, R.color.background)\n      titleTextForm = textForm(baseContext) {\n        textSize = 18\n        textColor = ContextCompat.getColor(baseContext, R.color.white)\n      }\n      descriptionTextForm = textForm(baseContext) {\n        textSize = 12\n        textColor = ContextCompat.getColor(baseContext, R.color.description)\n      }\n    }\n```\n\n### NeedsItemTheme\n`NeedsTheme` is an attribute class for changing `Needs` popup RecyclerView's item theme easily.\n\n```java\nNeedsItemTheme needsItemTheme = new NeedsItemTheme.Builder(context)\n               .setBackgroundColor(ContextCompat.getColor(context, R.color.background))\n               .setTitleTextForm(titleTextForm)\n               .setRequireTextForm(requireTextForm)\n               .setBulletForm(bulletForm)\n               .build();\n\nbuilder.setNeedsItemTheme(needsItemTheme);\n```\n\nHere is how to create `NeedsItemTheme` using kotlin dsl.\n```kotlin\nval itemTheme = needsItemTheme(baseContext) {\n      backgroundColor = ContextCompat.getColor(baseContext, R.color.background)\n      titleTextForm = textForm(baseContext) {\n        textColor = ContextCompat.getColor(baseContext, R.color.colorPrimaryDark)\n        textSize = 16\n      }\n      descriptionTextForm = textForm(baseContext) {\n        textColor = ContextCompat.getColor(baseContext, R.color.description)\n      }\n    }\n```\n\n\u003cimg src=\"https://user-images.githubusercontent.com/24237865/83263157-1cc7b480-a1f9-11ea-8208-f3843b51bb62.png\" align=\"right\" width=\"32%\"/\u003e\n\n### BulletForm\nWe can make bullet points in front of every title and they can be fully customized.\n```java\nBulletForm bulletForm = new BulletForm.Builder(context)\n                    .setBulletColorResource(R.color.colorPrimary)\n                    .setBulletSize(12)\n                    .setBulletPadding(9)\n                    .build();\n```\nHere is how to create `BulletForm` using kotlin dsl.\n```kotlin\nval bulletForm = bulletForm(context) {\n      setBulletColorResource(R.color.colorPrimary)\n      setBulletSize(12)\n}\n```\n\n### NeedsAnimation\nNeedsAnimation implements showing and dismissing popup with animations.\n\nELASTIC | CIRCULAR\n------------ | -------------\n![elastic](https://user-images.githubusercontent.com/24237865/54488606-ffa21100-48e6-11e9-9264-59ae113cad32.gif)| ![circluar](https://user-images.githubusercontent.com/24237865/54488605-ffa21100-48e6-11e9-8c0d-aba373077905.gif)\n\nNONE | FADE\n------------ | -------------\n![none](https://user-images.githubusercontent.com/24237865/54488604-ffa21100-48e6-11e9-9920-c172eafe7a8a.gif) | ![fade](https://user-images.githubusercontent.com/24237865/54488607-003aa780-48e7-11e9-8902-cbad62402822.gif)\n\n\n```java\nbuilder.setNeedsAnimation(NeedsAnimation.FADE)\nbuilder.setNeedsAnimation(NeedsAnimation.NONE)\nbuilder.setNeedsAnimation(NeedsAnimation.ELASTIC)\nbuilder.setNeedsAnimation(NeedsAnimation.CIRCULAR)\n```\n\n### Kotlin Extensions\nWe can show and initialize Needs property more polish using extensions.\n\n#### showNeeds\nShows the popup menu to the center. \u003cbr\u003e\nIt observes the target view's inflating and after inflate finished, it show up on the target view.\n```\ntargetView.showNeeds(needs)\n```\n\n### Lazy initialization\nWe can initialize the needs property lazily using `needs` keyword and Needs.Factory abstract class.\u003cbr\u003e\nThe `needs` extension keyword can be used on Activity and Fragment.\n```\nclass MainActivity : AppCompatActivity() {\n  private val myNeeds by needs\u003cDarkNeedsFactory\u003e()\n  \n  // ..\n}\n```\n\nWe should create a class which extends Needs.Factory.\u003cbr\u003e\nAn implementation class of the factory must have a default(non-argument) constructor.\n```kotlin\nclass DarkNeedsFactory : Needs.Factory() {\n\n  override fun create(context: Context, lifecycle: LifecycleOwner): Needs {\n    return Needs.Builder(context)\n      .setTitle(\"Permission instructions \\nfor using this Android app.\")\n      .setDescription(\"The above accesses are used to better serve you. This application is available even if you do not agree to allow it.\")\n      .setConfirm(\"Confirm\")\n      .setBackgroundAlpha(0.6f)\n      .setLifecycleOwner(lifecycle)\n      .setNeedsAnimation(NeedsAnimation.FADE)\n      .addNeedsItem(NeedsItem(null, \"· SD Card\", \"(Required)\", \"   Access photos, media, and files on device.\"))\n      .addNeedsItem(NeedsItem(null, \"· Location\", \"(Required)\", \"   Access this device's location.\"))\n      .addNeedsItem(NeedsItem(null, \"· Camera\", \"(Optional)\", \"   Take pictures and record video.\"))\n      .addNeedsItem(NeedsItem(null, \"· Contact\", \"(Optional)\", \"   Access this device's contacts.\"))\n      .addNeedsItem(NeedsItem(null, \"· SMS\", \"(Optional)\", \"   Send and view SMS messages.\"))\n      .build()\n  }\n}\n```\n\n### Preference\nIf you want to show-up the Popup only once or a specific number of times, here is how to implement it simply.\n```java\n.setPreferenceName(\"MyNeeds\") // sets preference name of the Needs.\n.setShowTime(3) // show-up three of times the popup. the default value is 1 If the preference name is set.\n```\n\n### Avoid Memory leak\nDialog, PopupWindow and etc.. have memory leak issue if not dismissed before activity or fragment are destroyed.\u003cbr\u003e\nBut Lifecycles are now integrated with the Support Library since Architecture Components 1.0 Stable released.\u003cbr\u003e\nSo we can solve the memory leak issue so easily.\u003cbr\u003e\n\nJust use `setLifecycleOwner` method. Then `dismiss` method will be called automatically before activity or fragment would be destroyed.\n```java\n.setLifecycleOwner(lifecycleOwner)\n```\n\n## Needs builder methods\n```java\n.setTitleIcon(@DrawableRes drawable: Drawable)\n.setTitle(value: String)\n.setTitleTextForm(value: TextForm)\n.setDescription(value: String)\n.setDescriptionTextForm(value: TextForm)\n.setConfirmBackgroundColor(@ColorInt value: Int)\n.setConfirm(value: String)\n.setConfirmTextForm(value: TextForm)\n.setConfirmVisible(value: Boolean)\n.setListAdapter(value: RecyclerView.Adapter\u003c*\u003e)\n.setListHeight(value: Int)\n.setPadding(value: Int)\n.addNeedsItem(value: NeedsItem)\n.addNeedsItemList(value: List\u003cNeedsItem\u003e)\n.setBackground(@DrawableRes value: Drawable)\n.setBackgroundColor(@ColorInt value: Int)\n.setBackgroundAlpha(value: Float)\n.setDividerColor(@ColorInt value: Int)\n.setDividerVisible(value: Boolean)\n.setDividerHeight(value: Float)\n.setOnConfirmListener(value: OnConfirmListener)\n.setLifecycleOwner(value: LifecycleOwner)\n.setNeedsTheme(value: NeedsTheme)\n.setNeedsItemTheme(value: NeedsItemTheme)\n.setNeedsAnimation(value: NeedsAnimation)\n```\n\n## Find this library useful? :heart:\nSupport it by joining __[stargazers](https://github.com/skydoves/Needs/stargazers)__ for this repository. :star:\n\n# License\n```xml\nCopyright 2019 skydoves\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","funding_links":["https://github.com/sponsors/skydoves","https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Fneeds","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskydoves%2Fneeds","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Fneeds/lists"}