首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Canvas 繪圖動畫實現:在 onDraw 中動態更新 Bitmap 座標實現移動效果

     編輯:程式設計綜合問答

需求:在自定義 View 的 onDraw() 中繪製兩張圖片,並實現從屏幕底部移動到頂部的動畫效果。

核心原理:狀態變量 + 重繪循環

  1. 用成員變量記錄圖片 Y 座標(float imgY1, imgY2)。
  2. 在 onDraw() 中使用變量繪製:canvas.drawBitmap(bmp, x, imgY, paint)。
  3. 啟動動畫線程/ValueAnimator,周期性更新座標並調用 postInvalidate() 觸發重繪。

完整實現代碼

public class MovingImageView extends View {
    private Bitmap bitmap1, bitmap2;
    private float y1, y2;
    private ValueAnimator animator;

    public MovingImageView(Context context) {
        super(context);
        init();
    }

    private void init() {
        bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.btnpre);
        bitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.btnpre);
        
        // 初始位置:屏幕底部(需在 onSizeChanged 獲取高度後設置)
        y1 = y2 = 0; // 稍後在 onSizeChanged 修正
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        y1 = y2 = h; // 從底部開始
        startAnimation(h);
    }

    private void startAnimation(int screenHeight) {
        animator = ValueAnimator.ofFloat(screenHeight, -bitmap1.getHeight());
        animator.setDuration(3000);
        animator.setInterpolator(new LinearInterpolator()); // 或 AccelerateDecelerateInterpolator
        animator.addUpdateListener(animation -> {
            float animatedY = (float) animation.getAnimatedValue();
            y1 = animatedY;
            y2 = animatedY + 200; // 錯開位置
            postInvalidate(); // 關鍵:請求重繪
        });
        animator.start();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.CYAN);
        canvas.drawBitmap(bitmap1, 10, y1, null);
        canvas.drawBitmap(bitmap2, 100, y2, null);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (animator != null) animator.cancel();
        bitmap1.recycle(); bitmap2.recycle();
    }
}

插值器選擇對比

插值器效果適用場景
LinearInterpolator勻速簡單移動
AccelerateDecelerateInterpolator漸入漸出自然過渡(推薦)
OvershootInterpolator超出回彈彈性感
PathInterpolator自定義貝塞爾曲線複雜軌跡

性能優化提醒

  • Bitmap 複用:在構造函數/onSizeChanged 中一次性解碼,切勿在 onDraw 中解碼。
  • 避免分配對象:onDraw 盡量不 new 對象(Paint、Rect 等提升為成員)。
  • 硬件加速:複雜動畫考慮 setLayerType(LAYER_TYPE_HARDWARE, null)。

掌握「狀態驅動重繪」模式,實現流暢自定義動畫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved