2011-04-10 64 views
13

我有一系列的靜止圖像和共500多個圖像呈現在可繪製目錄中。我需要製作一個動畫(每秒載入大約20張圖片)。我希望它運行平穩,沒有內存異常。Android:從靜止圖像製作動畫

我想過要做到這一點,圖像2至3秒(40至60圖像)應該加載內存和顯示,然後他們應該放棄(釋放內存),然後圖像接下來的2到3秒應該加載。這種技術可以防止內存異常。它只是一個想法,我不知道它是否是一個好主意。請引導我一些更好的想法與一些代碼去...如果我的想法是更好,可以工作,那麼請告訴我一些幫助代碼來做到這一點。

閱讀答覆,做你的建議後,我已經寫了一些這樣的代碼:

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:id="@+id/llMain"> 

<ViewFlipper android:id="@+id/imageflipper" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" > 
<ImageView android:id="@+id/ImageView01" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent"   
     android:scaleType="centerInside"   
     android:layout_gravity="center" /> 
    </ViewFlipper> 
    </LinearLayout> 

這裏是我做的動畫代碼:

public class Animation extends Activity { 
ViewFlipper flipper; 
int myIndex = 216; 
private final Handler handler = new Handler(); 
/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    flipper=(ViewFlipper)findViewById(R.id.imageflipper); 
    doTheAutoRefresh(); 
     //displayData(); 
} 

private void doTheAutoRefresh() { 
    handler.postDelayed(new Runnable() { 
     public void run(){ 
      displayData(); // this is where you put your refresh code 
      doTheAutoRefresh(); 
      } 
     }, 30); 

} 

private void displayData() 
{ 
    Resources r = getResources(); 
    if(myIndex > 230){ 
     myIndex = 216; 
     ImageView myImg = (ImageView)findViewById(R.id.ImageView01); 
     myImg.setImageResource(r.getIdentifier("drum0" + myIndex, "drawable", "com.vt.animation")); 

     myIndex += 1; 
     flipper.showNext(); 
    } 
    else{ 
     ImageView myImg = (ImageView)findViewById(R.id.ImageView01); 

     myImg.setImageResource(r.getIdentifier("drum0" + myIndex, "drawable", "com.vt.animation")); 

     myIndex += 1; 
     flipper.showNext(); 
    } 
} 

}

但它非常緩慢。我將刷新時間設置爲30毫秒,但實際上刷新時間並不快,而刷新時間大約爲1秒。任何建議讓它快速感覺像真正的動畫?

謝謝,

回答

18

好的。在這麼多天之後,我遇到了最大的問題和最簡單的解決方案。我永遠不會期望它會這麼容易做...:D

我已經使用處理程序和定時器來實現只有一個圖像視圖,沒有鰭狀肢,沒有動畫師沒有其他的東西......在這裏是我的解決方案:

----- main。xml文件-----

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:orientation="vertical" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:background="@drawable/background"> 

<ImageView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:id="@+id/imageView1"> 
</ImageView> 

這裏是我做的方式:}

public class MainActivity extends Activity { 
private ImageView _imagView; 
private Timer _timer; 
private int _index; 
private MyHandler handler; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    handler= new MyHandler(); 
    _imagView=(ImageView) findViewById(R.id.imageView1); 

    _index=0; 
    _timer= new Timer(); 
    _timer.schedule(new TickClass(), 500, 200); 
} 

private class TickClass extends TimerTask 
{ 
    @Override 
    public void run() { 
     // TODO Auto-generated method stub 
     handler.sendEmptyMessage(_index); 
     _index++; 
    } 
} 

private class MyHandler extends Handler 
{ 
    @Override 
    public void handleMessage(Message msg) { 
     // TODO Auto-generated method stub 
     super.handleMessage(msg); 

     try { 
       Bitmap bmp= BitmapFactory.decodeStream(MainActivity.this.getAssets().open("drum_"+_index+".png")); 
       _imagView.setImageBitmap(bmp); 

       Log.v("Loaing Image: ",_index+""); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.v("Exception in Handler ",e.getMessage()); 
     } 
    } 
} 

我已經放在我所有的圖像到資產目錄。

它的那麼簡單,因爲它可以,沒有什麼大的做...

我希望這將是爲找人去這樣:)

+0

@Mudasser Hassan如果服務器端的所有圖像,我必須下載所有圖像,並做這種類型的工作。 (播放視頻或圖像動畫)。我怎麼能做到這一點。我需要像360度旋轉一個單一的圖像顯示所有圖像。像http://www.mathieusavard.info/threesixty/demo.html – 2015-03-04 11:57:48

+0

謝謝。如果所有圖像來自服務器,我們必須下載所有圖像並顯示。你有什麼想法嗎?我正面臨着這個問題。請幫忙。 – 2015-03-22 12:12:38

+0

如果你使用'Handler.post()',代碼會更短。另一個問題是,你在UI線程上解碼圖像,這並不好。更優雅的解決方案是預先解碼背景中的下一個圖像(使用'AsyncTask'),並在200 ms後或解碼後顯示它,如果它需要更多時間。 – Mixaz 2016-09-02 22:03:58

2

加載幾個圖像是非常昂貴的。

我認爲最好加載一個包含該動畫所有動作的圖像。動畫地帶。

private Bitmap animation = BitmapFactory.decodeResource(getResources(), R.drawable.myPng);

