自定义可绘制视图未在Android应用上显示

时间:2014-11-15 22:43:00

标签: android

我目前正在构建一个基于难度设置产生迷宫的Android应用程序(容易产生带边框的5x5迷宫,中等8x8,硬11x11)。迷宫由黑色方块组成,其位置构成从左上角到右下角的路径,其他方向以及迷宫周围的单边形边界。如果有一个黑色方块,你就不能朝那个方向移动......等等,目前只构建了界面,而不是任何用户交互(我稍后会添加)。代码也有点乱 - 我知道这一点,并在问题解决后将其解决。

这个问题是没有显示迷宫 - 只是一个白色的空白区域!我正在为主界面使用XML文件和活动,并以迷宫形式使用自定义视图。

这是在游戏中创建界面的活动/类。此处使用的Level类包含有关当前分数/迷宫/用户位置等的数据。它已经过测试,我非常有信心它可以正常工作。

public class InGameInterface extends Activity {

    Level level;;
    MazeView maze;

    private boolean[][] currentMaze = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.in_game_interface);

        level = new Level();

        currentMaze = level.getNewMaze();
        loadMazeDisplay();
    }   

    private void loadMazeDisplay()
    {
        maze = new MazeView(this, level, currentMaze);

        RelativeLayout mazeHolder = (RelativeLayout) findViewById(R.id.maze);
        LayoutParams lP = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        mazeHolder.addView(maze, lP);
    }
}

下面是我试图插入自定义视图的XML文件的相关部分。<丢失了,因为Stack Overflow在这里不喜欢它们。

RelativeLayout
    android:id="@+id/maze"
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_marginLeft="7dp"
    android:layout_marginRight="15dp"
    android:layout_weight="2" >
RelativeLayout

以下是构建并应显示迷宫的MazeView。

public class MazeView extends View
{
private Activity context;
private Level level;
private boolean mazeIsPath[][] = null;

private Integer widthInPixels = 0, heightInPixels = 0;
private Integer cellWidthInPixels = 0, cellHeightInPixels = 0;
private Paint cell, ball, background, target;

public MazeView(Context context, Level level, boolean[][] maze) 
{
    super(context);
    this.context = (Activity) context;
    this.level = level;
    mazeIsPath = maze;

    cell = new Paint();
    cell.setColor(getResources().getColor(R.color.textColor));

    ball = new Paint();
    ball.setColor(getResources().getColor(R.color.splashBackground));

    background = new Paint();
    background.setColor(getResources().getColor(R.color.gameInterfaceBackground));

    target = new Paint();
    target.setColor(getResources().getColor(R.color.buttonBackground));

    widthInPixels = this.getWidth();
    heightInPixels = this.getHeight();

    setFocusable(true);
    this.setFocusableInTouchMode(true);
}

protected void onSizeChanged(Integer newW, Integer newH, Integer oldW, Integer oldH)
{
    widthInPixels = newW;
    heightInPixels = newH;

    super.onSizeChanged(newW, newH, oldW, oldH);
}

protected void onDraw(Canvas canvas)
{
    Integer counterX = 0, counterY = 0;

    canvas.drawRect(0, 0, widthInPixels, heightInPixels, background);

    for(counterX = 0; counterX < level.getWidth(); counterX++)
    {
        for(counterY = 0; counterY < level.getHeight(); counterY++)
        {
            if(mazeIsPath[counterX][counterY] != true)
            {
                canvas.drawRect((float)(cellWidthInPixels * counterX), (float)(cellHeightInPixels * counterX), (float)(cellWidthInPixels * (counterX + 1)), (float)(cellHeightInPixels * (counterY + 1)), cell);
            }
        }
    }

    canvas.drawCircle( (float)((cellWidthInPixels * level.getCurrentX()) + (0.5f*(cellWidthInPixels))), (float)((cellHeightInPixels * level.getCurrentX()) + (0.5f*(cellHeightInPixels))), (float)(cellHeightInPixels * (2f/3f)), ball);
    canvas.drawCircle( (float)((cellWidthInPixels * level.getFinalX()) + (0.5f*(cellWidthInPixels))), (float)((cellHeightInPixels * level.getFinalX()) + (0.5f*(cellHeightInPixels))), (float)(cellHeightInPixels * (4f/5f)), target);
}
}

我想知道是否有人可以指出我哪里出错了以及如何解决它!


对onDraw()的第一次修订:

