2013-08-14 67 views
7

Tôi đang vẽ một ảnh bitmap được chia tỷ lệ lên canvas và muốn làm mờ hình ảnh của tôi vào một thời điểm cụ thể.Android - Làm mờ hình ảnh bitmap trên canvas

Về cơ bản, khi hình ảnh nhân vật của tôi đi qua một phần nhất định của canvas, tôi yêu cầu hình ảnh ký tự từ từ biến mất (3 giây), trước khi trang tự động chuyển hướng đến lớp java tiếp theo.

Hiện tại, hình ảnh của tôi chỉ chuyển hướng đến lớp java mới, vui lòng xem bên dưới một số mã về cách tôi tạo hình ảnh của mình.

Resources res = getResources(); 
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, res.getDisplayMetrics()); 
imgSpacing = (int) px/2; 
int size = (int) ((PhoneWidth/5) - px); 

chrImg = BitmapFactory.decodeResource(getResources(), R.drawable.character); 
chrImg = Bitmap.createScaledBitmap(chrImg, size, size, true); 

Sau đó, trong onDraw vải:

if(indexX == mazeFinishX && indexY == mazeFinishY) 
{ 
    canvas.drawBitmap(finish, j * totalCellWidth, i * totalCellHeight, null); 
    // As soon as the character moves over this square they are automatically re-directed to new page 
    // This is where I want to fade the character image out before the re-direct 
} 

tôi đã xem xét trực tuyến, tuy nhiên không thể hoàn toàn làm việc ra làm thế nào để có được những phai làm việc cho hình ảnh drawable của tôi lấy từ các trò chơi nguồn lực của tôi thư mục drawable. Cảm ơn

Trả lời

8

Nếu bạn nghĩ rằng có khả năng bạn sẽ muốn thay đổi hoạt ảnh mờ dần xuống đường, chẳng hạn như chia tỷ lệ và/hoặc xoay, thì bạn nên sử dụng XML hoạt ảnh.

Nhưng chỉ để làm mờ nhanh bitmap, bạn có thể liên tục đăng thông báo vô hiệu hóa trễ.Có thể bạn muốn giới hạn khu vực bị vô hiệu của bạn để chỉ nơi bitmap nhân vật của bạn là:

private static final int FADE_MILLISECONDS = 3000; // 3 second fade effect 
private static final int FADE_STEP = 120;   // 120ms refresh 

// Calculate our alpha step from our fade parameters 
private static final int ALPHA_STEP = 255/(FADE_MILLISECONDS/FADE_STEP); 

// Initializes the alpha to 255 
private Paint alphaPaint = new Paint(); 

// Need to keep track of the current alpha value 
private int currentAlpha = 255; 

@Override 
protected void onDraw(Canvas canvas) { 
    ... 
    if(indexX == mazeFinishX && indexY == mazeFinishY) { 

     // Drawing your wormhole? 
     int x = j * totalCellWidth; 
     int y = i * totalCellHeight; 
     canvas.drawBitmap(finish, x, y, null); 

     if (currentAlpha > 0) { 

      // Draw your character at the current alpha value 
      canvas.drawBitmap(chrImg, x, y, alphaPaint); 

      // Update your alpha by a step 
      alphaPaint.setAlpha(currentAlpha); 
      currentAlpha -= ALPHA_STEP; 

      // Assuming you hold on to the size from your createScaledBitmap call 
      postInvalidateDelayed(FADE_STEP, x, y, x + size, y + size); 

     } else { 
      // No character draw, just reset your alpha paint 
      currentAlpha = 255; 
      alphaPaint.setAlpha(currentAlpha); 

      // Now do your redirect 
     } 
    } 
    ... 
} 

tôi khuyên bạn nên đặt hằng FADE_MILLISECONDS và FADE_STEP vào res/integers.xml chỉ vì vậy họ không được mã hóa cứng.

+0

Tôi đã thực hiện mã trên của bạn và mờ dần hoạt động chính xác. Tuy nhiên vấn đề ở đây là thực tế là việc tái trực tiếp của tôi không hoạt động. Nó truy cập các chức năng với mã chuyển hướng, tuy nhiên dường như bỏ qua nó, bất kỳ ý tưởng? –

