A lightweight dropdown popup spinner with an arrow and animations
PowerSpinner
A lightweight dropdown popup spinner with an arrow and animations.
Including in your project
Gradle
Add below codes to your root build.gradle
file (not your module build.gradle file).
allprojects {
repositories {
jcenter()
}
}
And add a dependency code to your module's build.gradle
file.
dependencies {
implementation "com.github.skydoves:powerspinner:1.0.1"
}
Usage
Add following XML namespace inside your XML layout file.
xmlns:app="http://schemas.android.com/apk/res-auto"
PowerSpinnerView
Here is a basic example of implementing PowerSpinnerView
.
Basically the PowerSpinnerView
extends TextView
, so we can use it like a TextView
.
You can set the unselected text using hint
and textColorHint
attributes.
<com.skydoves.powerspinner.PowerSpinnerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/md_blue_200"
android:gravity="center"
android:hint="Question 1"
android:padding="10dp"
android:textColor="@color/white_93"
android:textColorHint="@color/white_70"
android:textSize="14.5sp"
app:spinner_arrow_gravity="end"
app:spinner_arrow_padding="8dp"
app:spinner_divider_color="@color/white_70"
app:spinner_divider_show="true"
app:spinner_divider_size="0.4dp"
app:spinner_item_array="@array/questions"
app:spinner_popup_animation="dropdown"
app:spinner_popup_background="@color/background800"
app:spinner_popup_elevation="14dp" />
Create using builder class
We can create an instance of PowerSpinnerView
using the builder class.
val mySpinnerView = createPowerSpinnerView(this) {
setSpinnerPopupWidth(300)
setSpinnerPopupHeight(350)
setArrowPadding(6)
setArrowAnimate(true)
setArrowAnimationDuration(200L)
setArrowGravity(SpinnerGravity.START)
setArrowTint(ContextCompat.getColor(this@MainActivity, R.color.md_blue_200))
setSpinnerPopupAnimation(SpinnerAnimation.BOUNCE)
setShowDivider(true)
setDividerColor(Color.WHITE)
setDividerSize(2)
setLifecycleOwner(this@MainActivity)
}
Show and dismiss
Basically, when the PowerSpinnerView
is clicked, the spinner popup will be showed and
when an item is selected, the spinner popup will be dismissed.
But you can show and dismiss manually using methods.
powerSpinnerView.show() // show the spinner popup
powerSpinnerView.dismiss() // dismiss the spinner popup
// If the popup is not showing, shows the spinner popup menu.
// If the popup is already showing, dismiss the spinner popup menu.
powerSpinnerView.showOrDismiss()
And you can set the show and dismiss actions using some listener and attributes.
// the spinner popup will not be shown when clicked.
powerSpinnerView.setOnClickListener { }
// the spinner popup will not be dismissed when item selected.
powerSpinnerView.dismissWhenNotifiedItemSelected = false
OnSpinnerItemSelectedListener
Interface definition for a callback to be invoked when selected item on the spinner popup.
setOnSpinnerItemSelectedListener<String> { index, text ->
toast("$text selected!")
}
Here is the java way.
powerSpinnerView.setOnSpinnerItemSelectedListener(new OnSpinnerItemSelectedListener<String>() {
@Override public void onItemSelected(int position, String item) {
toast(item + " selected!")
}
});
selectItemByIndex
We can select an item manually or initially using the below method.
spinnerView.selectItemByIndex(4)
SpinnerAnimation
We can customize the showing and dimsmiss animation.
SpinnerAnimation.DROPDOWN
SpinnerAnimation.FADE
SpinnerAnimation.BOUNCE
Dropdown | Fade | Bounce |
---|---|---|
Customized adapter
We can use our customized adapter and binds to the PowerSpinnerView
.
The PowerSpinnerView
provides the spinner popup's recyclerview via getSpinnerRecyclerView
method.
Here is a sample of the customized adapter.
val adapter = IconSpinnerAdapter(spinnerView)
spinnerView.setSpinnerAdapter(adapter)
spinnerView.getSpinnerRecyclerView().layoutManager = GridLayoutManager(context, 2)
IconSpinnerAdapter
Basically, this library provides a customized adapter.
We should create an instance of the IconSpinnerAdapter
and call setItems
using a list of IconSpinnerItem
.
spinnerView.apply {
setSpinnerAdapter(IconSpinnerAdapter(this))
setItems(
arrayListOf(
IconSpinnerItem(contextDrawable(R.drawable.unitedstates), "Item1")))
getSpinnerRecyclerView().layoutManager = GridLayoutManager(context, 2)
selectItemByIndex(0) // select an item initially.
lifecycleOwner = this@MainActivity
}
Here is the java way.
List<IconSpinnerItem> iconSpinnerItems = new ArrayList<>();
iconSpinnerItems.add(new IconSpinnerItem(contextDrawable(R.drawable.unitedstates), "item1"));
IconSpinnerAdapter iconSpinnerAdapter = new IconSpinnerAdapter(spinnerView);
spinnerView.setSpinnerAdapter(iconSpinnerAdapter);
spinnerView.setItems(iconSpinnerItems);
spinnerView.selectItemByIndex(0);
spinnerView.setLifecycleOwner(this);
Customized adapter
Here is a way to customize your adapter for binding the PowerSpinnerView
.
Firstly, create a new adapter and viewHolder extending RecyclerView.Adapter
and PowerSpinnerInterface<T>
.
You shoud override spinnerView
, onSpinnerItemSelectedListener
fields and setItems
, notifyItemSelected
methods.
class MySpinnerAdapter(
powerSpinnerView: PowerSpinnerView
) : RecyclerView.Adapter<MySpinnerAdapter.MySpinnerViewHolder>(),
PowerSpinnerInterface<MySpinnerItem> {
override val spinnerView: PowerSpinnerView = powerSpinnerView
override var onSpinnerItemSelectedListener: OnSpinnerItemSelectedListener<MySpinnerItem>? = null
On the customized adapter, you must call spinnerView.notifyItemSelected
method when your item is clicked or the spinner item should be changed.
override fun onBindViewHolder(holder: MySpinnerViewHolder, position: Int) {
holder.itemView.setOnClickListener {
notifyItemSelected(position)
}
}
// we must call the spinnerView.notifyItemSelected method to let PowerSpinnerView know about changed information.
override fun notifyItemSelected(index: Int) {
this.spinnerView.notifyItemSelected(index, this.spinnerItems[index].text)
this.onSpinnerItemSelectedListener?.onItemSelected(index, this.spinnerItems[index])
}
And we can listen to the selected item's information.
spinnerView.setOnSpinnerItemSelectedListener<MySpinnerItem> { index, item -> toast(item.text) }
Avoid Memory leak
Dialog, PopupWindow and etc.. have memory leak issue if not dismissed before activity or fragment are destroyed.
But Lifecycles are now integrated with the Support Library since Architecture Components 1.0 Stable released.
So we can solve the memory leak issue so easily.
Just use setLifecycleOwner
method. Then dismiss
method will be called automatically before activity or fragment would be destroyed.
.setLifecycleOwner(lifecycleOwner)
PowerSpinnerView Attributes
Attributes | Type | Default | Description |
---|---|---|---|
spinner_arrow_drawable | Drawable | arrow | arrow drawable. |
spinner_arrow_show | Boolean | true | sets the visibility of the arrow. |
spinner_arrow_gravity | SpinnerGravity | end | the gravity of the arrow. |
spinner_arrow_padding | Dimension | 2dp | padding of the arrow. |
spinner_arrow_animate | Boolean | true | show arrow rotation animation when showing. |
spinner_arrow_animate_duration | integer | 250 | the duration of the arrow animation. |
spinner_divider_show | Boolean | true | show the divider of the popup items. |
spinner_divider_size | Dimension | 0.5dp | sets the height of the divider. |
spinner_divider_color | Color | White | sets the color of the divider. |
spinner_popup_width | Dimension | spinnerView's width | the width of the popup. |
spinner_popup_height | Dimension | WRAP_CONTENT | the height of the popup. |
spinner_popup_background | Color | spinnerView's background | the background color of the popup. |
spinner_popup_animation | SpinnerAnimation | Dropdown | the spinner animation when showing. |
spinner_popup_animation_style | Style Resource | -1 | sets the customized animation style. |
spinner_popup_elevation | Dimension | 4dp | the elevation size of the popup. |
spinner_item_array | String Array Resource | null | sets the items of the popup. |
spinner_dismiss_notified_select | Boolean | true | sets dismiss when the popup item is selected. |