2010-04-29 130 views
93

我想重疊兩個圖像在我的應用程序,但他們似乎崩潰在我的canvas.setBitmap()線。我究竟做錯了什麼?覆蓋android中的兩個圖像來設置圖像視圖

private void test() { 
    Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.t); 
    Bitmap mBitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.tt); 
    Bitmap bmOverlay = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig()); 
    Canvas canvas = new Canvas(); 
    canvas.setBitmap(bmOverlay); 
    canvas.drawBitmap(mBitmap, new Matrix(), null); 
    canvas.drawBitmap(mBitmap2, new Matrix(), null); 
    testimage.setImageBitmap(bmOverlay); 
} 
+0

能否使用FrameLayout裏爲好,像這樣: http://stackoverflow.com/a/11658554/586484 – Lysogen 2013-02-06 17:22:42

回答

228

您可以跳過複雜的Canvas操作並完全使用Drawables使用LayerDrawable完成此操作。您有以下兩種選擇之一:您可以選擇define it in XML然後簡單地設置圖像,也可以在代碼中動態配置LayerDrawable

解決方案#1(通過XML):

創建一個新的可繪製的XML文件,姑且稱之爲layer.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/t" /> 
    <item android:drawable="@drawable/tt" /> 
</layer-list> 

現在,使用設定的形象,繪製對象:

testimage.setImageDrawable(getResources().getDrawable(R.layout.layer)); 

解決方案#2(動態):

Resources r = getResources(); 
Drawable[] layers = new Drawable[2]; 
layers[0] = r.getDrawable(R.drawable.t); 
layers[1] = r.getDrawable(R.drawable.tt); 
LayerDrawable layerDrawable = new LayerDrawable(layers); 
testimage.setImageDrawable(layerDrawable); 

(我沒有測試過這個代碼,所以可能會出現錯誤,但是這個總體概要應該可以工作。)

+1

謝謝你,它的工作! 儘管有一個拼寫錯誤,以防其他人使用代碼: LayerDrawable layers2 = new LayerDrawable(layers); testimage.setImageDrawable(layers2); – John 2010-04-29 19:38:20

+5

對不起,你mustve編輯不久之後我抓住了代碼 – John 2010-04-29 19:52:12

+1

偉大的方式,以節省空間和重複使用的圖片。此外,您可以使用android:left,android:right,android:top和android:down來控制.xml文件中某個圖層的位置。 – zabawaba99 2012-10-24 03:44:05

8

確定只是讓你知道有一個程序叫做DroidDraw。它可以幫助您繪製對象並將它們放在另一個之上。我嘗試了您的解決方案,但是我在較小的圖像下使用了動畫,因此無法使用。但後來我試圖在一個相對佈局中放置一個圖像,這個佈局應該是在第一個圖像下,然後再繪製另一個圖像,這個圖像應該重疊並且一切都很好。所以RelativeLayout,DroidDraw和你很好去:)簡單,沒有任何種類的jiggery pockery :)這裏有一些雅代碼:

該徽標將在shazam背景圖片上。

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
android:id="@+id/widget30" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android" 
> 
<ImageView 
android:id="@+id/widget39" 
android:layout_width="219px" 
android:layout_height="225px" 
android:src="@drawable/shazam_bkgd" 
android:layout_centerVertical="true" 
android:layout_centerHorizontal="true" 
> 
</ImageView> 
<ImageView 
android:id="@+id/widget37" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:src="@drawable/shazam_logo" 
android:layout_centerVertical="true" 
android:layout_centerHorizontal="true" 
> 
</ImageView> 
</RelativeLayout> 
2

它有點晚了答案,但它涵蓋合併使用畢加索

從URL中的圖像

MergeImageView

import android.annotation.TargetApi; 
import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.BitmapFactory; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.os.AsyncTask; 
import android.os.Build; 
import android.util.AttributeSet; 
import android.util.SparseArray; 
import android.widget.ImageView; 
import com.squareup.picasso.Picasso; 

import java.io.IOException; 
import java.util.List; 

public class MergeImageView extends ImageView { 

    private SparseArray<Bitmap> bitmaps = new SparseArray<>(); 
    private Picasso picasso; 
    private final int DEFAULT_IMAGE_SIZE = 50; 
    private int MIN_IMAGE_SIZE = DEFAULT_IMAGE_SIZE; 
    private int MAX_WIDTH = DEFAULT_IMAGE_SIZE * 2, MAX_HEIGHT = DEFAULT_IMAGE_SIZE * 2; 
    private String picassoRequestTag = null; 

    public MergeImageView(Context context) { 
     super(context); 
    } 

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

