我想在surfaceview上创建动画。 这是一个表面视图:
public class AnimationSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
private AnimationWorker animationWorker;
private GestureDetectorCompat mGestureDetector;
private OverScroller mScroller;
private Cursor mCursor;
private int pIndexA, pIndexB;
private int dir;
private float posX=0;
public AnimationSurfaceView(Context context, Cursor cursor) {
super(context);
getHolder().addCallback(this);
mCursor = cursor;
mGestureDetector = new GestureDetectorCompat(context, mGestureListener);
mScroller = new OverScroller(context);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
animationWorker = new AnimationWorker(getHolder(), getContext(), null);
animationWorker.setRunning(true);
animationWorker.run();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
animationWorker.setRunning(false);
animationWorker.postTask(null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("sfsfsfdf", "Работает1!!!!!!!!!!!!!!!!!!!");
boolean retVal = mGestureDetector.onTouchEvent(event);
return retVal || super.onTouchEvent(event);
}
@Override
public void computeScroll() {
super.computeScroll();
if(mCursor != null){
int i1 = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.floor(posX/720f)));
int i2 = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.ceil(posX/720f)));
if(i1 != pIndexA){
dir = i1-pIndexA;
pIndexA = i1;
pIndexB = i2;
}
}
}
private void updateWorker(){
animationWorker.postTask(new AnimationTask(posX, dir));
AnimationWorker.syncObj.notifyAll();
}
private final GestureDetector.SimpleOnGestureListener mGestureListener
= new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
mScroller.forceFinished(true);
animationWorker.cancelTaskQueue();
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
posX += -distanceX;
updateWorker();
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
velocityX = - velocityX;
fling(velocityX);
return true;
}
private void fling(float velocity){
mScroller.forceFinished(true);
mScroller.fling((int) posX, 0, (int) -velocity, 0, 0, 720 * (mCursor != null ? mCursor.getCount() : 1), 0, 0);
updateWorker();
}
};
这是一名工人:
public class AnimationWorker extends Thread {
private static final String LOG_TAG = AnimationWorker.class.getSimpleName();
public static final Object syncObj = new Object();
private boolean runFlag = false;
private SurfaceHolder surfaceHolder;
private Context context;
private BlockingQueue<AnimationTask> queue;
private Cursor mCursor;
private AnimationImageCacheHelper animationImageCacheHelper;
private final String ASSET_SUFFIX = "assets://";
private final String FILE_SUFFIX = "file://";
Rect clipRect;
Rect bitmapRect;
Paint paint;
Pair<Bitmap, Bitmap> bitmaps;
int mLeftIndex;
int mRightIndex;
private final Float TRACK_LENTH = 720f;
private final Float MAX_ALPHA = 255f;
public AnimationWorker(
SurfaceHolder surfaceHolder,
Context context,
Cursor cursor){
super();
this.surfaceHolder = surfaceHolder;
this.animationImageCacheHelper = new AnimationImageCacheHelper();
bitmapRect = new Rect();
paint = new Paint();
clipRect = new Rect();
queue = new LinkedBlockingDeque<AnimationTask>();
}
public void setRunning(boolean run){
runFlag = run;
}
public void postTask(AnimationTask task){
try {
queue.put(task);
}catch (Exception e){
//do nothing
}
}
public void cancelTaskQueue(){
queue.clear();
}
@Override
public void run() {
while(runFlag){
Log.e(LOG_TAG, "running");
try {
AnimationTask task = queue.remove();
if(task != null) {
processTask(task);
}
}catch(Exception e){
try {
synchronized (syncObj) {
syncObj.wait();
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Log.e(LOG_TAG, "exception");
e.printStackTrace();
}
}
}
private void processTask(AnimationTask task){
int leftIndex = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.floor(task.currentPosition/TRACK_LENTH.intValue())));
int rightIndex = Math.max(0,Math.min(mCursor.getCount()-1, (int)Math.ceil(task.currentPosition/TRACK_LENTH.intValue())));
if(mLeftIndex != leftIndex || mRightIndex != rightIndex){
bitmaps = getBitmaps(leftIndex, rightIndex, task.direction);
}
float alpha = (MAX_ALPHA / TRACK_LENTH * task.currentPosition) % MAX_ALPHA;
draw(bitmaps.first, bitmaps.second, alpha);
}
private Pair<Bitmap, Bitmap> getBitmaps(int leftIndex, int rightIndex, int direction){
final Bitmap foregroundBitmap;
final Bitmap backgroundBitmap;
final Pair<Bitmap, Bitmap> result;
if(direction == 1) {
//right on top
if(mCursor.moveToPosition(leftIndex)){
String backgroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
backgroundBitmap = loadImage(backgroundImageUrl);
}else{
backgroundBitmap = null;
}
if (mCursor.moveToPosition(rightIndex)){
String foregroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
foregroundBitmap = loadImage(foregroundImageUrl);
}else{
foregroundBitmap = null;
}
} else {
//left on top
if(mCursor.moveToPosition(rightIndex)){
String backgroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
backgroundBitmap = loadImage(backgroundImageUrl);
}else{
backgroundBitmap = null;
}
if (mCursor.moveToPosition(leftIndex)){
String foregroundImageUrl = mCursor.getString(mCursor.getColumnIndex(PhotoContract.PhotoEntry.COLUMN_PHOTO_URL));
foregroundBitmap = loadImage(foregroundImageUrl);
}else{
foregroundBitmap = null;
}
}
result = new Pair<Bitmap, Bitmap>(foregroundBitmap, backgroundBitmap);
return result;
}
private Bitmap loadImage(String uri){
if(animationImageCacheHelper.isImageContains(uri)){
return animationImageCacheHelper.getBitmap(uri);
}
if (uri.startsWith(ASSET_SUFFIX)) {
Bitmap bitmap = ImageLoader.getInstance().loadImageSync(uri);
animationImageCacheHelper.put(uri, bitmap);
return bitmap;
} else {
Bitmap bitmap = ImageLoader.getInstance().loadImageSync("file://" + uri);
animationImageCacheHelper.put(uri, bitmap);
return bitmap;
}
}
private void draw(Bitmap foreground, Bitmap background, float alpha){
Canvas canvas;
canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
canvas.getClipBounds(clipRect);
synchronized (surfaceHolder) {
//draw background
paint.setAlpha(255);
bitmapRect.set(0, 0, background.getWidth(), background.getHeight());
canvas.drawBitmap(background, bitmapRect, clipRect, paint);
//draw foreground
paint.setAlpha((int)alpha);
bitmapRect.set(0, 0, foreground.getWidth(), foreground.getHeight());
canvas.drawBitmap(foreground, bitmapRect, clipRect, paint);
}
}finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
我正在收听 onTouch 事件,并为工作人员添加任务(当前位置和方向)。工作人员必须从队列中获取任务并绘制当前状态。 在我的版本中没有任何反应Surfaceview会冻结,我需要从我的设备中取出电池来解锁它。
*注意:我尝试使用queue.take()
- 但我得到的结果相同