+0

Tôi đã thêm một trường "currentAlpha", sử dụng setAlpha/getAlpha có thể không hoạt động với bất kỳ thứ gì khác ngoài bước alpha 1. –

1
 if(indexX == mazeFinishX && indexY == mazeFinishY) 
     { 
      canvas.drawBitmap(finish, j * totalCellWidth, i * totalCellHeight, null); 
      // As soon as the character moves over this square they are automtically re-directs to new page 
      new CountDownTimer(0500, 1000) { 
       @Override 
       public void onTick(long millisUntilFinished) {} 
       @Override 
       public void onFinish() { 
Paint paint = new Paint(); 
paint.setAlpha(25); 
canvas.drawBitmap(chrImg, 0, 0, paint); 
       } 
      }.start(); 
      new CountDownTimer(0500, 1000) { 
       @Override 
       public void onTick(long millisUntilFinished) {} 
       @Override 
       public void onFinish() { 
Paint paint = new Paint(); 
paint.setAlpha(45); 
canvas.drawBitmap(chrImg, 0, 0, paint);    } 
      }.start(); 
      new CountDownTimer(0500, 1000) { 
       @Override 
       public void onTick(long millisUntilFinished) {} 
       @Override 
       public void onFinish() { 
Paint paint = new Paint(); 
paint.setAlpha(70); 
canvas.drawBitmap(chrImg, 0, 0, paint);    } 
      }.start(); 
      new CountDownTimer(0500, 1000) { 
       @Override 
       public void onTick(long millisUntilFinished) {} 
       @Override 
       public void onFinish() { 
Paint paint = new Paint(); 
paint.setAlpha(100); 
canvas.drawBitmap(chrImg, 0, 0, paint);    } 
      }.start(); 
      // This is where I want to fade the cahracter image out before the re-direct 
      new CountDownTimer(3000, 1000) { 

      @Override 
      public void onTick(long millisUntilFinished) { 
       // TODO Auto-generated method stub 

      } 

      @Override 
      public void onFinish() { 
       // TODO Auto-generated method stub 

        Intent i = new Intent(currentclass.this, nextClass.class); 
        startActivity(i); 
      } 
     }.start(); 

    } 

điều này sẽ làm cho bitmap của bạn trở nên trong suốt (alpha sẽ là 100) .. và sau đó chuyển hướng đến lớp tiếp theo sau 3 giây.

Cập nhật: cho bitmap bạn không thể sử dụng .setAlpha vì vậy chúng tôi phải sử dụng một lớp sơn, vì vậy chúng tôi tạo ra một lớp sơn mới mỗi lần sau đó đặt bitmap với sơn. nhưng nếu bạn có một imageView bạn có thể sử dụng .setalpha

+0

Điều này làm việc trong việc trì hoãn chuyển hướng, tuy nhiên tôi muốn làm cho nó để hình ảnh từ từ biến mất. Về cơ bản, tôi có một hình ảnh lỗ sâu và muốn hình ảnh nhân vật biến mất vào đó thông qua một số loại hình hoạt hình (tôi đã suy nghĩ mờ dần hình ảnh đi). –

+0

Chỉ cần thử mã của bạn, tuy nhiên nhận ra rằng vì nó là một bitmap từ các tài nguyên có thể drawable, bạn không thể sử dụng setAlpha. Có cách nào khác không, vui lòng xem mã gốc của tôi để nhân rộng hình ảnh. –

+0

Tôi đã cập nhật mã, hãy kiểm tra mã ngay bây giờ. –

3

Cách tốt nhất để tôi giải thích điều này là cung cấp một ví dụ xem tùy chỉnh đầy đủ mà bạn có thể kéo các phần từ đó bạn cần. Dưới đây là một khung nhìn hoàn thành điều này.

public class CharacterView extends View { 

    private Paint mCharacterPaint; 
    private Bitmap mCharacterBitmap; 
    private Transformation mTransformation; 
    private AlphaAnimation mFadeOut; 

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

