Подтвердить что ты не робот

Android Spinner Reveal Animation Material Design

Мне просто нужно что-то довольно простое. Невозможно найти какой-либо справочник/ресурс в Интернете, который поможет мне достичь следующих действий:

Итак, есть 3 вещи:

  • Пульсация, которая, по-видимому, ограничена представлением
  • Увеличить анимацию всплывающего окна (не удается найти способ ее настройки)
  • Текст переносится из поля Spinner в фактическое всплывающее окно

Любая помощь приветствуется.

ИЗМЕНИТЬ

Пульсация - это прямолинейная вещь, которая может быть найдена в документах. Масштабирование анимации всплывающего окна - вот что интересно мне больше всего. Если бы я мог получить ссылку на это всплывающее окно, я мог бы анимировать его, но я хочу... Идеи кто-нибудь?

4b9b3361

Ответ 1

Я работаю над решением этого в прошлом > 48 часов (у меня есть дополнительное время, не обвиняйте меня), и я могу сказать вам это точно:

  • Использование темы AppCompat и обычного Spinner дает вам рябь для свободной (yay!). Если у вас есть пользовательский Spinner, не забудьте расширить AppCompatSpinner, и вы получите неплохую тематику. Цитирование AppCompatSpinner javadoc:

A Spinner, поддерживающий совместимые функции на старой версии платформы, включая:

  • Позволяет использовать динамический оттенок фона с помощью методов оттенков фона в ViewCompat.
  • Позволяет установить оттенок фона с использованием backgroundTint и backgroundTintMode.
  • Позволяет настраивать тему всплывающих окон, используя popupTheme.

Это будет автоматически использоваться, когда вы используете Spinner в своих макетах. Вам нужно будет только вручную использовать этот класс при написании пользовательских представлений.

  1. Существует способ no получить PopupWindow, который отображается, расширяя класс ЛЮБОЙ. Есть много вложенных классов, которые способствуют этой функции (спойлер: они в основном частные).

  2. Вы можете настроить переходы ввода и выхода PopupWindow... статически в своей теме (woohoo!). В настоящее время я использую AppCompat v23 и выполняю следующее исследование, которое я нашел:

    • Стиль, который настраивает ListPopupWindow LOLLIPOP и выше

      <style name="Widget.Material.ListPopupWindow">
          <item name="dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
          <item name="popupBackground">@drawable/popup_background_material</item>
          <item name="popupElevation">@dimen/floating_window_z</item>
          <item name="popupAnimationStyle">@empty</item>
          <item name="popupEnterTransition">@transition/popup_window_enter</item>
          <item name="popupExitTransition">@transition/popup_window_exit</item>
          <item name="dropDownVerticalOffset">0dip</item>
          <item name="dropDownHorizontalOffset">0dip</item>
          <item name="dropDownWidth">wrap_content</item>
      </style>
      
    • Стиль, который настраивает его перед LOLLIPOP:

      <style name="Base.Widget.AppCompat.ListPopupWindow" parent="">
          <item name="android:dropDownSelector">?attr/listChoiceBackgroundIndicator</item>
          <item name="android:popupBackground">@drawable/abc_popup_background_mtrl_mult</item>
          <item name="android:dropDownVerticalOffset">0dip</item>
          <item name="android:dropDownHorizontalOffset">0dip</item>
          <item name="android:dropDownWidth">wrap_content</item>
      </style>
      
    • И это то, что вы задали в своей теме:

      // From the constructor listPopupWindowStyle is the 
      // theme attribute you're looking for.
      public ListPopupWindow(Context context, AttributeSet attrs) {
          this(context, attrs, R.attr.listPopupWindowStyle);
      }
      

