기본적으로 드로어 블에 저장되는 자동차의 다른 이미지를로드해야합니다. 360도 회전을 시뮬레이션 할 수 있습니다. 사용자가 뷰를 드래그 할 때 드래그 거리를 설정해야합니다. 다음 프레임을로드하십시오. 표면보기를 사용하고 캔버스 위에 이미지를 그립니다. 이미지가 너무 커서 모든 이미지를 한 번에 메모리에로드 할 수 없으므로 현재 이미지 만 메모리에 저장하여 이미지를로드하고 있습니다. 그러나이 방법은 너무 느립니다. 내가 잘못하고있는 것을 지적 할 수 있습니까? 또는 다른 것을 달성하기위한 더 좋은 방법. 당신의 도움을 주셔서 감사합니다.SurfaceView에서 이미지를로드하는 중 문제가 발생했습니다.
이 내 코드
/** * @author rajeshcp * 뷰의 평면도로 * 계층 구조 CarDetailsActivity * @since 13 이월 행동 클래스 2013 */
입니다public class VirtualView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener, TweenListener {
private final int frame_width = 1024;
private final int frame_height = 462;
private InteractionListener mInteractionListener;
private final int mSnapVelocity = 1000;
private VelocityTracker mVelocityTracker;
protected int mTouchSlop;
private int mMaxVelocity;
private Rect mViewArea;
private IQTweener mValueanimator;
private ColorVariationVO mColorVariationVO;
/**************Indicates the current frame*********************/
private int mCurrentFrameIndex;
/**********Initial touch x coordinate**************/
private int mInitialTouchX;
/***********The drag distance for frame change***********/
private int mDragInterWell = 10;
private final int mTotalFrames = 36;
protected final int mMaxFrameSkip = 3;
/**************Identity matrix**********************/
private Matrix mIdentityMatrix;
private Paint mPaint;
/*********The bitmap to be drawn over the canvas*********/
private Bitmap mCurrentFrame;
private ViewUpdater mViewUpdater;
/*++++++++++++++++++++++++++++++++++++++++++++++*/
/*+++++++++++++Getters and Setters++++++++++++++*/
/*++++++++++++++++++++++++++++++++++++++++++++++*/
/**
* @param of type null
* @return mColorVariationVO of type ColorVariationVO
* getter function for mColorVariationVO
* @since Feb 13, 2013
* @author rajeshcp
*/
public ColorVariationVO getmColorVariationVO() {
return mColorVariationVO;
}
/**
* @param mColorVariationVO of type ColorVariationVO
* @return of type null
* setter function for mColorVariationVO
* @since Feb 13, 2013
* @author rajeshcp
*/
public void setmColorVariationVO(ColorVariationVO mColorVariationVO) {
this.mColorVariationVO = mColorVariationVO;
loadNextFrame();
}
/**
* @param context of type Context
* @return of type VirtualView
* Constructor function
* @since Feb 13, 2013
* @author rajeshcp
*/
public VirtualView(Context context) {
super(context);
init();
}
/**
* @param context of type Context
* @param attrs of type AttributeSet
* @return of type VirtualView
* Constructor function
* @since Feb 13, 2013
* @author rajeshcp
*/
public VirtualView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
/**
* @param context of type Context
* @param attrs of type AttributeSet
* @param defStyle of type int
* @return of type VirtualView
* Constructor function
* @since Feb 13, 2013
* @author rajeshcp
*/
public VirtualView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
/**
* @param of type null
* @return of type null
* function which will initialize the values for the view
* @since 13 Feb 2013
*/
private void init()
{
setZOrderOnTop(true);
getHolder().setFormat(PixelFormat.TRANSPARENT);
mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG);
mIdentityMatrix = new Matrix();
mCurrentFrameIndex = 0;
mViewUpdater = new ViewUpdater();
mInteractionListener = new InteractionListener();
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaxVelocity = configuration.getScaledMaximumFlingVelocity();
getHolder().addCallback(this);
setOnTouchListener(this);
setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
}
/**
* @param direction of type int
* @return of type null
* function which will change the current frame index
* @since Feb 13, 2013
* @author rajeshcp
*/
private void initiateFrameChange(final int direction)
{
mCurrentFrameIndex += Math.max(-mMaxFrameSkip, Math.min(mMaxFrameSkip, direction));
if(mCurrentFrameIndex > (mTotalFrames - 1))
{
mCurrentFrameIndex = (mCurrentFrameIndex % (mTotalFrames - 1));
}else if(mCurrentFrameIndex < 0)
{
mCurrentFrameIndex = (mTotalFrames - 1) + (mCurrentFrameIndex % (mTotalFrames - 1));
}
loadNextFrame();
}
/**
* @param index of type int
* @return of type Bitmap
* function which will create the bitmap form the
* resources
* @since Feb 13, 2013
* @author rajeshcp
*/
@SuppressLint("UseSparseArrays")
private Bitmap getFrame(final int index)
{
Bitmap bitmap = null;
if(mColorVariationVO != null)
{
final int drawableId = getResourceId(index);
try
{
bitmap = BitmapFactory.decodeResource(getResources(), drawableId);
}catch (Exception e) {
Log.d(getClass().getName(), e.getLocalizedMessage());
}
}
return bitmap;
}
/**
* @param index of type int
* @return of type int
* function which create the resource id
* from index
* @since Feb 18, 2013
* @author rajeshcp
*/
private int getResourceId(final int index)
{
final String frameName = mColorVariationVO.getmCarAssetPath() + "_" + index;
int drawableId = 0;
try {
@SuppressWarnings("rawtypes")
Class res = R.drawable.class;
Field field = res.getField(frameName);
drawableId = field.getInt(null);
}
catch (Exception e) {
Log.e(getClass().getName(), "Failure to get drawable id.", e);
}
return drawableId;
}
/* (non-Javadoc)
* @see android.view.View#onDraw(android.graphics.Canvas)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mCurrentFrame != null && canvas != null)
{
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
mIdentityMatrix.reset();
// mPaint.setStyle(Paint.Style.STROKE);
// mPaint.setStrokeWidth(1);
// mPaint.setColor(Color.MAGENTA);
// mPaint.setTextSize(100);
//
// canvas.drawText(String.valueOf(mCurrentFrameIndex), (getWidth()/(mTotalFrames - 1)) * mCurrentFrameIndex, (getHeight() - 100)/2, mPaint);
mIdentityMatrix.postTranslate(getWidth() - frame_width, (getHeight() - frame_height)/2);
canvas.drawBitmap(mCurrentFrame, mIdentityMatrix, mPaint);
}
}
/* (non-Javadoc)
* @see android.view.SurfaceHolder.Callback#surfaceChanged(android.view.SurfaceHolder, int, int, int)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
/* (non-Javadoc)
* @see android.view.SurfaceHolder.Callback#surfaceCreated(android.view.SurfaceHolder)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
if(mViewArea == null)
{
int top = (getHeight() - frame_height)/2;
int left = getWidth() - frame_width;
mViewArea = new Rect(left, top, frame_width + left, frame_height + top);
}
mDragInterWell = (int)(mViewArea.width()/(2 * mTotalFrames));
if(mViewUpdater == null)
{
init();
}
mViewUpdater.start();
mInteractionListener.start();
}
/* (non-Javadoc)
* @see android.view.SurfaceHolder.Callback#surfaceDestroyed(android.view.SurfaceHolder)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(mViewUpdater != null)
{
mViewUpdater.setRun(false);
mViewUpdater = null;
mInteractionListener.mIsRunning = false;
mInteractionListener = null;
}
}
private boolean isScrolled = false;
/* (non-Javadoc)
* @see android.view.View.OnTouchListener#onTouch(android.view.View, android.view.MotionEvent)
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
mInteractionListener.queueEvent(event);
return true;
}
/**
* @param velocity of type int
* @return of type null
* function which will initiate the
* fling animation
* @since Feb 15, 2013
* @author rajeshcp
*/
private void initiateFling(int velocity)
{
return;
// int maxDuration = mMaxFrameSkip * mSnapVelocity;
// velocity = Math.max(-maxDuration, Math.min(maxDuration, velocity));
// int end = ((int)(velocity/mSnapVelocity)) * mTotalFrames;
//
// if(mValueanimator == null)
// {
// mValueanimator = new IQTweener(mCurrentFrameIndex, mTotalFrames - 1);
// mValueanimator.setmListener(this);
// }
// mValueanimator.setMduration(2000);
// mValueanimator.setmStart(mCurrentFrameIndex);
// mValueanimator.setmEnd(end);
// mValueanimator.start();
}
/**
* @param of type null
* @return of type null
* function which will clear
* the touch values
* @since Feb 15, 2013
* @author rajeshcp
*/
private void onTouchEnd()
{
isScrolled = false;
mVelocityTracker.clear();
mVelocityTracker.recycle();
mVelocityTracker = null;
mInitialTouchX = 0;
}
/* (non-Javadoc)
* @see com.inkoniq.iqpromomultitouch.animations.IQTweener.TweenListener#onUpdate(java.lang.Object)
* @since Feb 15, 2013
* @author rajeshcp
*/
@Override
public void onUpdate(float mCurrent) {
final int mIndex = (int) mCurrent;
if(mIndex > (mTotalFrames - 1))
{
mCurrentFrameIndex = (mIndex % (mTotalFrames - 1));
}else if(mIndex < 0)
{
mCurrentFrameIndex = (mTotalFrames - 1) + (mIndex % (mTotalFrames - 1));
}
}
/**
* @param of type null
* @return of type null
* function which will load the next frame from local storage
* @since Feb 13, 2013
* @author rajeshcp
*/
private void loadNextFrame()
{
final Bitmap frame = getFrame(mCurrentFrameIndex);
if(mCurrentFrame != null)
{
Bitmap temp = mCurrentFrame;
mCurrentFrame = frame;
temp.recycle();
temp = null;
}else
{
mCurrentFrame = frame;
}
}
/**
* @author rajeshcp
* class which will take care of updating the view
* @since 13 Feb 2013
*/
private class ViewUpdater extends Thread
{
private SurfaceHolder surface;
private boolean run = true;
/**
* @param run of type boolean
* @return of type null
* setter function for run
* @since 13 Feb 2013
*/
public void setRun(boolean run) {
this.run = run;
}
/**
* @param surface of type SurfaceHolder
* @param gameView of type GameView
* Constructor function
* @since 13 Feb 2013
*/
public ViewUpdater()
{
}
/*
* (non-Javadoc)
* @see java.lang.Thread#run()
* @since Feb 13, 2013
* @author rajeshcp
*/
@Override
public void run() {
Canvas canvas;
while (run) {
canvas = null;
try {
surface = getHolder();
canvas = surface.lockCanvas(null);
synchronized (surface) {
onDraw(canvas);
}
} finally {
if (canvas != null) {
surface.unlockCanvasAndPost(canvas);
}
}
}
}
}
/**
* @author rajeshcp
* Class which will handle the touch
* events
* @since 19 Feb 2013
*/
private class InteractionListener extends Thread
{
ArrayList<MotionEvent> mEventQueue;
boolean mIsRunning = false;
/**
* @param of type null
* @return of type InteractionListener
* Constructor function
* @since Feb 19, 2013
* @author rajeshcp
*/
public InteractionListener()
{
init();
}
/**
* @param of type null
* @return of type null
* @since Feb 19, 2013
* @author rajeshcp
*/
private void init()
{
mIsRunning = true;
mEventQueue = new ArrayList<MotionEvent>();
}
/**
* @param event of type MotionEvent
* @return of type null
* function which will add the event to
* the mEventQueue
* @since Feb 19, 2013
* @author rajeshcp
*/
private void queueEvent(MotionEvent event)
{
mEventQueue.add(event);
}
/**
* @param event of type MotionEvent
* @return of type null
* function which will process the touch event
* @since Feb 19, 2013
* @author rajeshcp
*/
private void onTouch(MotionEvent event) {
if(event == null)
return;
if(mVelocityTracker == null)
{
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
if(!mViewArea.contains((int)event.getX(), (int)event.getY()))
{
return;
}
switch(event.getAction())
{
case MotionEvent.ACTION_DOWN :
{
if(mValueanimator != null)
{
mValueanimator.cancel();
}
isScrolled = false;
mInitialTouchX = (int)event.getX();
break;
}
case MotionEvent.ACTION_MOVE :
{
final int currentX = (int)event.getX();
final int draggedDistance = (currentX - mInitialTouchX);
if(draggedDistance != 0 && draggedDistance % mDragInterWell == 0)
{
isScrolled = true;
initiateFrameChange(draggedDistance/mDragInterWell);
Log.d(getClass().getName(), "frameIndex = " + mCurrentFrameIndex);
mInitialTouchX = currentX;
}
break;
}
case MotionEvent.ACTION_UP :
{
if(isScrolled)
{
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
int velocityX = (int) velocityTracker.getXVelocity();
if((velocityX > mSnapVelocity) || (velocityX < -mSnapVelocity))
{
initiateFling(velocityX);
}
}
onTouchEnd();
break;
}
case MotionEvent.ACTION_CANCEL :
{
onTouchEnd();
break;
}
default :
{
break;
}
}
}
/* (non-Javadoc)
* @see java.lang.Thread#run()
* @since Feb 19, 2013
* @author rajeshcp
*/
@Override
public void run() {
while (mIsRunning) {
while (mEventQueue.size() > 0) {
onTouch(mEventQueue.remove(0));
try
{
Thread.sleep(16);
}catch (Exception e) {
}
}
}
}
}
}
어디에서 잘못하고 있는지 정확히 지적 할 수 있습니까? 렌더링에서 지연의 주원인이되는 이유는 무엇입니까? 로컬 자원의 이미지를로드 할 수있는 모든 것이이 지연의 원인 일 수있는 모든 것을 시도했습니다.이 경우 어떻게 지연을 없앨 수 있습니까? – Triode
SurfaceView의 한계는 비트 맵을 처리하는 중에 많은 일을하는 것으로 생각하면 시간이 많이 걸릴 것입니다. 비트 맵의 작업은 처리해야하는 픽셀 수 (해상도)에 비례하기 때문에. 당신이 뭔가 잘못하고 있다고 말하면 안되지만 잘못된 접근법을 사용하고 있습니다. – JoxTraex
http://stackoverflow.com/questions/1039393/iphone-app-png-sequence-animation-how-to-use-opengle-optimally-without-crashin하지만 이것은 IPhone의 경우입니다. – Triode