给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
자체의 구현 문제로 인해 대상을WeakReference
유형으로 저장하게 됩니다.이 때문에 객체 인스턴스가 유지되지 않으면 gc에 의해 재활용될 가능성이 높습니다. 따라서
또한 계속 누르면 여러 애니메이션 요청이 계속해서 생성됩니다. 지난 번과 마지막 번(...마지막)에서 완료되지 않은 애니메이션이 현재 애니메이션 작업에 영향을 미칩니다. 예상 요구 사항을 충족하려면 마지막 애니메이션 요청을 취소해야 합니다. 코드는 다음과 같습니다.ViewWrapper
을 클래스 멤버 변수로 사용하여 재활용을 방지해야 합니다.으아악