    public MergeImageView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
    public MergeImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
     super(context, attrs, defStyleAttr, defStyleRes); 
    } 

    @Override 
    public boolean isInEditMode() { 
     return true; 
    } 

    public void clearResources() { 
     if (bitmaps != null) { 
      for (int i = 0; i < bitmaps.size(); i++) 
       bitmaps.get(i).recycle(); 
      bitmaps.clear(); 
     } 
     // cancel picasso requests 
     if (picasso != null && AppUtils.ifNotNullEmpty(picassoRequestTag)) 
      picasso.cancelTag(picassoRequestTag); 
     picasso = null; 
     bitmaps = null; 
    } 

    public void createMergedBitmap(Context context, List<String> imageUrls, String picassoTag) { 
     picasso = Picasso.with(context); 
     int count = imageUrls.size(); 
     picassoRequestTag = picassoTag; 

     boolean isEven = count % 2 == 0; 
     // if url size are not even make MIN_IMAGE_SIZE even 
     MIN_IMAGE_SIZE = DEFAULT_IMAGE_SIZE + (isEven ? count/2 : (count/2) + 1); 
     // set MAX_WIDTH and MAX_HEIGHT to twice of MIN_IMAGE_SIZE 
     MAX_WIDTH = MAX_HEIGHT = MIN_IMAGE_SIZE * 2; 
     // in case of odd urls increase MAX_HEIGHT 
     if (!isEven) MAX_HEIGHT = MAX_WIDTH + MIN_IMAGE_SIZE; 

     // create default bitmap 
     Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_wallpaper), 
       MIN_IMAGE_SIZE, MIN_IMAGE_SIZE, false); 

     // change default height (wrap_content) to MAX_HEIGHT 
     int height = Math.round(AppUtils.convertDpToPixel(MAX_HEIGHT, context)); 
     setMinimumHeight(height * 2); 

     // start AsyncTask 
     for (int index = 0; index < count; index++) { 
      // put default bitmap as a place holder 
      bitmaps.put(index, bitmap); 
      new PicassoLoadImage(index, imageUrls.get(index)).execute(); 
      // if you want parallel execution use 
      // new PicassoLoadImage(index, imageUrls.get(index)).(AsyncTask.THREAD_POOL_EXECUTOR); 
     } 
    } 

    private class PicassoLoadImage extends AsyncTask<String, Void, Bitmap> { 

     private int index = 0; 
     private String url; 

     PicassoLoadImage(int index, String url) { 
      this.index = index; 
      this.url = url; 
     } 

     @Override 
     protected Bitmap doInBackground(String... params) { 
      try { 
       // synchronous picasso call 
       return picasso.load(url).resize(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE).tag(picassoRequestTag).get(); 
      } catch (IOException e) { 
      } 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Bitmap output) { 
      super.onPostExecute(output); 
      if (output != null) 
       bitmaps.put(index, output); 

      // create canvas 
      Bitmap.Config conf = Bitmap.Config.RGB_565; 
      Bitmap canvasBitmap = Bitmap.createBitmap(MAX_WIDTH, MAX_HEIGHT, conf); 
      Canvas canvas = new Canvas(canvasBitmap); 
      canvas.drawColor(Color.WHITE); 

      // if height and width are equal we have even images 
      boolean isEven = MAX_HEIGHT == MAX_WIDTH; 
      int imageSize = bitmaps.size(); 
      int count = imageSize; 

      // we have odd images 
      if (!isEven) count = imageSize - 1; 
      for (int i = 0; i < count; i++) { 
       Bitmap bitmap = bitmaps.get(i); 
       canvas.drawBitmap(bitmap, bitmap.getWidth() * (i % 2), bitmap.getHeight() * (i/2), null); 
      } 
      // if images are not even set last image width to MAX_WIDTH 
      if (!isEven) { 
       Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmaps.get(count), MAX_WIDTH, MIN_IMAGE_SIZE, false); 
       canvas.drawBitmap(scaledBitmap, scaledBitmap.getWidth() * (count % 2), scaledBitmap.getHeight() * (count/2), null); 
      } 
      // set bitmap 
      setImageBitmap(canvasBitmap); 
     } 
    } 
} 

XML

<com.example.MergeImageView 
    android:id="@+id/iv_thumb" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" /> 

實施例

List<String> urls = new ArrayList<>(); 
String picassoTag = null; 
// add your urls 
((MergeImageView)findViewById(R.id.iv_thumb)). 
     createMergedBitmap(MainActivity.this, urls,picassoTag); 
3

可以使用下面的代碼來解決問題或download demo here

創建兩個函數來處理每個。

首先,畫布繪製並且圖像被繪製在從點彼此的頂部(0,0)

在點擊鏈接

public void buttonMerge(View view) { 

     Bitmap bigImage = BitmapFactory.decodeResource(getResources(), R.drawable.img1); 
     Bitmap smallImage = BitmapFactory.decodeResource(getResources(), R.drawable.img2); 
     Bitmap mergedImages = createSingleImageFromMultipleImages(bigImage, smallImage); 

     img.setImageBitmap(mergedImages); 
    } 

函數來創建的覆蓋。

private Bitmap createSingleImageFromMultipleImages(Bitmap firstImage, Bitmap secondImage){ 

    Bitmap result = Bitmap.createBitmap(firstImage.getWidth(), firstImage.getHeight(), firstImage.getConfig()); 
    Canvas canvas = new Canvas(result); 
    canvas.drawBitmap(firstImage, 0f, 0f, null); 
    canvas.drawBitmap(secondImage, 10, 10, null); 
    return result; 
}public void buttonClick(View view){ 

}

Read more