给button写了一个包装类,设置setWidth()和getWidth()方法,大多时候动画运行是正确的,但是当我连续运行几次之后就出错了,目的是把button的宽度从500px通过动画变成800px
运行几次后, 动画执行完成后button的宽度未设置为800, 如下图:
这是代码
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView textView;
private Button button;
private int clickTimes = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.click);
textView = (TextView) findViewById(R.id.tv_showWidth);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
performAnimate();
clickTimes ++;
ViewTreeObserver observer = button.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
textView.setText("The " + (clickTimes) + "th click" + "button's width:" + button.getWidth());
}
});
}
});
}
private void performAnimate() {
ViewWrapper viewWrapper = new ViewWrapper(button);
ObjectAnimator.ofInt(viewWrapper, "width", 500, 800).setDuration(1000).start();
}
private static class ViewWrapper {
private View mTarget;
public ViewWrapper(View mTarget) {
this.mTarget = mTarget;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout(); //长度宽度改变需要调用此方法进行view的测量、布局和绘制
Log.d(TAG, "setWidth: " + mTarget.getWidth());
}
}
}
layout 文件
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.circleview.MainActivity">
<Button
android:id="@+id/click"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:text="Property Animation" />
<TextView
android:id="@+id/tv_showWidth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="please click the button" />
</LinearLayout>
问题就出在
performAnimate()
的ObjectAnimator.ofInt(...)
调用, 由于ObjectAnimator
本身实现的问题, 它会把 target 存为WeakReference
类型. 关键代码如下:由于这个原因, 如果不保持对象实例, 那么就很有可能会被gc回收掉. 因此,
ViewWrapper
应该作为类成员变量, 以防被回收.另外, 如果不停地按, 就会不停地产生多个动画请求. 而上次以及上上次(上...上次)未执行完成的动画会影响当次的动画动作. 如果要达到预期的要求, 就应该把上次的动画请求取消掉. 代码如下: