2009-08-21 44 views
45

Tôi đang cố gắng tải một bitmap trong Android mà tôi muốn lát. Tôi hiện đang sử dụng sau đây trong quan điểm của tôi để hiển thị một bitmap:Bitmap bitmap của Android

canvas.drawBitmap(bitmap, srcRect, destRect, null) 

tôi về cơ bản muốn sử dụng bitmap này làm hình nền trong ứng dụng của tôi và muốn lặp lại bitmap trong cả X và Y hướng .

Tôi đã nhìn thấy hằng số TileMode.REPEAT cho lớp BitmapShader nhưng tôi không chắc chắn nếu điều này được sử dụng để lặp lại bitmap thực tế hoặc được sử dụng để áp dụng bộ lọc cho bitmap.

+0

Bất kỳ ai biết làm thế nào để làm điều này trong mã java mà không cần sử dụng xml? – endryha

Trả lời

123

Bạn sẽ làm điều này trong xml thay vì mã java. Tôi đã không cố gắng này bản thân mình nhưng tôi đã tìm thấy ví dụ này.

<xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
android:id="@+id/MainLayout" 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:orientation="vertical" 
android:background="@drawable/backrepeat" 
> 

sau đó trong một xml gọi backrepeat.xml

<bitmap xmlns:android="http://schemas.android.com/apk/res/android" 
    android:src="@drawable/back" 
    android:tileMode="repeat" /> 

reference

+2

chỉ để thêm, backrepeat.xml đi trong thư mục "drawable" –

+2

Điều này sẽ không làm việc để vẽ một canvas ... – stealthcopter

+0

Có thể là pedantic ở đây nhưng dòng đầu tiên nên đọc - Neil

15

Các backrepeat.xml trên là lỗi

<bitmap 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:src="@drawable/tile" 
    android:tileMode="repeat" 
    android:dither="true" /> 
+17

Tại sao nó lỗi và cách sửa lỗi này? –

+0

Điều này thêm: android: dither = "true", không có gì nếu ô không hoạt động tốt để bắt đầu. –

34

đặn ra phiên bản mã:

BitmapDrawable TileMe = new BitmapDrawable(MyBitmap); 
    TileMe.setTileModeX(Shader.TileMode.REPEAT); 
    TileMe.setTileModeY(Shader.TileMode.REPEAT); 

    ImageView Item = new ImageView(this); 
    Item.setBackgroundDrawable(TileMe); 

Sau đó, nếu bạn có một drawable để gạch, điều này có thể được sử dụng thay để làm cho BitmapDrawable:

BitmapDrawable TileMe = new BitmapDrawable(BitmapFactory.decodeResource(getResources(), R.drawable.tile)); 
+0

Điều đó hoạt động tốt, nhưng làm thế nào bạn sẽ lặp lại nó theo chiều dọc? Tôi đã thử loại bỏ setTileModeX, nhưng sau đó nó thậm chí không làm việc cả. –

+0

