In the previous chapters, Xiaobai has introduced the basic usage of TextView, Button, Checkbox and Switch and other basic controls, please see:

  1. Small white 7 – Android native development fur series -TextView

  2. Small white 7 – Android native development fur series (2) -Button and Checkbox

  3. Small white 7 – Android native development fur series (3) -Switch

In this chapter, White needs to find a tasteless control that can be discarded. It’s called the Spinner, which can simply be called the options control. When we talk about options, the first thing that comes to mind is dropdown. Spinner is a similar control in the native World of Android. Of course, Spinner is a little more complex, and the complexity feels like a result of some of the ideas Google or early Android teams explored in mobile UI design and development. Unfortunately, Spinner’s quest was not very successful. Therefore, at the end of this chapter, Xiao Bai will recommend an alternative approach.

Spinner is the simplest to use

A TAB control like Dropdown is often used in a project to implement certain input items such as type, classification, etc. At the same time, these input items usually have fixed options. For example, in the calendar app, we usually need to select the day of the week to input. This is where you can use the simplest use of Spinner.

  • Define a fixed list of options

At this point you need to use strings.xml. If you’ve read TextView, Switch, etc., you should be familiar with the strings. XML file that defines the fixed text configuration for static text display on the interface. But strings. XML is much more powerful than Xiao Bai imagined. Here is an example of a string-array that defines a fixed optional value. I feel like I’ve found a new continent:

<string-array name="week"> <item> Monday </item> <item> Tuesday </item> <item> Wednesday </item> <item> Thursday </item> <item> Friday </item> <item> Saturday </item> <item> Sunday </item> </string-array>Copy the code
  • Define the Spinner and set the selection values

“Here you simply need to specify the text list above for Spinner’s property entries, as shown in Figure 1:

Figure 1 Setting the Entries property

Through the above two steps, that is, the most basic use can be achieved. Of course, the limitations of this use are obvious: First, Spinner’s options are limited to specifying string-array list elements, and there is no flexibility to change them. Second, there is no option customization that can be set through entries property binding data. For example, if you want an icon next to each option, you can’t. Of course, this approach solves about 50% of our needs, since Spinner’s application scenarios are usually less demanding.

Spinner and Adapter

In addition to the most basic usage, Spinner can also be used with adapters. Essentially, the Spinner can be thought of as a ListView, a direct relative of the ListView. Through Adapter, you can achieve flexible option binding, and you can control the display of each option. Of course, the disadvantages are also obvious. It is slightly complicated to use. Without further ado, let’s introduce the usage process.

  • The layout file that defines the Spinner option list elements.

The options list element layout file is used to layout what the interface looks like for each TAB in the drop-down list. You can use this Layout File to create a very complex look by right clicking res > New > XML > Layout XML File. Here we define a spinner_item. XML file and a simple TextView control to implement the Monday-Sunday display, as follows:

<? The XML version = "1.0" encoding = "utf-8"? > <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/spinner_item" android:layout_width="match_parent" android:layout_height="wrap_content"/>Copy the code
  • Defines the layout file for the Spinner selected element.

The selected elements layout file is used to layout how the selected elements will look on the Spinner control. If your presentation is simple, such as just displaying text, then the selected element layout file and the options list element layout file can be combined. However, if there is a difference in the display, then it is advisable to separate them out. This works like an option list element layout file. The spinner_selected_item. XML file contains the following code:

<? The XML version = "1.0" encoding = "utf-8"? > <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/spinner_selected_item" android:layout_width="match_parent" android:layout_height="wrap_content" />Copy the code
  • Define a data entity class and the implementation of SpinnerAdapter.

The data entity class is a Data-hosting Java class that holds the specific data that needs to be used in the Spinner control. Data entity classes can be very complex, depending on the implementation of your requirements. Here we define a SpinnerDataEntity class as follows:

