2011-10-04 85 views
0

Loooong時間查看器,終於輪到在這裏註冊StackOverflow!自定義動畫可繪製電池消耗

經過很長的時間尋找一種方式做在Android上的ViewGroup的滾動背景,我已經開發了以下內容:

public class SlidingDrawable extends Drawable implements Drawable.Callback { 
private static final String TAG = "SlidingDraw"; 
private static float STEP_SIZE = 1.0f; 

private BitmapDrawable mBitmap; 
private Context mContext; 

private float mPosX; 
private int mBitmapWidth; 

private Runnable mInvalidater; 
private Handler mHandler; 

public SlidingDrawable(Context c){ 
    mContext = c; 

    // use this as the callback as we're implementing the interface 
    setCallback(this); 

    mHandler = new Handler(); 
    mInvalidater = new Runnable(){ 
     @Override 
     public void run(){ 
      // decrement the drawables step size 
      mPosX -= SlidingDrawable.STEP_SIZE; 

      /* 
      * Check to see if the current position is at point where it should 
      * loop. If so, reset back to 0 to restart 
      */ 
      if(Math.abs(mPosX) >= mBitmapWidth) mPosX = 0; 
      // redraw 
      invalidateDrawable(null); 
     } 
    }; 
} 
public static void setStepSize(float newSize){ 
    SlidingDrawable.STEP_SIZE = newSize; 
} 
public void createBitmap(String path, ViewGroup parent){ 
    // height of the parent container 
    int height = parent.getHeight(); 

    /* Initialize local variables 
    * bgBitmap - the resulting bitmap to send into SlidingDrawable instance 
    * imageStream - raw bitmap data to be decoded into bgBitmap 
    */  
    WindowManager wMgr = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 
    int mScreenWidth = wMgr.getDefaultDisplay().getWidth(); 

    InputStream imageStream; 
    Matrix imgMatrix = new Matrix(); 
    Bitmap bitmap = null; 
    try { 
     imageStream = mContext.getAssets().open(path); 

     // create a temporary bitmap object for basic data 
     Bitmap temp = BitmapFactory.decodeStream(imageStream); 
     int width = temp.getWidth(); 

     // find the width difference as a percentage to apply to the 
     // transformation matrix 
     float widthDifference = ((float)mScreenWidth)/(float)(width/2); 
     imgMatrix.postScale(widthDifference, 0, 0f, 0f); 

     // create a copy of the bitmap, scaled correctly to maintain loop 
     bitmap = Bitmap.createScaledBitmap(temp, (int)(width * widthDifference), height, true); 

     // recycle the temp bitmap 
     temp.recycle(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    mBitmap = new BitmapDrawable(bitmap); 

    // required 
    mBitmapWidth = getIntrinsicWidth()/2; 
    Rect bounds = new Rect(0, 0, getIntrinsicWidth(), getIntrinsicHeight());   
    setBounds(bounds); 
} 
@Override 
public void draw(Canvas canvas) { 
    canvas.drawBitmap(mBitmap.getBitmap(), mPosX, 0f, null); 
    scheduleDrawable(this, mInvalidater, SystemClock.uptimeMillis()); 
} 
@Override 
public int getOpacity() { 
    return PixelFormat.OPAQUE; 
} 

@Override 
public void scheduleDrawable(Drawable who, Runnable what, long when) { 
    mHandler.postAtTime(what, who, when); 
} 

@Override 
public void unscheduleDrawable(Drawable who, Runnable what) { 
    mHandler.removeCallbacks(what, who); 
} 
@Override 
public void invalidateDrawable(Drawable who) { 
    invalidateSelf(); 
} 
/* 
* Methods not directly used or called omitted 
* 
*/ 

}

它在活動等中使用所以:

@Override 
public void onWindowFocusChanged(boolean focus){ 
    // set the background of the root view of main.xml 
    SlidingDrawable drawable = new SlidingDrawable(getApplicationContext()); 
    drawable.createBitmap("bgimg/basebg.jpg", mRoot); 
    mRoot.setBackgroundDrawable(drawable); 
} 

長話短說,basebg.jpg圖像是一個大致1600x480的圖像圖像。 SlidingDrawable的構造函數用於縮放和移動yaddah yaddah。有用。

現在,問題是,這樣做似乎效率低下。我似乎無法找到關於這種實現的很多信息,所以我在黑暗中我可以削減CPU週期,或者即使我正確使用方法調用。

我的問題包括:

  • 是更好地drawBitmap而不是使用setTranslate()或的postTranslate和借鑑使用矩陣位圖?
  • 使用drawBitmap還是使用諸如translate(),save()和restore()之類的畫布函數會更好嗎?
  • draw()方法被調用的速率是多少,並且有沒有辦法將它限制爲24 FPS o limit redraws?
  • 這些東西的「何時」參數到底是什麼?傳遞SystemClock.uptimeMillis()是唯一有效的工作,並試圖通過添加一個「+ 100」或每隔100毫秒觸發一次來延遲它就會造成口吃。

,我可以......我把它留給StackOverflow的現在:)

回答

0

一段時間後,用繪圖板,我儘可能多的研究這個問題,我簡單的功能了。實質上,它每SystemClock.uptimeMillis()發送一個invalidate()呼叫,爲每一步更改做一次重繪。

因此,我刪除了Drawable.Callback接口並直接從處理程序傳遞了invalidateSelf()調用,刪除了中間接口方法,這似乎沒有做任何特別的事情。

有使用 drawBitmap(Bitmap source, int X, int Y, Paint p)drawBitmap(Bitmap source, Matrix matrix, Paint p)在CPU使用率稍有差異,所以選擇了後者,以節省週期。

新方法如下:

// Runnable 
mInvalidater = new Runnable(){ 
    @Override 
    public void run(){ 
     // decrement the drawables step size 
     mPosX -= SlidingDrawable.STEP_SIZE; 
     if(Math.abs(mPosX) >= mBitmapWidth){ 
      mPosX = 0; 
      mImageMatrix.setTranslate(0, 0); 
     } 
     mImageMatrix.postTranslate(-STEP_SIZE, 0); 
     SlidingDrawable.this.invalidateSelf(); 
    } 
}; 
// Draw method 
@Override 
public void draw(Canvas canvas) { 
    canvas.drawBitmap(mBitmap.getBitmap(), mImageMatrix, null); 
    mHandler.postAtTime(mInvalidater, SystemClock.uptimeMillis() + 64); 
} 

我拔掉了電話,1分鐘左右運行應用,然後打開我的摩托Droid的電池使用測試電池的結果。之前,電池使用超過了顯示器,現在它舒適地位於下方。在一些情況下,我的應用程序坐在憤怒的小鳥下面,但並不總是如此,憤怒的小鳥也是一個基準,它通過運行開始屏幕(其中bg卷軸和小鳥到處飛)。

CPU使用率使用ADB shell命令dumpsys cpuinfo進行檢查,因爲在運行2.2的設備上通過DDMS似乎存在問題viewing CPU info

我仍然可以聽到關於此的其他想法,但現在,它已經解決了。