@WilliamL. Odd. [Docs] (http://developer.android.com/reference/android/graphics/drawable/BitmapDrawable.html#setTileModeX (android.graphics.Shader.TileMode)) dường như nói rằng nó chỉ hoạt động với một trong số chúng . Đoán tốt nhất là thử ['Shader.TileMode.CLAMP'] (http://developer.android.com/reference/android/graphics/Shader.TileMode.html) và xem điều gì xảy ra, sau đó. – Izkata

+0

Nó hoạt động nếu tôi lặp lại nó theo chiều ngang, nhưng không chỉ theo chiều dọc. Và CLAMP thực hiện điều tương tự như chưa đặt chế độ xếp kề ở vị trí đầu tiên. –

5

Dường như một số người quan tâm đến việc này trong View, ở phương pháp OnDraw. Các mã sau đây đã làm việc cho tôi:

bgTile = BitmapFactory.decodeResource(context.getResources(), R.drawable.bg_tile); 

float left = 0, top = 0; 
float bgTileWidth = bgTile.getWidth(); 
float bgTileHeight = bgTile.getHeight(); 

while (left < screenWidth) { 
    while (top < screenHeight) { 
     canvas.drawBitmap(bgTile, left, top, null); 
     top += bgTileHeight; 
    } 
    left += bgTileWidth; 
    top = 0; 
} 
+0

Nó sẽ lấp đầy tất cả các khu vực. Ô cuối cùng có thể không hoàn thành, không gian bên phải/dưới cùng của màn hình sẽ vẫn được vẽ. – kgiannakakis

+0

Tôi chỉ sử dụng phần này cho một đoạn vải của tôi chứ không phải tất cả, vì vậy rõ ràng là bạn sẽ bị thu hút thêm sau đó chiều rộng và chiều cao không chia hết cho hình ảnh. Tôi đã xóa nhận xét của mình vì nhận xét đó không liên quan đến câu hỏi. Lấy làm tiếc! – stealthcopter

+0

Trong trường hợp này, bạn sẽ sử dụng BitmapDrawable.setBounds và BitmapDrawable.draw (Canvas) – tactoth

4
<xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    android:id="@+id/MainLayout" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" 
    android:background="@drawable/back" 
    android:tileMode="repeat" 
> 

này làm việc tốt cho tôi. Tôi không phải tạo bitmap một cách riêng biệt. Tôi đã sử dụng thuộc tính tileMode trong bố cục.

+0

Cảm ơn, tôi thấy đây là phương pháp dễ nhất. – patrickandroid

0

Nếu bạn muốn lặp lại nền theo chiều dọc, bạn có thể đặt chiều rộng bố cục thành "wrap_content", trong khi nếu bạn muốn đặt nền lặp lại, hãy đặt chiều cao thành "wrap_content". Nếu cả chiều cao và chiều rộng được đặt thành "fill_parent" thì nó sẽ được tô theo hướng X và Y.

Ví dụ, đoạn mã sau sẽ lặp lại nền của bạn theo chiều dọc:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:background="@drawable/news_detail_activity_bg"> 
</LinearLayout> 
1

Chỉ cần đặt dòng này của mã trong onCreate(): -

final Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.actionbar_bg); 
final BitmapDrawable bitmapDrawable = new BitmapDrawable(bmp); 
bitmapDrawable.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); 
final ActionBar bar = getSupportActionBar(); 
bar.setBackgroundDrawable(bitmapDrawable); 
0
/* Tiled Layer Bitmap*/ 


public class TiledLayer { 
private int cellWidth; 
private int cellHeight; 
private int yPosition = 0, xPosition = 0; 
private int[][] grid; 
private Image image; 
private int[] tileXPositions; 
private int[] tileYPositions; 
private ArrayList animatedTiles; 
private int numberOfTiles; 
private int numberOfColumns; 
private int numberOfRows; 
private int gridColumns; 
private int gridRows, width, height; 

public TiledLayer(Image image, int columns, int rows, int tileWidth, 
     int tileHeight, int width, int height) { 
    this.grid = new int[columns][rows]; 
    this.gridColumns = columns; 
    this.gridRows = rows; 
    this.width = columns * tileWidth; 
    this.height = rows * tileHeight; 
    this.animatedTiles = new ArrayList(); 
    setStaticTileSet(image, tileWidth, tileHeight); 
    } 

public void setStaticTileSet(Image image, int tileWidth, int tileHeight) { 
    this.image = image; 
    this.cellWidth = tileWidth; 
    this.cellHeight = tileHeight; 
    int columns = 64;//image.getWidth()/tileWidth; 
    int rows =40;// image.getHeight()/tileHeight; 
    this.tileXPositions = new int[columns]; 
    int pos = 0; 
    for (int i = 0; i < columns; i++) { 
     this.tileXPositions[i] = pos; 
     pos += tileWidth; 
    } 
    this.tileYPositions = new int[rows]; 
    pos = 0; 
    for (int i = 0; i < rows; i++) { 
     this.tileYPositions[i] = pos; 
     pos += tileHeight; 
    } 

    if (columns * rows < this.numberOfTiles) { 
     // clear the grid, when there are not as many tiles as in the 
     // previous set: 
     for (int i = 0; i < this.grid.length; i++) { 
      for (int j = 0; j < this.grid[i].length; j++) { 
       this.grid[i][j] = 0; 
      } 
     } 
    } 
    this.numberOfTiles = columns * rows; 
    this.numberOfColumns = columns; 
    this.numberOfRows = rows; 
    } 

