Path 上的 ObjectAnimator 不适用于 Marshmallow?
ObjectAnimator on Path not working on Marshmallow?
ObjectAnimator.ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)
似乎在 API 21 中有效,但在 23 中无效?
简单复制:这是 activity 和布局。尝试长按文本视图,两个级别都可以。但是,只需点击视图:21 有效但 23 无效。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View hello = findViewById(R.id.hello);
final Path p = new Path();
p.addCircle(-200, 0, 100, Path.Direction.CW);
hello.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(hello, "translationX", "translationY", p);
a.setDuration(1000);
a.start();
}
});
hello.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(hello, "scaleX", 2);
a.setDuration(1000);
a.start();
return true;
}
});
}
}
--
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="letstwinkle.com.pathtest.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="63dp"
android:layout_marginTop="210dp"
android:id="@+id/hello"
android:background="#880033"/>
</RelativeLayout>
这可能与 6 月份报告的这个错误相同。 https://code.google.com/p/android/issues/detail?id=212776
作为变通方法,您可以使用带有自定义 AnimatorUpdateListener
的 ValueAnimator
。
首先,您的 Path
需要一个 PathMeasure
。这将使您能够访问特定距离(0 <= 距离 <= 路径长度)的路径长度和路径坐标等数据。
Path p = new Path();
p.addCircle(-200, 0, 100, Path.Direction.CW);
PathMeasure pathMeasure = new PathMeasure(p, true);
然后将 ValueAnimator
设置为从 0 到路径长度的动画。
final ValueAnimator a = ValueAnimator.ofFloat(0,pathMeasure.getLength());
a.setDuration(1000);
接下来,您添加一个 AnimatorUpdateListener
来实际操作 View
。我将首先展示如何添加它:
MyAnimatorUpdateListener myListener = new MyAnimatorUpdateListener(hello, pathMeasure);
a.addUpdateListener(myListener);
继续使用 OnClickListener:
hello.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
a.start();
}
});
请注意,我更改了代码并在 OnClickListener
之外声明/初始化了 ValueAnimator
以获得更好的性能:这样,每次单击时都不会重新创建它TextView
这样垃圾收集器就不会那么忙了:)。
最后,AnimatorUpdateListener
代码:
class MyAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener
{
private View view;
private PathMeasure pathMeasure;
private float[] coordinates = new float[2];
public MyAnimatorUpdateListener(View view, PathMeasure pathMeasure)
{
this.view = view;
this.pathMeasure = pathMeasure;
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float distance = (float) animation.getAnimatedValue();
pathMeasure.getPosTan(distance, coordinates, null);
view.setTranslationX(coordinates[0]);
view.setTranslationY(coordinates[1]);
}
}
ObjectAnimator.ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)
似乎在 API 21 中有效,但在 23 中无效?
简单复制:这是 activity 和布局。尝试长按文本视图,两个级别都可以。但是,只需点击视图:21 有效但 23 无效。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View hello = findViewById(R.id.hello);
final Path p = new Path();
p.addCircle(-200, 0, 100, Path.Direction.CW);
hello.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(hello, "translationX", "translationY", p);
a.setDuration(1000);
a.start();
}
});
hello.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ObjectAnimator a = ObjectAnimator.ofFloat(hello, "scaleX", 2);
a.setDuration(1000);
a.start();
return true;
}
});
}
}
--
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="letstwinkle.com.pathtest.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginEnd="63dp"
android:layout_marginTop="210dp"
android:id="@+id/hello"
android:background="#880033"/>
</RelativeLayout>
这可能与 6 月份报告的这个错误相同。 https://code.google.com/p/android/issues/detail?id=212776
作为变通方法,您可以使用带有自定义 AnimatorUpdateListener
的 ValueAnimator
。
首先,您的 Path
需要一个 PathMeasure
。这将使您能够访问特定距离(0 <= 距离 <= 路径长度)的路径长度和路径坐标等数据。
Path p = new Path();
p.addCircle(-200, 0, 100, Path.Direction.CW);
PathMeasure pathMeasure = new PathMeasure(p, true);
然后将 ValueAnimator
设置为从 0 到路径长度的动画。
final ValueAnimator a = ValueAnimator.ofFloat(0,pathMeasure.getLength());
a.setDuration(1000);
接下来,您添加一个 AnimatorUpdateListener
来实际操作 View
。我将首先展示如何添加它:
MyAnimatorUpdateListener myListener = new MyAnimatorUpdateListener(hello, pathMeasure);
a.addUpdateListener(myListener);
继续使用 OnClickListener:
hello.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
a.start();
}
});
请注意,我更改了代码并在 OnClickListener
之外声明/初始化了 ValueAnimator
以获得更好的性能:这样,每次单击时都不会重新创建它TextView
这样垃圾收集器就不会那么忙了:)。
最后,AnimatorUpdateListener
代码:
class MyAnimatorUpdateListener implements ValueAnimator.AnimatorUpdateListener
{
private View view;
private PathMeasure pathMeasure;
private float[] coordinates = new float[2];
public MyAnimatorUpdateListener(View view, PathMeasure pathMeasure)
{
this.view = view;
this.pathMeasure = pathMeasure;
}
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float distance = (float) animation.getAnimatedValue();
pathMeasure.getPosTan(distance, coordinates, null);
view.setTranslationX(coordinates[0]);
view.setTranslationY(coordinates[1]);
}
}