触点的涟漪
谷歌已经开始向应用程序开发人员指出他们在Material Design风格的UI中使用涟漪动画时,这些涟漪似乎不会从触发动画的触摸点散发出来。
使用谷歌的搜索引擎,我发现的唯一可以解释如何使这项工作成为Lucas Rocha的TwoWayView库问题的评论。幸运的是,这个评论足以让我创造出似乎有用的东西。
正如Butcher先生在他的推文中提示的那样,关键似乎是Drawable上的setHotspot()方法。在API Level 21中添加,这教导了drawable一个“热点”,而RippleDrawable显然使用它作为涟漪效应的发散点。 setHotspot()获取一对浮点值,大概是在OnTouchListener中使用setHotspot(),因为MotionEvent使用浮点值报告触摸事件的X / Y位置。
此示例应用程序演示了在RecyclerView的上下文中使用setHotspot(),作为我正在为下一本书更新工作的50多页的章节的一部分。此RecyclerView使用LinearLayoutManager来复制经典ListView的基本结构。我的行基于CardView:
```的xml
因此,如果用户触摸一行,我会将触摸点传播到背景作为其热点。我特意返回false表示我们没有使用触摸事件,因此如果需要,它将继续使用其他事件处理程序。
如果没有这个setHotspot()调用,RippleDrawable似乎默认为drawable的中心。因此,对于列表样式的RecyclerView的行,涟漪效应将从行的中心发出。 setHotspot(),与触摸事件相关联,改变了发射点。
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
cardview:cardCornerRadius="4dp">
<LinearLayout
android:id="@+id/row_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="?android:attr/selectableItemBackground">
<!-- other widgets in here -->
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
```
The LinearLayout that the CardView wraps has ?android:attr/selectableItemBackground as its background, pulling in a theme attribute. If this app runs on API Level 21, that background will be a RippleDrawable.
When I set up the row, I attach an OnTouchListener to set the hotspot, but only on API Level 21+ devices (as setHotspot() does not exist before then):
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
row.setOnTouchListener(new View.OnTouchListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onTouch(View v, MotionEvent event) {
v
.findViewById(R.id.row_content)
.getBackground()
.setHotspot(event.getX(), event.getY());
return(false);
}
});
}
这似乎有效。我不知道这是否是正式的正确答案,因为我没有看到任何来自Google的代码如何实现这一点(例如,搜索SDK样本的setHotspot()没有任何结果)。特别是,直接在后台调用setHotspot()会让我担心(我们应该首先调用mutate()吗?)。因此,想象一粒盐,一边长约15厘米,并采用这种实施方式。
答案 0 :(得分:0)
显示或动画时,显示动画可为用户提供视觉连续性 隐藏一组UI元素。该 ViewAnimationUtils.createCircularReveal()方法使您能够 动画剪裁圆圈以显示或隐藏视图。
使用此效果显示以前不可见的视图:
View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the final radius for the clipping circle
float finalRadius = (float) Math.hypot(cx, cy);
// create the animator for this view (the start radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
// make the view visible and start the animation
myView.setVisibility(View.VISIBLE);
anim.start();
使用此效果隐藏以前可见的视图:
// previously visible view
final View myView = findViewById(R.id.my_view);
// get the center for the clipping circle
int cx = myView.getWidth() / 2;
int cy = myView.getHeight() / 2;
// get the initial radius for the clipping circle
float initialRadius = (float) Math.hypot(cx, cy);
// create the animation (the final radius is zero)
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
// start the animation
anim.start();