    public int createAnimatedTile(int staticTileIndex) { 
    if (staticTileIndex >= this.numberOfTiles) { 

     throw new IllegalArgumentException("invalid static tile index: " 
       + staticTileIndex + " (there are only [" 
       + this.numberOfTiles + "] tiles available."); 

    } 
    this.animatedTiles.add(new Integer(staticTileIndex)); 
    return -1 * (this.animatedTiles.size() - 1); 
} 

public void setAnimatedTile(int animatedTileIndex, int staticTileIndex) { 
    if (staticTileIndex >= this.numberOfTiles) { 

    } 
    int animatedIndex = (-1 * animatedTileIndex) - 1; 
    this.animatedTiles.set(animatedIndex, new Integer(staticTileIndex)); 
    } 

public int getAnimatedTile(int animatedTileIndex) { 
    int animatedIndex = (-1 * animatedTileIndex) - 1; 
    Integer animatedTile = (Integer) this.animatedTiles.get(animatedIndex); 
    return animatedTile.intValue(); 
} 
public void setCell(int col, int row, int tileIndex) { 
    if (tileIndex >= this.numberOfTiles) { 

     throw new IllegalArgumentException("invalid static tile index: " 
       + tileIndex + " (there are only [" + this.numberOfTiles 
       + "] tiles available."); 

    } 
    this.grid[col][row] = tileIndex; 
} 

public int getCell(int col, int row) { 
    return this.grid[col][row]; 
} 

public void fillCells(int col, int row, int numCols, int numRows, 
     int tileIndex) { 
    if (tileIndex >= this.numberOfTiles) { 

     throw new IllegalArgumentException("invalid static tile index: " 
       + tileIndex + " (there are only [" + this.numberOfTiles 
       + "] tiles available."); 

    } 
    int endCols = col + numCols; 
    int endRows = row + numRows; 
    for (int i = col; i < endCols; i++) { 
     for (int j = row; j < endRows; j++) { 
      this.grid[i][j] = tileIndex; 
     } 
    } 
} 

    public final int getCellWidth() { 
    return this.cellWidth; 
} 

    public final int getCellHeight() { 
    return this.cellHeight; 
} 

public final int getColumns() { 
    return this.gridColumns; 
} 

public final int getRows() { 
    return this.gridRows; 
} 

public final void paint(Graphics g) { 
    int clipX = 0;// g.getClipX(); 
    int clipY = 0;// g.getClipY(); 
    int clipWidth = width;// g.getClipWidth(); 
    int clipHeight = height;// g.getClipHeight(); 

    // jmt restore clip to previous state 

    int x = this.xPosition; 
    int y = this.yPosition; 
    int[][] gridTable = this.grid; 
    for (int i = 0; i < this.gridColumns; i++) { 
     int[] gridRow = gridTable[i]; 
     for (int j = 0; j < gridRow.length; j++) { 
      int cellIndex = gridRow[j]; 
      if (cellIndex != 0) { 
       // okay this cell needs to be rendered: 
       int tileIndex; 
       if (cellIndex < 0) { 
        Integer tile = (Integer) this.animatedTiles 
          .get((-1 * cellIndex) - 1); 
        tileIndex = tile.intValue() - 1; 
       } else { 
        tileIndex = cellIndex - 1; 
       } 
       // now draw the tile: 
       g.save(Canvas.CLIP_SAVE_FLAG); 
       // jmt: clear the screen 
       Rect r = new Rect(0, 0, cellWidth, cellHeight); 
       g.clipRect(r); 
       g.setClip(x, y, this.cellWidth, this.cellHeight); 
       int column = tileIndex % this.numberOfColumns; 
       int row = tileIndex/this.numberOfColumns; 
       int tileX = x - this.tileXPositions[column]; 
       int tileY = y - this.tileYPositions[row]; 

       g.drawImage(this.image, tileX, tileY); 
       g.restore(); 
      } 
      y += this.cellHeight; 
     } // for each row 
     y = this.yPosition; 
     x += this.cellWidth; 
    } // for each column 

    // reset original clip: 
    g.setClip(clipX, clipY, clipWidth, clipHeight); 
} 

}