Задание цветного текста с текстом программно отстает, медленный, неправильный цвет для секунды секунды

TL;DR: Мой счетчик отображает неправильный цвет в течение секунды.

У меня проблема с моим счетчиком. Всякий раз, когда я запускаю приложение, если активность не кэшируется в памяти, она иногда отстает. Текст является цветом по умолчанию (например, черным), прежде чем я смогу установить его в нужный цвет. Это выглядит очень непрофессионально.

Видео: Пожалуйста, смотрите эту запись на экране, чтобы увидеть это в действии: https://drive.google.com/file/d/0By2AG5yaBEhMRnRsbVBDU251STQ/view

Как он ищет одну сплит-секунду при загрузке страницы: введите описание изображения здесь

Как это выглядит после времени запаздывания (и как оно должно выглядеть с самого начала): введите описание изображения здесь

Код:

public class MyActivity extends AppCompatActivity
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        Spinner spinner = (Spinner) findViewById(R.id.spinner);

        //Get rid of the normal toolbar title, because the spinner is replacing the title.
        getSupportActionBar().setDisplayShowTitleEnabled(false);

        //Set the choices on the spinner by setting the adapter.
        spinner.setAdapter(new SpinnerAdapter(toolbar.getContext(), new String[]{"Overview", "Story", "Specifications", "Poll", "Video"}, accentColor, backgroundColor));

        //Set the listener for when each option is clicked.
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
        {

            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
            {
                //Change the selected item text color
                ((TextView) view).setTextColor(backgroundColor);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent)
            {
            }
        });
    }
}

XML:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
                                   xmlns:app="http://schemas.android.com/apk/res-auto"
                                   android:layout_width="match_parent"
                                   android:layout_height="wrap_content"
                                   android:background="@color/ColorPrimary"
                                   android:elevation="4dp">
    <Spinner
        android:id="@+id/spinner"
        app:popupTheme="@style/AppTheme.PopupOverlay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</android.support.v7.widget.Toolbar>

Ответ 1

Что я делал неправильно:

Раньше я следил за советом этого ответа и устанавливал цвет текста в методе onItemSelected, но этот метод вызывается автоматически только после пользовательского интерфейса и вы не можете вызвать onItemSelected непосредственно из своего кода. Это вызвало задержку. (Но это все еще необходимо, когда вы выбираете элемент из выпадающего списка - см. Мое решение по этому вопросу.)

Решение:

Стратегия заключается в том, чтобы получить представление "Выбранное" и установить его цвет текста до завершения контура. Когда я тестировал его в отладчике, во время метода onCreate не отображается UI, поэтому это гарантированно работает.

Мне просто пришлось добавить этот код после вызова setAdapter(...):

//Set the text color of the Spinner selected view (not a drop down list view)
spinner.setSelection(0, true);
View v = spinner.getSelectedView();
((TextView)v).setTextColor(backgroundColor);

Ключевым моментом является вызов spinner.setSelection(0, true) с параметром true. В противном случае, если вы просто вызываете spinner.setSelection(0), представление v будет равно null. Я узнал об этом благодаря этому ответу.

Полный метод:

Вот полный метод. ПРИМЕЧАНИЕ. Код в onItemSelected должен быть там! Поскольку в противном случае каждый раз, когда вы выбираете элемент из выпадающего списка, он будет иметь неправильный цвет.

@Override 
protected void onCreate(Bundle savedInstanceState)
{ 
    Spinner spinner = (Spinner) findViewById(R.id.spinner);

    //Get rid of the normal toolbar title, because the spinner is replacing the title. 
    getSupportActionBar().setDisplayShowTitleEnabled(false); 

    //Set the choices on the spinner by setting the adapter. 
    spinner.setAdapter(new SpinnerAdapter(toolbar.getContext(), new String[]{"Overview", "Story", "Specifications", "Poll", "Video"}, accentColor, backgroundColor));

    //Set the text color of the Spinner selected view (not a drop down list view)
    spinner.setSelection(0, true);
    View v = spinner.getSelectedView();
    ((TextView)v).setTextColor(backgroundColor);

    //Set the listener for when each option is clicked. 
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
    { 

        @Override 
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
        { 
           //Change the selected item text color 
           ((TextView) view).setTextColor(backgroundColor);
        } 

        @Override 
        public void onNothingSelected(AdapterView<?> parent)
        { 
        } 
    }); 

} 

Для получения дополнительной информации об исходном коде методов setSelection см. код AbsSpinner.java здесь: https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/widget/AbsSpinner.java

И вот Spinner.java в случае, если это поможет: https://android.googlesource.com/platform/frameworks/base/+/jb-release/core/java/android/widget/Spinner.java