I took part in the 2021 popular creators, for me, please vote for the precious vote address rank. Juejin. Cn/rank / 2021/3… Thank you very much!
preface
Spinner is a drop-down selection component. It is very convenient to use the system’s own spinner. First, define an array (strings.xml) as follows:
<array name="grade">
<item>In grade one</item>
<item>Second grade</item>
<item>The third grade</item>
<item>In fourth grade</item>
<item>The fifth grade</item>
<item>The sixth grade</item>
</array>
Copy the code
The code is as follows:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.grade, android.R.layout.simple_spinner_item);
spinner.setAdapter(adapter);
Copy the code
This results in a simple spinner that looks like this:
But this is not the style and effect I want, let’s change it a little bit.
(1) Change the initial layout
That is, the popover style, first customize a layout, as follows:
spinner_layout.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:textColor="#6d6d6d"
android:textSize="15sp"
android:drawableRight="@drawable/arrow"
android:drawablePadding="5dp"
tools:text="First grade">
</TextView>
Copy the code
Then replace createFromResource as follows:
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.grade, R.layout.spinner_layout);
Copy the code
This is not enough, as there is also a background with arrows, just set the background to transparent like this:
spinner.setBackgroundColor(0x0);
Copy the code
This renders the initial layout as spinner_layout.
(2) Change the layout of list item
After the above modification, the layout of the list item in the popover is also changed to spinner_layout. Check the constructor of ArrayAdapter, we can see that there are two variables: mResource and mDropDownResource, where mResource is the initial layout. And mDropDownResource is the layout of the list item.
In createFromResource, mResource and mDropDownResource are assigned the same value. But ArrayAdapter also has a setDropDownViewResource function.
Start by defining a layout as follows:
spinner_item.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:textColor="#6d6d6d"
android:textSize="15sp"
android:padding="8dp"
android:gravity="center_horizontal"
tools:text="First grade">
</TextView>
Copy the code
Then use the setDropDownViewResource function as follows:
adapter.setDropDownViewResource(R.layout.spinner_item);
Copy the code
(3) Change the popover background and position
In the first animation you can see that the popover is covered, and we want it to be underneath, and it’s rounded with arrows.
This will need to use the two functions of spinner setPopupBackgroundResource and setDropDownVerticalOffset.
However, note that these two functions need to be on android4.1 or above. Since there are few versions below 4.1 at present, we only consider above 4.1. The code is as follows:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
spinner.setPopupBackgroundResource(R.drawable.bg_spinner);
spinner.setDropDownVerticalOffset(dip2px(20));
}
Copy the code
(4) Add the selected effect
After the above processing, we have the desired style. But it’s not nearly as good. The popover list is missing the selected styles. For example, if I currently select “grade 2”, in the popover, the corresponding item font should be darker and bolder. We searched spinner’s source code and found no corresponding function or solution, so we’ll do it ourselves.
The spinner uses a adapter to load the list, and the createFromResource function creates a new adapter automatically. We can create a custom adapter as follows:
public class SpinnerAdapter<T> extends ArrayAdapter<T> {
private int selectedPostion;
public void setSelectedPostion(int selectedPostion) {
this.selectedPostion = selectedPostion;
}
public SpinnerAdapter(@NonNull Context context, int resource, @NonNull T[] objects) {
super(context, resource, objects);
}
@Override
public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getDropDownView(position, convertView, parent);
TextView textView = (TextView)view;
if(selectedPostion == position){
textView.setTextColor(0xff373741);
textView.getPaint().setFakeBoldText(true);
}
else{
textView.setTextColor(0xff6d6d6d);
textView.getPaint().setFakeBoldText(false);
}
return view;
}
public static @NonNull SpinnerAdapter<CharSequence> createFromResource(@NonNull Context context,
@ArrayRes int textArrayResId, @LayoutRes int textViewResId) {
final CharSequence[] strings = context.getResources().getTextArray(textArrayResId);
return newSpinnerAdapter<>(context, textViewResId, strings); }}Copy the code
Note that the getDropDownView function in the ArrayAdapter gets the view used by the popover item, not the getView function.
In the meantime we’re going to rewrite a createFromResource function.
Replace the adapter used previously with the custom one and set the listener for the spinner. The code is as follows:
Spinner spinner = (Spinner) findViewById(R.id.spinner);
adapter = SpinnerAdapter.createFromResource(this, R.array.grade, R.layout.spinner_layout);
adapter.setDropDownViewResource(R.layout.spinner_item);
spinner.setBackgroundColor(0x0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
spinner.setPopupBackgroundResource(R.drawable.bg_spinner);
spinner.setDropDownVerticalOffset(dip2px(20));
}
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<? > parent, View view,int position, long id) {
adapter.setSelectedPostion(position);
}
@Override
public void onNothingSelected(AdapterView
parent) {}});Copy the code
The final effect is as follows:
We can implement more complex effects and styles by defining the Adapter ourselves, but we will discuss this later.