Public class SpinnerDataEntity {/** * value */ private String value; /** * Display text */ private String text; public SpinnerDataEntity(){ } public SpinnerDataEntity(String value, String text){ this.value = value; this.text = text; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public String getText() { return text; } public void setText(String text) { this.text = text; }}Copy the code

The SpinnerAdapter interface defines the adaptation of data to the interface display, similar to the processing of data binding, display the specified interface control. Basically, it tells the Spinner how to display the selected elements, what to display, how to display the drop-down list, what to display. There are many implementations of the SpinnerAdapter interface, such as ArrayAdapter, SimpleAdapter, etc. Here we extend ArrayAdapter to achieve our desired custom SpinnerCustomAdapter. The code is as follows:

import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; /** * SpinnerCustomAdapter */ Public class SpinnerCustomAdapter extends ArrayAdapter<SpinnerDataEntity> {private int resource; private int selectedResource; public SpinnerCustomAdapter(@NonNull Context context, int resource, int selectedResource, @NonNull SpinnerDataEntity[] objects) { super(context, resource, objects); this.resource = resource; this.selectedResource = selectedResource; } @Override public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { if(convertView == null){ convertView = LayoutInflater.from(this.getContext()).inflate(this.resource, null); } TextView itemView = (TextView) convertView; SpinnerDataEntity item = getItem(position); itemView.setText(item.getText()); return convertView; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { if(convertView == null){ convertView = LayoutInflater.from(this.getContext()).inflate(this.selectedResource, null); } TextView itemView = (TextView) convertView; SpinnerDataEntity item = getItem(position); itemView.setText(item.getText()); return convertView; }}Copy the code

Where resource and selectedResource specify option list element layout file spinner_item. XML and selected element layout file spinner_selected_item.xml respectively by layout file ID. The selected element data interface is displayed by processing the binding from the write getView method. GetDropDownView handles the data interface presentation of the binding options list elements.

  • Define the Spinner

  • Bind Adapter to Spinner

Finally, pass the SpinnerCustomAdapter instance to the Spinner through the Spinner’s setAdapter method. Note that the layout file for the SpinnerCustomAdapter should be in R.Layout, not R.ID, remember! The binding code in the Activity looks like this:

private Spinner weekday; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_spinner_view); if(savedInstanceState == null){ this.initWeekdaySpinner(); } } private void initWeekdaySpinner() { SpinnerDataEntity[] dataEntities = new SpinnerDataEntity[]{ new New SpinnerDataEntity(" Monday ", "Monday "), new SpinnerDataEntity(" Tuesday "," Tuesday "), new SpinnerDataEntity(" Wednesday ", "Wednesday "), new SpinnerDataEntity(" Tuesday "," Tuesday "), New SpinnerDataEntity(" Wednesday ", "Wednesday "), New SpinnerDataEntity (" Thursday ", "Monday"), the new SpinnerDataEntity (" Friday ", "Friday"), the new SpinnerDataEntity (" Saturday ", New SpinnerDataEntity(" Sunday ", "Sunday ")}; ArrayAdapter<SpinnerDataEntity> spinnerDataEntityArrayAdapter = new SpinnerCustomAdapter(getApplicationContext(), R.layout.spinner_item, R.layout.spinner_selected_item, dataEntities); this.weekday = findViewById(R.id.weekday); this.weekday.setAdapter(spinnerDataEntityArrayAdapter); }Copy the code

This way you can get a custom flexible Spinner. If you want an icon you can also add it up and give you a sun:

                           

Spinner dropdown mode and Dialog mode

We’ve seen some usage of a Spinner from the above two examples. But Spinner can actually be presented in two ways. One is dropdown like you saw in the example above. The other is a dialog, which is a pop-up box. Dropdown is a very common way to do this, especially on the web, and you’ll see it used a lot. However, this approach is not very friendly on mobile phones. For example, how big is the drop-down menu? Or what if the list is long? Dialog was clearly one of the early android teams to try to improve the Spinner front end experience. It was called trial because He felt that Dialog was not a very successful improvement and still had flaws. First, compare the interface between the two.

Figure 3 dropdown mode and Dialog mode

The only difference between the two is the spinnerMode property, which defaults to DropDown.

<Spinner android:id="@+id/weekday" android:layout_width="match_parent" android:layout_height="wrap_content" Android: layout_gravity = "center_vertical" android: spinnerMode = "dialog" / >Copy the code

Because of the existence of the two modes, the properties of the Spinner are also divided into two sets and work in different modes.

Property of Spinner Dropdown mode

Spinner in DropDown mode has the following properties:

  1. DropDownWidth property: This property controls the width of the drop-down menu. If you select an element with less text, you can reduce it.

  2. DropDownVerticalOffset property: This property controls the vertical offset of the dropdown menu. Usually, as in the example above, the drop-down menu appears to obscure the selected element. With this property, you can control the drop-down menu to move one position.

  3. DropDownHorizontalOffset property: This property is similar to dropDownVerticalOffset for controlling the horizontal offset of drop-down menus.

  4. DropDownSelector property: This property sets the effect of a state change when an option element is clicked and selected. However, pro tests, unless specially set, this property will not work.

  5. PopupBackground property: Sets the background color of the drop-down menu.

The dropDownVerticalOffset property is used as an example.

Figure 4 dropDownVerticalOffset with and without setting

Properties in Spinner Dialog mode

The spinner has only one property in dialog mode:

Prompt property – This property is used to give the pop-up mode box a title. The odd thing about this property is that it doesn’t accept strings that are set directly, such as Prompt = “Please select” which would cause an error. But android: Prompt = “@string/spinner_prompt” is acceptable. Can it also accept drawable and layout types? I’ll leave you guys with the whiteness. The effect is as follows:

                          

Figure 5 Prompt Settings

A scroll selector that mimics DropDown

As White mentioned earlier, Spinner is not a good mobile visualization, whether dropdown or Dialog mode. This is mainly due to some size Settings and a slightly larger list of items. But in fact, there is a better selector design, and that is scroll selection. IOS users should be familiar with it. From a user experience point of view, this design of the select box is a good choice. Of course, white can not say it is not a problem. Its biggest problem is apple’s patents. Unfortunately, as far as He knows, Apple has patented UI designs such as scrolling selection. Ah, find a good how so difficult!!

Here’s a quick pickerview from Jaaksi: github.com/jaaksi/pick… . Oh, god! Worship!

Here’s how to use one of the OptionPicker controls:

  • Import packages in build.gradle:

    Implementation ‘org. Jaaksi: pickerview: 3.0.2’

  • You need a TextView that mimes the input to display the selected element information.

  • You need to define the OptionDataSet to store data.

    package com.white7code.mobile.android.basecourse;

    import org.jaaksi.pickerview.dataset.OptionDataSet;

    import java.util.List;

    public class WeekDayOption implements OptionDataSet {

    private String value;
    
    public WeekDayOption(String value){
        this.value = value;
    }
    
    @Override
    public List<WeekDayOption> getSubs() {
        return null;
    }
    
    @Override
    public CharSequence getCharSequence() {
        return this.value;
    }
    
    @Override
    public String getValue() {
        return this.value;
    }
    Copy the code

    }

  • You need to create TextView click events, build triggers OptionPicker display.

    package com.white7code.mobile.android.basecourse;

    import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.TextView;

    import androidx.appcompat.app.AppCompatActivity;

    import org.jaaksi.pickerview.dataset.OptionDataSet; import org.jaaksi.pickerview.picker.OptionPicker;

    import java.util.ArrayList; import java.util.List;

    public class SpinnerViewActivity extends AppCompatActivity {

    private TextView spinnerSimulator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_spinner_view); if (savedInstanceState == null) { this.initSpinnerSimulator(); } } private void initSpinnerSimulator() { final List<WeekDayOption> options = new ArrayList<>(7); Options. Add (new WeekDayOption(" Monday ")); Options. Add (new WeekDayOption(" Tuesday ")); Options. Add (new WeekDayOption(" Wednesday ")); Options. Add (new WeekDayOption(" Thursday ")); Options. Add (new WeekDayOption(" Friday ")); Options. Add (new WeekDayOption(" Saturday ")); Options. Add (new WeekDayOption(" Sunday ")); final Activity self = this; this.spinnerSimulator = findViewById(R.id.spinner_simulator); this.spinnerSimulator.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { OptionPicker optionPicker = new OptionPicker.Builder(self, 1, new OptionPicker.OnOptionSelectListener() { @Override public void onOptionSelect(OptionPicker picker, int[] selectedPosition, OptionDataSet[] selectedOptions) { if (selectedOptions ! = null && selectedOptions.length > 0) { spinnerSimulator.setText(selectedOptions[0].getValue()); } } }).create(); optionPicker.setData(options); optionPicker.show(); }}); }Copy the code

    }

You’ll end up with something like figure 6:

                                    

Figure 6 scroll selector

conclusion

So here’s white’s basic introduction to the use of some fur on the Spinner. In fact, small white feel that there are many aspects worth digging, limited by personal energy, can only point so far. Need these slowly knowledge precipitate for everyone reference, helpful. I also hope that xiaobai, the real Android xiaobai, can learn some of the essence of android native development in this way.