如果自定义视图具有多种形状,是否可以仅对其中一种进行动画处理? 例如:对于我的一个应用程序,在自定义视图上绘制了2个圆,一个内圆和另一个外圆。当我尝试使用比例动画制作动画时,我看到两个圆圈都被动画化了,因为我只需要其中一个就可以。 我想到的解决方案之一是拥有多个自定义视图。 但是不确定这是否是正确的方法。 有其他更好的解决方案吗?
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.test.customanimation.CustomView
android:id="@+id/circular_progress"
android:layout_width="400dp"
android:layout_height="400dp"
android:layout_gravity="center"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/scale_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Scale Up"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<Button
android:id="@+id/scale_down"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="Scale Down"/>
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private CustomView mCustomView;
private Button mScaleUpBtn;
private Button mScaleDownBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCustomView = findViewById(R.id.circular_progress);
mScaleUpBtn = findViewById(R.id.scale_up);
mScaleUpBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCustomView.scaleUpAnimation(5000);
}
});
mScaleDownBtn = findViewById(R.id.scale_down);
mScaleDownBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCustomView.scaleDownAnimation(5000);
}
});
}
}
CustomView.java
public class CustomView extends View {
private Paint OuterCirclePaint,InnerCirclePaint;
float mCircleX,mCircleY,mInnerCircleRadius,mOuterCircleRadius;
public CustomView(Context context) {
super(context);
init();
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomView(Context context, @Nullable AttributeSet attrs, int
defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public CustomView(Context context, @Nullable AttributeSet attrs, int
defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init(){
OuterCirclePaint = new Paint();
OuterCirclePaint.setColor(Color.GREEN);
OuterCirclePaint.setStrokeWidth(20);
OuterCirclePaint.setStyle(Paint.Style.STROKE);
InnerCirclePaint = new Paint();
InnerCirclePaint.setColor(Color.BLACK);
InnerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
mCircleX = getWidth()/2;
mCircleY = getHeight()/2;
if(mCircleX < mCircleY) {
mInnerCircleRadius = (getWidth() / 2) - 100;
mOuterCircleRadius = (getWidth() / 2) - 40;
}
else {
mInnerCircleRadius = (getHeight() / 2) - 100;
mOuterCircleRadius= (getHeight() / 2) - 40;
}
canvas.drawCircle(mCircleX,mCircleY,mOuterCircleRadius,OuterCirclePaint);
canvas.drawCircle(mCircleX,mCircleY,mInnerCircleRadius,InnerCirclePaint);
}
public void scaleDownAnimation(int duration){
ScaleAnimation fade_in = new ScaleAnimation(1.0f,0.5f,1.0f,0.5f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
fade_in.setDuration(duration);
fade_in.setFillAfter(true);
this.startAnimation(fade_in);
}
public void scaleUpAnimation(int duration){
ScaleAnimation fade_out = new ScaleAnimation(0.5f,1.0f,0.5f,1.0f,
Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
fade_out.setDuration(duration);
fade_out.setFillAfter(true);
this.startAnimation(fade_out);
}
}
答案 0 :(得分:1)
您已经覆盖onDraw()
,并提供了自己的方法来处理动画。 IMO这种方法最适合性能,因此我会保持这种方式,只切换到另一个动画框架,即Property Animations
为了在动画过程中仅重绘内圆,我建议对动画使用ValueAnimator
和ValueAnimator.AnimatorUpdateListener
。
让我们为CustomView
private float scaleFactor = 1f;
private ValueAnimator scaleUpAnimator;
private ValueAnimator scaleDownAnimator;
private ValueAnimator.AnimatorUpdateListener updateListener;
按如下所示初始化它们
private void initAnimations() {
scaleUpAnimator = ValueAnimator.ofFloat(0.5f, 1.0f);
scaleDownAnimator = ValueAnimator.ofFloat(1.0f, 0.5f);
updateListener = new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
scaleFactor = (float)animation.getAnimatedValue();
CustomView.this.invalidate();
}
};
scaleUpAnimator.addUpdateListener(updateListener);
scaleDownAnimator.addUpdateListener(updateListener);
}
更改onDraw()
内圈的线
canvas.drawCircle(mCircleX, mCircleY, mInnerCircleRadius * scaleFactor, innerCirclePaint);
...并开始这样的动画
public void scaleDownAnimation(int duration){
scaleDownAnimator.setDuration(duration);
scaleDownAnimator.start();
}
public void scaleUpAnimation(int duration){
scaleUpAnimator.setDuration(duration);
scaleUpAnimator.start();
}