2013-02-19 3 views
0

기본적으로 드로어 블에 저장되는 자동차의 다른 이미지를로드해야합니다. 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) { 
       } 
      } 

     } 
    } 

} 
} 

답변

1

시뮬레이션 된 360도보기를 표시하려는 복잡성 때문에이 렌더링을 처리하기 위해 OpenGL을 사용하는 것이 좋습니다. 이렇게하면 콘텐츠가 표시되는 방식에 훨씬 많은 힘을 줄 수 있으며 구현이 단순 해집니다.

그러나; 그것은 이것이 간단한 구현이라는 것을 말하는 것이 아닙니다. 그러나 이와 같은 것을 구현하는 것이 가장 좋은 방법 일 것입니다.

+0

어디에서 잘못하고 있는지 정확히 지적 할 수 있습니까? 렌더링에서 지연의 주원인이되는 이유는 무엇입니까? 로컬 자원의 이미지를로드 할 수있는 모든 것이이 지연의 원인 일 수있는 모든 것을 시도했습니다.이 경우 어떻게 지연을 없앨 수 있습니까? – Triode

+1

SurfaceView의 한계는 비트 맵을 처리하는 중에 많은 일을하는 것으로 생각하면 시간이 많이 걸릴 것입니다. 비트 맵의 ​​작업은 처리해야하는 픽셀 수 (해상도)에 비례하기 때문에. 당신이 뭔가 잘못하고 있다고 말하면 안되지만 잘못된 접근법을 사용하고 있습니다. – JoxTraex

+0

http://stackoverflow.com/questions/1039393/iphone-app-png-sequence-animation-how-to-use-opengle-optimally-without-crashin하지만 이것은 IPhone의 경우입니다. – Triode

관련 문제