Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在自定义视图中设置可绘制对象的动画_Android_Animation_View_Drawable - Fatal编程技术网

Android 在自定义视图中设置可绘制对象的动画

Android 在自定义视图中设置可绘制对象的动画,android,animation,view,drawable,Android,Animation,View,Drawable,我正在尝试在自定义视图中设置ShapeDrawable的动画。但我不确定完成这项任务的最佳方法是什么 我是否应该尝试在路径上画一个棋子并调用invalidate(),直到它到达目标方块?或者是否有更好的方法使用异步任务或处理程序 这是我的代码,为了便于阅读,我省略了很多方法和变量 public class CheckerBoard extends View { public enum State implements Parcelable { EMPTY(0), WHI

我正在尝试在自定义视图中设置
ShapeDrawable
的动画。但我不确定完成这项任务的最佳方法是什么

我是否应该尝试在路径上画一个棋子并调用
invalidate()
,直到它到达目标方块?或者是否有更好的方法使用异步任务或处理程序

这是我的代码,为了便于阅读,我省略了很多方法和变量

public class CheckerBoard extends View {

    public enum State implements Parcelable {
        EMPTY(0), WHITE(1), BLACK(2);
    }

        private final State[][] boardStates = new State[SIZE][SIZE];

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(bgColor);
        for (int y = 0; y < SIZE; y++) {
            for (int x = 0; x < SIZE; x++) {
                if ((y % 2 == 0 && x % 2 != 0) || (y % 2 != 0 && x % 2 == 0)) {
                    drawRect(x, y, canvas);
                    drawPawn(x, y, canvas);
                }
            }
        }
    }

    private void drawRect(int x, int y, Canvas c) {
    }

    private void drawPawn(int x, int y, Canvas c) {
    }

    private void init() {
        setupBoard();
        pawnLinePaint.setStyle(Paint.Style.STROKE);
        wPawnDrawable.getPaint().setColor(wColor);
        wPawnDrawable.getPaint().setShadowLayer(tileSize + 2, 4, 4, Color.GRAY);
        bPawnDrawable.getPaint().setColor(bColor);
        bPawnDrawable.getPaint().setShadowLayer(tileSize + 2, 4, 4, Color.GRAY);
        playerState = startState;
    }

    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int x = (int) (event.getX() / tileSize);
                int y = (int) (event.getY() / tileSize);
                if (selection[0] >= 0) { // A tile is already selected
                    if (isValidMove(selection[0], selection[1], x, y)) {
                        makeMove(x, y);
                        clearSelection();
                        switchPlayer();
                        invalidate();
                    }

                } else { // New selection
                    if (isValidSelection(x, y)) {
                        selection[0] = x;
                        selection[1] = y;
                        invalidate();
                    }
                }

                return true;
            default:
                return super.onTouchEvent(event);
        }
    }

    private void makeMove(int x, int y) {
        // Move the pawn to the new square
        boardStates[y][x] = boardStates[selection[1]][selection[0]];
        // Old square is now empty
        boardStates[selection[1]][selection[0]] = State.EMPTY;  
    }

    private void switchPlayer() {
        playerState = playerState == State.WHITE ? State.BLACK : State.WHITE;
    }

    public CheckerBoard(Context context) {
        super(context);
        init();
    }

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

    public CheckerBoard(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }


    private class Pawn extends ShapeDrawable {
        public Pawn() {
            super(new OvalShape());
        }

        public void drawWithCircles(Canvas canvas, float x, float y){
            super.draw(canvas);
            canvas.drawCircle(x * tileSize + pawnDiameter, y * tileSize + pawnDiameter, pawnDiameter - pawnPadding,
                    pawnLinePaint);
            canvas.drawCircle(x * tileSize + pawnDiameter, y * tileSize + pawnDiameter, pawnDiameter - pawnPadding * 6,
                    pawnLinePaint);
            canvas.drawCircle(x * tileSize + pawnDiameter, y * tileSize + pawnDiameter, pawnDiameter - pawnPadding * 8,
                    pawnLinePaint);
        }
    }

}
公共类棋盘扩展视图{
公共枚举状态实现可包裹{
空(0)、白(1)、黑(2);
}
私有最终状态[][]BoardState=新状态[大小][大小];
@凌驾
受保护的void onDraw(画布){
画布。drawColor(bgColor);
对于(int y=0;y=0){//已选择磁贴
if(isValidMove(选择[0],选择[1],x,y)){
makeMove(x,y);
选举();
switchPlayer();
使无效();
}
}else{//新选择
if(isValidSelection(x,y)){
选择[0]=x;
选择[1]=y;
使无效();
}
}
返回true;
违约:
返回super.onTouchEvent(事件);
}
}
私有void makeMove(整数x,整数y){
//将棋子移到新的方块上
BoardState[y][x]=BoardState[selection[1]][selection[0]];
//老广场现在空无一人
BoardState[选择[1]][选择[0]]=State.EMPTY;
}
私有void switchPlayer(){
playerState=playerState==State.WHITE?State.BLACK:State.WHITE;
}
公共棋盘(上下文){
超级(上下文);
init();
}
公共棋盘(上下文、属性集属性){
超级(上下文,attrs);
init();
}
公共棋盘(上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
init();
}
私有类典当扩展可变形{
公共典当{
超级(新卵形());
}
公共空白drawWithCircles(画布、浮动x、浮动y){
超级绘画(画布);
画布.画圈(x*tileSize+pawnDiameter,y*tileSize+pawnDiameter,pawnDiameter-PawnAdding,
当线漆);
画布.画圈(x*tileSize+pawnDiameter,y*tileSize+pawnDiameter,pawnDiameter-PawnAdding*6,
当线漆);
画布.画圈(x*tileSize+pawnDiameter,y*tileSize+pawnDiameter,pawnDiameter-PawnAdding*8,
当线漆);
}
}
}
谢谢你的帮助


blant

您应该为应用程序创建两个线程。一个线程是UI线程,它只在当前状态下绘制电路板。另一个线程是移动棋盘上项目的游戏引擎或动画线程

第一个线程以您想要的帧速率运行,第二个线程应该运行得更快。通过这种方式,您实际上不必亲自处理动画,因为UI线程只是按照当前的状态绘制电路板。在引擎线程中,更新游戏、棋盘、棋子以及线程的每个周期的状态

这样做有两个好处。首先,如果引擎线程陷入某种计算中,游戏的帧率不会下降。其次,它允许你从游戏中抽象出绘图,从而使调试更加容易

以进度条为例。假设您试图创建一个带有进度条的文件上传程序,但只有一个线程。因此,您启动进度条,然后开始上载文件。如果上载过程被阻塞,则必须等待文件完成上载,然后才能更新进度条,这实际上会使进度条变得无用。但是,如果您使用两个线程进行此操作,那么您可以设置它,这样一个线程就可以根据一些常见变量简单地更新进度条图形。另一个tread负责执行操作并更新进度变量

有关更多信息,请查看以下链接:


您应该为应用程序创建两个线程。一个线程是UI线程,它只在当前状态下绘制电路板。另一个线程是移动棋盘上项目的游戏引擎或动画线程

第一个线程以您想要的帧速率运行,第二个线程应该运行得更快。通过这种方式,您实际上不必亲自处理动画,因为UI线程只需按当前状态绘制电路板