Тем не менее, я все еще в процессе получения вашей специфики, но я решаю ее с помощью клонирования 2 класса: AppCompatSpinner и ListPopupWindow и добавления общедоступного getPopup() getter к клонированному ListPopupWindow коду, поэтому он доступен в моем клонированном AppCompatSpinner. Это открывает пару возможностей. Примером может служить мой метод centerPopup(), который должен сдвигать положение выложенного всплывающего окна на основе центров spinnerItem (выбранного элемента, который отображается в представлении spinner) и spinnerDropdownItem (отдельные представления, которые отображаются как элементы списка в падать). Метод centerPopup() затем вызывается в DropdownPopup.show() сразу после вызова super.show()

private void centerPopup(boolean updateListSelection) {
    boolean aboveAnchor = getPopup().isAboveAnchor();

    int[] spinnerLocation = new int[2];
    int[] popupLocation = new int[2];

    ListView listView = getListView();

    /*
        Popup is anchored at spinner TOP LEFT when it is set to overlap else at BOTTOM LEFT

        Also seems the windowlayoutparams generated for popup is wrapcontent for width and height
        As a result popup locationOnScreen returns [0, 0] which is relative to the window.
        We can take it as relative to spinner location and add spinnerLocation X value to give
        left edge of popup
     */

    MaterialSpinner.this.getLocationInWindow(spinnerLocation);
    int spMidX = spinnerLocation[0] + (MaterialSpinner.this.getWidth() / 2);
    int spMidY = spinnerLocation[1] + (MaterialSpinner.this.getHeight() / 2);

    Rect spinnerBgdPadding = new Rect();
    MaterialSpinner.this.getBackground().getPadding(spinnerBgdPadding);

    // ----- BUG - returns erroneous height
    // Ideally should measure one of the drop down list children and give a height
    // exactly as it wouldwhen laid out eventually.
    // Works only for lists with homogenously tall content
    View child = listView.getAdapter().getView(0, null, listView);

    child.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT));

    child.measure(
            MeasureSpec.makeMeasureSpec(listView.getWidth() - listView.getPaddingLeft() - listView.getPaddingRight(), MeasureSpec.AT_MOST),
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
    );
    int listItemHeight = child.getMeasuredHeight();
    // ----- /BUG

    getPopup().getContentView().getLocationInWindow(popupLocation);
    int popMidX = spinnerLocation[0] + (getPopup().getWidth()) / 2;
    int popMidY = spinnerLocation[1] + (listItemHeight / 2);

    int hoff = getHorizontalOffset();
    int voff = getVerticalOffset();

    int xoff = spMidX - popMidX - hoff - spinnerBgdPadding.left;
    int yoff = spMidY - popMidY - voff;

    getPopup().update(spinnerLocation[0] + xoff, spinnerLocation[1] + yoff, -1, -1, true);

    if (updateListSelection)
        listView.setSelectionFromTop(MaterialSpinner.this.getSelectedItemPosition(), 0)
    ;

    // getPopup().update(MaterialSpinner.this, xoff, yoff, -1, -1);
    // int numVisItems = listView.getLastVisiblePosition() - getFirstVisiblePosition();

}

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

После центрирования следующий шаг будет состоять в том, чтобы прокрутить dropDownList selectedPosition View до центра PopupWindow и соответствующим образом обновить yoff Y-offset.

Атрибут popupEnterTransition ограничивается только LOLLIPOP, но если это не проблема, вы можете вставить туда масштабный переход, который должен получить необходимый эффект. Я не пробовал это, но я также думаю, что лучшая анимация будет эффектом раскрывать от центра прядильщика (это похоже на видео с вашего specs).

Но все это хорошо... в теории x_x lol

Ответ 2

1) Пульсация может быть достигнута двумя способами: одним из них является использование CardView в качестве родительского элемента для каждого элемента списка, а другой способ - создать селектор и установить его в качестве фона для вашего единственного элемента списка.

2) Вы можете попытаться использовать переходы элементов для анимирования вашего представления соответственно.

3). Вы должны передать свой текст в виде дополнительных данных из вашего списка элементов списка покупок во внутренний раскрывающийся список. Или вам нужно просто сохранить и сохранить выбранную позицию.

Вы также можете использовать для этого сторонние библиотеки. Проверьте http://android-arsenal.com, чтобы найти его!