Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/179.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.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
Java Canvas.drawBitmap将源代码对半剪切_Java_Android_Animation_Canvas_Android Canvas - Fatal编程技术网

Java Canvas.drawBitmap将源代码对半剪切

Java Canvas.drawBitmap将源代码对半剪切,java,android,animation,canvas,android-canvas,Java,Android,Animation,Canvas,Android Canvas,我一直在尝试用Android做一些精灵动画(这是一个大学练习),但我遇到了一个奇怪的问题。它没有绘制我定义为源的矩形,而是精确地绘制了该矩形的一半 这是我的绘图方法的代码 public class Sprite { Bitmap image; Point frameSize; int[] rows; public int curFrame; public int curRow; public void draw(Canvas c, Paint p, Vector2 pos) { Rec

我一直在尝试用Android做一些精灵动画(这是一个大学练习),但我遇到了一个奇怪的问题。它没有绘制我定义为源的矩形,而是精确地绘制了该矩形的一半

这是我的绘图方法的代码

public class Sprite {
Bitmap image;
Point frameSize;
int[] rows;
public int curFrame;
public int curRow;

public void draw(Canvas c, Paint p, Vector2 pos)
{
    Rect src;
    int left = curFrame * frameSize.x;
    int top = curRow * frameSize.y;
    int right = left + frameSize.x;
    int bottom = top + frameSize.y;

    src = new Rect(left, top, right, bottom);
    Rect dest = new Rect((int)pos.x, 0, (int)pos.x + frameSize.x, frameSize.y);

    c.drawBitmap(image, src, dest, p);
}
这是我正在使用的图像

所有帧的大小都相同(44x40),图像为440x80,我在调用该方法时将该值作为frameSize

点基本上是一个包含一对x,y整数的对象

Vector2是一个包含一对x,y浮动的对象

出于调试目的,我还呈现了一些文本

以下是一些屏幕截图:

对不起,截图太多了。我不知道是否有办法在StackOverflow中显示更小的

我看不到你的代码。重要的是:

int left = currIndex * peopleWidth;
int top = 40;
int right = left + peopleWidth;
int bottom = 80;
//clip the bitmap to show
Rect src = new Rect(left, top, right, bottom);
//set the display location in view
Rect display = new Rect(0, 0, mWidth, mHeight);
canvas.drawBitmap(mBitmap, src, display, null);
这是我的密码:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.rajesh.customcamera.R;

import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;

/**
 * Created by rajesh.zhu on 2017/9/28.
 */

public class MovingPeopleView extends View {
    private static final String TAG = "MovingPeopleView";
    private int defaultWidth = 44;
    private int defaultHeight = 40;
    private int mWidth = 0;
    private int mHeight = 0;
    private int peopleWidth = 44;
    private int peopleHeight = 40;
    private int currIndex = 0;

    private Bitmap mBitmap = null;
    private boolean isRunning = false;

    public MovingPeopleView(Context context) {
        this(context, null);
    }

    public MovingPeopleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MovingPeopleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            //match_parent || absolute_value
            mWidth = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            //wrap_content
            mWidth = Math.min(defaultWidth, widthSize);
        } else {
            mWidth = defaultWidth;
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            mHeight = heightSize;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            mHeight = Math.min(defaultHeight, heightSize);
        } else {
            mHeight = defaultHeight;
        }

        setMeasuredDimension(mWidth, mHeight);
    }

    private void init(Context context) {
        mBitmap = BitmapFactory.decodeResource(context.getResources(), R.mipmap.icon_moving_people);
        //Log.i(TAG, "Width:" + mBitmap.getWidth() + ", Height:" + mBitmap.getHeight());
        //you can set the peopleWidth and peopleHeight here
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        int left = currIndex * peopleWidth;
        int top = 40;
        int right = left + peopleWidth;
        int bottom = 80;
        //clip in bitmap to show
        Rect src = new Rect(left, top, right, bottom);
        //set the show location in view
        Rect display = new Rect(0, 0, mWidth, mHeight);
        canvas.drawBitmap(mBitmap, src, display, null);
    }

    public void start() {
        isRunning = true;
        run();
    }

    public void stop() {
        isRunning = false;
    }

    private void run() {
        if (isRunning) {
            Observable
                    .timer(100, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Consumer<Long>() {
                        @Override
                        public void accept(@NonNull Long aLong) throws Exception {
                            currIndex++;
                            if (currIndex == 10) {
                                currIndex = 0;
                            }
                            Log.i(TAG, "run");
                            invalidate();
                            run();
                        }
                    });
        }
    }

    public void recycler() {
        if (mBitmap != null) {
            mBitmap.recycle();
            mBitmap = null;
        }
    }
}
导入android.content.Context;
导入android.graphics.Bitmap;
导入android.graphics.BitmapFactory;
导入android.graphics.Canvas;
导入android.graphics.Rect;
导入android.support.annotation.Nullable;
导入android.util.AttributeSet;
导入android.util.Log;
导入android.view.view;
导入com.rajesh.customcamera.R;
导入java.util.concurrent.TimeUnit;
导入io.reactivex.Observable;
导入io.reactivex.android.schedulers.AndroidSchedulers;
导入io.reactivex.annotations.NonNull;
导入io.reactivex.functions.Consumer;
/**
*由rajesh.zhu于2017/9/28创建。
*/
公共类MovingPeopleView扩展了视图{
私有静态最终字符串标记=“MovingPeopleView”;
私有int defaultWidth=44;
私家车高度=40;
私有int mWidth=0;
私有整数mHheight=0;
私有int peopleWidth=44;
私人内部人员身高=40;
私有int currIndex=0;
私有位图mBitmap=null;
私有布尔值isRunning=false;
公共MovingPeopleView(上下文){
这个(上下文,空);
}
public MovingPeopleView(上下文上下文,@Nullable AttributeSet attrs){
这(上下文,属性,0);
}
public MovingPeopleView(上下文上下文,@Nullable AttributeSet attrs,int-defStyleAttr){
super(上下文、attrs、defStyleAttr);
init(上下文);
}
@凌驾
测量时受保护的同步空隙(int-widthMeasureSpec、int-heightMeasureSpec){
超级测量(宽度测量、高度测量);
int widthMode=MeasureSpec.getMode(widthmasurespec);
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
if(widthMode==MeasureSpec.justice){
//匹配父项| |绝对值
mWidth=宽度尺寸;
}else if(widthMode==MeasureSpec.AT_){
//包装内容
mWidth=数学最小值(默认宽度,宽度大小);
}否则{
mWidth=默认宽度;
}
if(heightMode==MeasureSpec.justice){
mHeight=高度尺寸;
}else if(heightMode==MeasureSpec.AT_){
mHeight=数学最小值(默认高度、高度大小);
}否则{
mHeight=默认高度;
}
设置测量尺寸(米宽,米高);
}
私有void init(上下文){
mBitmap=BitmapFactory.decodeResource(context.getResources(),R.mipmap.icon\u moving\u people);
//Log.i(标记“Width:+mBitmap.getWidth()+”,Height:+mBitmap.getHeight());
//您可以在此处设置peopleWidth和peopleHeight
}
@凌驾
公共空白绘制(画布){
超级绘画(画布);
int left=currendex*peopleWidth;
int top=40;
int right=left+peopleWidth;
int-bottom=80;
//剪辑位图以显示
Rect src=新的Rect(左、上、右、下);
//在视图中设置显示位置
Rect显示=新的Rect(0,0,mWidth,mHheight);
drawBitmap(mBitmap、src、display、null);
}
公开作废开始(){
isRunning=true;
run();
}
公共停车场(){
isRunning=false;
}
私家车{
如果(正在运行){
可观察
.计时器(100,时间单位.毫秒)
.observeOn(AndroidSchedulers.mainThread())
.订阅(新消费者){
@凌驾
public void accept(@NonNull Long-aLong)引发异常{
currendex++;
如果(当前索引==10){
货币指数=0;
}
Log.i(标记“运行”);
使无效();
run();
}
});
}
}
公共废物回收商(){
如果(mBitmap!=null){
mBitmap.recycle();
mBitmap=null;
}
}
}
您可以在XML中使用它:

<com.rajesh.customcamera.view.MovingPeopleView
    android:id="@+id/moving_people"
    android:layout_width="50dp"
    android:layout_height="50dp" />

可观察到的部分看起来很危险。你应该把代码放在其他地方,并注意订阅。可能在onAttach中开始可见,在onAttach中取消订阅或在可见性更改时开始可见。