【问题标题】:Android Tile BitmapAndroid 平铺位图
【发布时间】:2010-11-21 14:45:22
【问题描述】:

我正在尝试在 Android 中加载我想要平铺的位图。我目前在视图中使用以下内容来显示位图:

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

我基本上想在我的应用程序中使用这个位图作为背景图像,并希望在 X 和 Y 方向上重复该位图。

我已经看到 BitmapShader 类的 TileMode.REPEAT 常量,但我不确定这是用于重复实际位图还是用于对位图应用过滤器。

【问题讨论】:

  • 有人知道如何在不使用 xml 的情况下在 java 代码中执行此操作吗?

标签: android bitmap


【解决方案1】:

您可以在 xml 而不是 java 代码中执行此操作。我自己没有尝试过,但我确实找到了这个例子。

<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"
>

然后在一个名为 backrepeat.xml 的 xml 中

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

reference

【讨论】:

  • 只是添加,backrepeat.xml 进入“drawable”文件夹
  • 这里可能有点迂腐,但第一行应该是 -
  • 这适用于最近的 Android API 版本(大约 4.x),但至少在 API 2.2 之前不起作用。任何人都知道解决方法/修复和更多细节? developer.android.com/reference/android/R.attr.html#tileMode 参考说它是从 API 1 开始添加的,但它仍然不起作用。
  • 这个例子无处不在,但为什么我们认为它在实际创建平铺背景时工作,每个图像周围都有最丑陋的空白填充?它是无用的边缘。我经历了每一圈,尝试了一切。我试过使用透明度和不透明度。
【解决方案2】:

上面的 backrepeat.xml 有问题

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

【讨论】:

  • 为什么它有问题以及如何解决它?
  • 这个添加了:android:dither="true",如果瓷砖一开始就不能很好地工作,它什么也不做。
【解决方案3】:

弄清楚代码版本:

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

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

然后,如果您有一个可绘制的平铺,则可以使用它来制作 BitmapDrawable:

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

【讨论】:

  • 这很好用,但是你如何只垂直重复它呢?我尝试删除 setTileModeX,但它甚至根本不起作用。
  • @WilliamL。奇怪的。 docs 似乎说它应该只适用于其中一个。最好的猜测是尝试Shader.TileMode.CLAMP,然后看看会发生什么。
  • 如果我只水平重复它就可以工作,但不能只垂直重复。 CLAMP 的作用与一开始没有设置平铺模式相同。
【解决方案4】:

似乎有些人有兴趣在 View 的 onDraw 方法中执行此操作。以下代码对我有用:

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;
}

【讨论】:

  • 它将填满所有区域。最后一个图块可能不完整,屏幕最右边/最底部的空间仍将被绘制。
  • 我只是将它用于我的画布的一部分而不是全部,所以显然你得到了额外的绘制,然后宽度和高度不能被图像大小整除。我删除了我的评论,因为它与问题无关。对不起!
  • 在这种情况下,您将使用 BitmapDrawable.setBounds 和 BitmapDrawable.draw(Canvas)
【解决方案5】:
<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"
>

这对我来说很好。我不必单独创建位图。我在布局中使用了 tileMode 属性。

【讨论】:

  • 谢谢,我发现这是最简单的方法。
【解决方案6】:

如果您只想垂直重复背景,您可以将布局的宽度设置为“wrap_content”,而如果您想将背景设置为水平重复,请将高度设置为“wrap_content”。如果高度和宽度都设置为“fill_parent”,那么它将在 X 和 Y 方向平铺。

例如,以下代码将垂直重复您的背景:

<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>

【讨论】:

    【解决方案7】:

    只需将这行代码放在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);
    

    【讨论】:

      【解决方案8】:
      /* 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);
           }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-15
        • 2021-08-04
        • 2012-03-23
        • 2011-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多