0

基本的に360度の回転をシミュレートするために、ドローアブルに保存されている車のさまざまな画像をロードする必要があります。ユーザーがビューをドラッグするたびに、ユーザーがビューを横切るとドラッグ距離を設定し、次のフレームをロードします。サーフェスビューを使用して、キャンバス上に画像を描画しています。画像が大きすぎるため、一度にすべての画像をメモリにロードすることはできません。そのため、現在の画像のみをメモリに保持して、その場で画像をロードしています。しかし、このアプローチは遅すぎます。私が間違っていることを誰かが指摘できますか?または同じことを達成するための他のより良い方法。ご協力いただきありがとうございます。

これは私のコードです

/ ** * @authorrajeshcp*ビューのトップビューとして機能するクラス*CarDetailsActivityの階層*@2013年2月13日以降*/

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) {
                }
            }

        }
    }

}
}
4

1 に答える 1

1

シミュレートされた360度のビューを表示しようとすると複雑になるため、OpenGLを使用してこのレンダリングを処理することを検討することをお勧めします。これにより、コンテンツの表示方法が大幅に強化され、実装が簡素化されます。

でも; そもそもこれが単純な実装であると言っているわけではありません。しかし、それはこのようなものを実装するための最良の方法でしょう。

于 2013-02-19T18:45:10.553 に答える