protected void onDraw(Canvas canvas)
{
    Integer counterX = 0, counterY = 0;
    widthInPixels = new Integer(canvas.getWidth());
    heightInPixels = new Integer(canvas.getHeight());

    canvas.drawRect(0, 0, widthInPixels, heightInPixels, background);

    for(counterX = 0; counterX < level.getWidth(); counterX++)
    {
        for(counterY = 0; counterY < level.getHeight(); counterY++)
        {
            if(mazeIsPath[counterX][counterY] != true)
            {
                canvas.drawRect((float)(cellWidthInPixels * counterX), (float)(cellHeightInPixels * counterX), (float)(cellWidthInPixels * (counterX + 1)), (float)(cellHeightInPixels * (counterY + 1)), cell);
            }
        }
    }

    canvas.drawCircle( (float)((cellWidthInPixels * level.getCurrentX()) + (0.5f*(cellWidthInPixels))), (float)((cellHeightInPixels * level.getCurrentX()) + (0.5f*(cellHeightInPixels))), (float)(cellHeightInPixels * (2f/3f)), ball);
    canvas.drawCircle( (float)((cellWidthInPixels * level.getFinalX()) + (0.5f*(cellWidthInPixels))), (float)((cellHeightInPixels * level.getFinalX()) + (0.5f*(cellHeightInPixels))), (float)(cellHeightInPixels * (4f/5f)), target);

    Log.w("onDraw width", widthInPixels.toString());
    Log.w("onDraw height", heightInPixels.toString());
    Integer cWidth = new Integer(canvas.getWidth());
    Integer cHeight = new Integer(canvas.getHeight());
    Log.w("canvas width", cWidth.toString());
    Log.w("cavas height", cHeight.toString());
}

1 个答案:

答案 0 :(得分:0)

我说,忘了widthInPixels&amp; heightInPixels,因为它们取决于布局。要使用它们,您必须实现onMeasure(这可能是有趣的)。但是,由于您的观点非常简单,只需使用canvas.getWidth()getHeight()中的值即可。请尝试以下操作以查看其是否有效

private static final int CELLS_PER_SCREEN = 5; // the number of cells that fit on a view

protected void onDraw(Canvas canvas) {

    int totalWidth=canvas.getWidth(), 
        totalHeight=canvas.getHeight(), 
        cellWidthInPixels=totalWidth / CELLS_PER_SCREEN,
        cellHeightInPixels=totalHeight / CELLS_PER_SCREEN;

    canvas.drawRect(0, 0, totalWidth, totalHeight, background);

    for (int counterX = 0, xlen=level.getWidth(); counterX < xlen; counterX++) {
        for (int counterY = 0, ylen=level.getHeight(); counterY < ylen; counterY++) {
            if (!mazeIsPath[counterX][counterY]) {
                canvas.drawRect(
                     (float)(cellWidthInPixels * counterX), 
                     (float)(cellHeightInPixels * counterX), 
                     (float)(cellWidthInPixels * (counterX + 1)), 
                     (float)(cellHeightInPixels * (counterY + 1)), cell
                );
            }
        }
    }

    canvas.drawCircle( (float)((cellWidthInPixels * level.getCurrentX()) + (0.5f*(cellWidthInPixels))), (float)((cellHeightInPixels * level.getCurrentX()) + (0.5f*(cellHeightInPixels))), (float)(cellHeightInPixels * (2f/3f)), ball);
    canvas.drawCircle( (float)((cellWidthInPixels * level.getFinalX()) + (0.5f*(cellWidthInPixels))), (float)((cellHeightInPixels * level.getFinalX()) + (0.5f*(cellHeightInPixels))), (float)(cellHeightInPixels * (4f/5f)), target);

    Log.w("onDraw width", widthInPixels.toString());
    Log.w("onDraw height", heightInPixels.toString());
    Integer cWidth = new Integer(canvas.getWidth());
    Integer cHeight = new Integer(canvas.getHeight());
    Log.w("canvas width", cWidth.toString());
    Log.w("cavas height", cHeight.toString());
}

还有一些关于onDraw的建议:OnDraw被非常频繁地调用,并且尽可能优化它是非常重要的。

  • 使用int而不是Integers,Integer是一个Object,而int只是一个快速的原始类型。
  • 预先计算易于重复使用的东西,特别是浮动乘法。你的drawCircles()做了很多只用cellWidthInPixels改变的数学...所以每次计算它们一次,每次cellWidthInPixels改变