    public CharacterView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(context); 
    } 

    public CharacterView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(context); 
    } 

    private void init(Context context) { 
     //This would be your character image instead 
     mCharacterBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); 

     //We need a paint to efficiently modify the alpha 
     mCharacterPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     //This is needed to house the current value during the animation 
     mTransformation = new Transformation(); 
     //Construct an animation that will do all the timing math for you 
     mFadeOut = new AlphaAnimation(1f, 0f); 
     mFadeOut.setDuration(500); 
     //Use a listener to trigger the end action 
     mFadeOut.setAnimationListener(new Animation.AnimationListener() { 
      @Override 
      public void onAnimationStart(Animation animation) { } 

      @Override 
      public void onAnimationEnd(Animation animation) { 
       //Trigger your action to change screens here. 
      } 

      @Override 
      public void onAnimationRepeat(Animation animation) { } 
     }); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_DOWN) { 
      //In this example, touching the view triggers the animation 
      // your code would run this sequence when the character reaches the 
      // appropriate coordinates (P.S. I would not advocate putting this code 
      // inside of onDraw() 
      mFadeOut.start(); 
      mFadeOut.getTransformation(System.currentTimeMillis(), mTransformation); 
      invalidate(); 
     } 
     return true; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     //...existing drawing code... 

     canvas.drawBitmap(mCharacterBitmap, 0, 0, mCharacterPaint); 
     if (mFadeOut.hasStarted() && !mFadeOut.hasEnded()) { 
      mFadeOut.getTransformation(System.currentTimeMillis(), mTransformation); 
      //Keep drawing until we are done 
      mCharacterPaint.setAlpha((int)(255 * mTransformation.getAlpha())); 
      invalidate(); 
     } else { 
      //Reset the alpha if animation is canceled 
      mCharacterPaint.setAlpha(255); 
     } 
    } 
} 

Cách hiệu quả nhất để tự động thay đổi tính minh bạch của những gì bạn vẽ là để áp dụng nó sử dụng một Paint vẽ để Canvas của bạn. Bạn sẽ cần phải liên tục invalidate() chế độ xem với mỗi lần chuyển đổi khung hình để hiển thị hoạt ảnh cho đến khi ký tự biến mất. Ví dụ này sử dụng đối tượng Animation và đối tượng Transformation để xử lý tất cả toán thời gian để làm cho hoạt ảnh thực sự trông đẹp.

Gợi ý ở đây là bạn bắt đầu hoạt ảnh thông qua một số kích hoạt bên ngoài (tôi sẽ không khuyên bạn nên kiểm tra khi nào mờ dần trong onDraw(), có lẽ tốt hơn ở vị trí các vị trí ký tự đó được cập nhật. vì đơn giản vì, tôi bắt đầu này khi chế độ xem để chạm vào.

kích hoạt này bắt đầu hoạt hình và nhận được giá trị chuyển đổi ban đầu, sau đó invalidate() gây ra một mới onDraw(). trong khi các hình ảnh động đang chạy, onDraw() được lặp lại do invalidate() và mỗi lần lặp lại, alpha trên sơn giảm nhẹ

Khi hoạt ảnh kết thúc, nó sẽ gọi số AnimationListener cho bạn, vì vậy bạn có thể kích hoạt quá trình chuyển đổi màn hình bên trong của onAnimationEnd().

+0

Bạn chỉ nên vô hiệu hóa khu vực nơi nhân vật đang được vẽ lại. –

+0

Đây có thể là một tối ưu hóa tốt đẹp nếu chế độ xem tổng thể lớn. Mặc dù trong nhiều trường hợp phổ biến (chẳng hạn như với khả năng tăng tốc phần cứng được kích hoạt), các đường bẩn bị bỏ qua; vì vậy nó thường không có giá trị nỗ lực của bao gồm trừ khi đảm bảo hiệu suất. – Devunwired

+0

Câu trả lời này từ một trong những nhà phát triển Android dường như mâu thuẫn với xác nhận của bạn rằng tăng tốc phần cứng bỏ qua các vùng bẩn: http://stackoverflow.com/questions/7233830/partial-invalidation-in-custom-android-view-with-hardware-acceleration –