的想法是遍歷位圖。

+0

雪碧幫助別人是不是我的情況。我告訴你我有超過500張圖片。首先,我不能製作500張圖像,但是如果我製作的話,我認爲它不可能加載那個巨大的地帶,或者它不會是一個好方法...尋找一些更好的想法... – 2011-04-11 08:05:01

1

那麼,我使用viewFlipper,切換視圖。這一個好東西,就是你可以看到前面的圖像滑出,而新的幻燈片

內部圖像顯示方法:

if (direction == NEXT) { 
     viewFlipper.setInAnimation(slideLeftIn); 
     viewFlipper.setOutAnimation(slideLeftOut); 

     if (currImg < max) 
      currImg++; 
     if (currImg == max) 
      currImg = 0; 

     if (currentView == 0) { 
      currentView = 1; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView02); 
      iv.setImageResource(images[currImg]); 
     } else if (currentView == 1) { 
      currentView = 2; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView03); 
      iv.setImageResource(images[currImg]); 
     } else { 
      currentView = 0; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView01); 
      iv.setImageResource(images[currImg]); 
     } 
     viewFlipper.showNext(); 
    } 
    else if (direction == PREV) { 
     viewFlipper.setInAnimation(slideRightIn); 
     viewFlipper.setOutAnimation(slideRightOut); 

     if (currImg > 0) 
      currImg--; 
     else if (currImg <= 0) 
      currImg = (max-1); 

     if (currentView == 0) { 
      currentView = 2; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView03); 
      iv.setImageResource(images[currImg]); 
     } else if (currentView == 2) { 
      currentView = 1; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView02); 
      iv.setImageResource(images[currImg]); 
     } else { 
      currentView = 0; 
      ImageView iv = (ImageView) findViewById(R.id.ImageView01); 
      iv.setImageResource(images[currImg]); 
     } 
     viewFlipper.showPrevious(); 

和XML文件中:

 <ViewFlipper android:id="@+id/imageflipper" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" > 

     <ImageView android:id="@+id/ImageView01" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"   
      android:scaleType="centerInside"   
      android:layout_gravity="center" /> 

     <ImageView android:id="@+id/ImageView02" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"   
      android:scaleType="centerInside"   
      android:layout_gravity="center" /> 

     <ImageView android:id="@+id/ImageView03" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content"   
      android:scaleType="centerInside"   
      android:layout_gravity="center" /> 

     </ViewFlipper> 
+0

還有2件事情我很困惑。 1,回收碼在哪裏?你如何回收舊圖像並加載新圖像?第二,我想製作一個動畫,而不是向左或向右翻轉圖像,而不是平滑的動畫(新圖像加載和舊圖像自動卸載)...我是Android新手,也不太瞭解JAVA。任何代碼示例將真正有幫助和讚賞... :) – 2011-04-12 07:03:54

+0

那麼,Java有垃圾收集器,所以你不必手動釋放內存,如iphone等obj-c。你可以使用system.gc()強制啓動垃圾收集器。 iv.setImageResource()正在改變imageview中的圖像,並且我聲明瞭將用於動畫切換的2個動畫(用於新舊圖片)。如果你想自動動畫,而不是手勢,只需添加一些計時器,並使用上述方法,如每2秒或平方毫米。 Ofc,從xml聲明動畫並保持方向的值(在我的情況下,我需要NEXT或PREV)。 – yosh 2011-04-12 09:03:02

+0

我已經做了一些事情,閱讀你的代碼,並在其他帖子/網站上探索更多。我編輯了我的問題,並添加了我的代碼。它的清爽太慢了。我想讓它感覺像真正的動畫非常快。任何建議?謝謝 – 2011-04-13 13:08:59

30

使用一個FrameAnimation,例如在res/drawable/movie.xml

<?xml version="1.0" encoding="utf-8"?> 
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" 
    android:oneshot="true"> 
    <item android:drawable="@drawable/frame1" android:duration="50" /> 
    <item android:drawable="@drawable/frame2" android:duration="50" /> 
    <item android:drawable="@drawable/frame3" android:duration="50" /> 
    etc... 
</animation-list> 

然後在Java:

imageView.setBackgroundResource(R.drawable.movie); 
AnimationDrawable anim = (AnimationDrawable) imageView.getBackground(); 
anim.start(); 
+1

它可以用於沒有OutOfMemoryException的500張圖片嗎?在繪製每個圖像後它會調用gc()嗎?以及暫停/恢復/停止/播放的東西?我可以使用這種方法來實現這些功能嗎? – 2011-04-14 05:20:19

+0

我還沒有嘗試過這麼多的圖片,但它是由Android框架處理的,所以它應該很聰明。我很確定它能很好地處理內存。也就是說,這對於一個完整的視頻來說可能是不夠的......爲什麼不將視頻轉化爲視頻,將其放入res/raw中,然後使用MediaPlayer播放:這很容易,再加上它暫停,玩,尋求和所有。壓縮會更好,可能會好得多... – olivierg 2011-04-14 08:08:42

+0

非常感謝。視頻無法解決我的問題我認爲,因爲我試圖開發一些應用程序,如說話的聖誕老人。你可以在這裏查看[鏈接](http://www.appbrain.com/app/talking-santa-free/com.outfit7.talkingsantafree) – 2011-04-14 08:46:36