我只需要一些相对简单的东西。在网上找不到任何指南/资源来帮助我实现以下行为:
所以有三件事:
- 出现在视图中的涟漪
- 弹出窗口的缩放动画(找不到自定义的方法)
- 文本从Spinner字段传递到实际弹出窗口
任何帮助都将不胜感激。
编辑
涟漪实际上是可以在文档中找到的直接的东西。弹出窗口下拉列表的缩放动画是我最感兴趣的部分。如果我只能获得对该弹出窗口的引用,我就可以按照自己的意愿进行动画处理……有什么想法吗?
我只需要一些相对简单的东西。在网上找不到任何指南/资源来帮助我实现以下行为:
所以有三件事:
任何帮助都将不胜感激。
编辑
涟漪实际上是可以在文档中找到的直接的东西。弹出窗口下拉列表的缩放动画是我最感兴趣的部分。如果我只能获得对该弹出窗口的引用,我就可以按照自己的意愿进行动画处理……有什么想法吗?
There is no way to retrieve the PopupWindow
that displays by extending ANY class. There are a lot of nested classes that contribute to the feature (spoiler: They are mostly private).
You can customize the enter and exit transitions of the PopupWindow
...statically in your theme (woohoo!). I'm currently using AppCompat v23 and doing some investigation i found:
The style that customizes ListPopupWindow
LOLLIPOP and above
<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>
The style that customizes it pre-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>
And this is what you set in your Theme:
// From the constructor listPopupWindowStyle is the
// theme attribute you're looking for.
public ListPopupWindow(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.listPopupWindowStyle);
}
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();
}
View
滚动到popupWindow
中心并相应地更新yoff
Y偏移量。
popupEnterTransition属性限制为只有LOLLIPOP
,但如果这不是问题,您可以在那里插入缩放动画,这样就可以获得所需的效果。但我还没有尝试过,但我认为更好的动画效果应该是从下拉列表中心开始的reveal效果(从你的规格视频看起来是这样的)。ViewTreeObserver.OnGlobalLayoutListener
来获取弹出窗口。 - efemoneyWindow
上。它会捕获刚添加到窗口的弹出窗口,然后你可以取消注册vto?我在想这个是因为我相信弹出窗口是在它自己的窗口中创建的。 - efemoney1) 实现水波纹效果有两种方法:一种是将CardView作为每个单独列表项的父元素,另一种是创建一个选择器并将其设置为单个列表项的背景。
2) 您可以尝试使用元素转换来相应地动画化您的视图
3) 您应该将您的文本作为额外数据从购物信息列表项传递到内部下拉列表,或者您需要简单地保存和维护所选位置
您可能还想使用第三方库来实现此功能。 请访问http://android-arsenal.com 查找一个!