0

壁畫內置支持圓形圖像和圓角,但其他形狀如鑽石或平行四邊形等呢?Android壁畫:繪製不同種類的圖像形狀

通過使用BitmapShader的自定義可繪製對標準ImageView執行操作很簡單。例如,下面的自定義繪製對象接收圖像的位圖和邊坡高度作出的ImageView的樣子這樣的畫面:

enter image description here

public class MaskDrawable extends Drawable { 
    private Paint mPaint; 
    private Path mPath; 
    private int mSlopeHeight; 

    public MaskDrawable(Bitmap bitmap, int slopeHeight) { 
     BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 
     mPaint = new Paint(); 
     mPaint.setAntiAlias(true); 
     mPaint.setShader(shader); 
     mSlopeHeight = slopeHeight; 

     mPath = new Path(); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     Rect bounds = getBounds(); 

     mPath.moveTo(0, 0); 
     mPath.lineTo(0, bounds.bottom); 
     mPath.lineTo(bounds.right, bounds.bottom - mSlopeHeight); 
     mPath.lineTo(bounds.right, 0); 
     canvas.drawPath(mPath, mPaint); 
    } 

要做到這一點與壁畫,我需要的圖像的位圖,但我不知道該怎麼做。我讀過,我可以直接從ImagePipeline獲取位圖,但是它有很多缺點。在一種情況下,返回的位圖是短暫的,不應該用於在屏幕上繪製,而在另一種情況下,我會得到一個CloseableReference,我需要在某些不明確的位置釋放它。我看到的淨爲止類似於此代碼獲取位圖:

ImagePipeline imagePipeline = Fresco.getImagePipeline(); 

     ImageRequest imageRequest = ImageRequestBuilder 
       .newBuilderWithSource(uri) 
       .setRequestPriority(Priority.HIGH) 
       .setLowestPermittedRequestLevel(ImageRequest.RequestLevel.FULL_FETCH) 
       .build(); 

     DataSource<CloseableReference<CloseableBitmap>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, getContext()); 

     DataSubscriber<CloseableReference<CloseableBitmap>> dataSubscriber = 
       new BaseDataSubscriber<CloseableReference<CloseableBitmap>>() { 
        @Override 
        protected void onNewResultImpl(DataSource<CloseableReference<CloseableBitmap>> dataSource) { 
         mBitmapRef = dataSource.getResult(); 
         // Get the bitmap here and use it in my custom drawable? 
        } 

        @Override 
        protected void onFailureImpl(DataSource<CloseableReference<CloseableBitmap>> dataSource) { 
        } 
       }; 

     dataSource.subscribe(dataSubscriber, UiThreadImmediateExecutorService.getInstance()); 

我還沒有試過,但並想知道如果有人能提供有效的解決方案,而不是比特和字節我已經聚集到了很遠的地方。它必須正確完成,否則我可以輕鬆地泄漏內存,從而擺脫了首先使用Fresco的整個想法。

回答

-1

您不需要也不建議在處理視圖時使用imagepipeline。

一種方法是在後處理器中管理這些位圖。您需要重寫處理方法,使用相同的BitmapShader,繪圖,畫布實現,使用PlatformBitmapFactory createBitmap創建可清除的位圖CloseableReference,並最終在完成位圖時關閉參考。

見多 http://frescolib.org/docs/modifying-image.html

編輯

下面是我想出了從王潔獲得幫助後的最終實現。下面的代碼片段將圖像放置在問題中呈現的形狀中。

mSimpleDraweeView = (SimpleDraweeView) findViewById(R.id.shaped_picture); 
final int slopeHeight = 100; 

Postprocessor maskProcessor = new BasePostprocessor() { 
    @Override 
    public CloseableReference<Bitmap> process(Bitmap sourceBitmap, PlatformBitmapFactory bitmapFactory) { 
     // Get the size of the downloaded bitmap 
     final int width = sourceBitmap.getWidth(); 
     final int height = sourceBitmap.getHeight(); 

     // Create a new bitmap and use it to draw the shape that we want. 
     CloseableReference<Bitmap> bitmapRef = bitmapFactory.createBitmap(width, height); 
     try { 
      Bitmap destBitmap = bitmapRef.get(); 

      // Create canvas using the new bitmap we created earlier 
      Canvas canvas = new Canvas(destBitmap); 

      // Set up the Paint we will use for filling in the shape 
      // BitmapShader will fill the shape with the downloaded bitmap 
      BitmapShader shader = new BitmapShader(sourceBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 
      Paint paint = new Paint(); 
      paint.setAntiAlias(true); 
      paint.setShader(shader); 

      // Set up the actual shape. Modify this part with any shape you want to have. 
      Path path = new Path(); 
      path.moveTo(0, 0); 
      path.lineTo(0, height); 
      path.lineTo(width, height - slopeHeight); 
      path.lineTo(width, 0); 

      // Draw the shape and fill it with the paint 
      canvas.drawPath(path, paint); 

      return CloseableReference.cloneOrNull(bitmapRef); 
     } 
     finally { 
      CloseableReference.closeSafely(bitmapRef); 
     } 
    } 
}; 

ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri) 
     .setPostprocessor(maskProcessor) 
     .build(); 

DraweeController controller = Fresco.newDraweeControllerBuilder() 
     .setImageRequest(request) 
     .setOldController(mSimpleDraweeView.getController()) 
     .build(); 

mSimpleDraweeView.setController(controller); 
+0

我已經更新了答案,讓具體的解決方案實現,以防其他人碰到這個問題。 –