我只需要一些简单的东西。
找不到任何在线指南/资源,可以帮助我实现following behaviour:

因此,有3件事:

  • 似乎绑定(bind)到 View
  • 的波纹
  • 放大弹出窗口的动画(找不到自定义方法)
  • 文本从Spinner字段携带到实际弹出的

  • 任何帮助表示赞赏。

    编辑

    涟漪实际上是可以直接在文档中找到的东西。弹出下拉菜单的放大动画是我最感兴趣的。如果我只能引用该弹出窗口,则可以对其进行动画处理,但是...有人吗?

    最佳答案

    在过去的48小时内,我一直在致力于解决此问题的方法(我有一些额外的时间不要怪我),我可以肯定地告诉你这些:

  • 使用AppCompat主题和常规Spinner,可以为免费(是的!)起波纹。如果您有自定义的Spinner,请确保扩展AppCompatSpinner,这样您将获得一些不错的主题。引用AppCompatSpinner javadoc:


  • 没有,没有方式来检索通过扩展 ANY 类显示的PopupWindow。有很多嵌套类可以为该功能做出贡献(破坏者:它们大多是私有(private)的)。
  • 可以自定义主题中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类来解决它:AppCompatSpinnerListPopupWindow,并向克隆的getPopup()代码添加公共(public)ListPopupWindow getter,以便可以在我的克隆AppCompatSpinner中对其进行访问。这带来了两个机会。我的centerPopup()方法就是一个示例,该方法应根据spinnerItem(在Spinner View 本身中显示的所选项目)和spinnerDropdownItem(在下拉列表中以列表项目显示的单个 View )的中心来移动布局弹出窗口的位置)。然后在调用DropdownPopup.show()之后立即在super.show()中调用centerPopup()方法
    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偏移量。

    popupEnterTransition属性仅限制为LOLLIPOP,但是如果这不成问题,则可以在此处插入按比例放大的过渡,这应该可以为您带来想要的效果。不过,我还没有尝试过,但我也认为更好的动画效果是旋转中心的显示效果(看起来像您的规范视频中的效果)。

    但是所有这些都很好...理论上x_x大声笑

    关于android - Android Spinner显示动画素材设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30053820/

    10-10 18:45
    查看更多