2011-04-10 4 views
13

나는 drawable 디렉토리에 표시된 일련의 정지 이미지와 총 500 개 이상의 이미지를 가지고 있습니다. 애니메이션 (초당 약 20 이미지로드)을 만들어야합니다. Out of Memory Exception없이 원활하게 실행되기를 바랍니다.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

저는 이미지 뷰, 플리퍼, 애니메이터를 전혀 사용하지 않기 위해 핸들러와 타이머를 모두 사용했습니다 ... 여기 내 해결책은 다음과 같습니다.

----- 주.

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()); 
     } 
    } 
} 

}

참고 : 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> 
내가 그것을했을 방법입니다 내가 배치 한
내 모든 이미지를 자산 디렉토리에 저장하십시오.

그것 할 수있는 큰 아무것도, 그것을 할 수있는 간단을 ...

가 나는 그것이이

+0

@ Mudasser Hassan 서버 측의 모든 이미지가 있으면 모든 이미지를 다운로드하고 해당 유형의 작업을 수행해야합니다. (비디오 또는 이미지 애니 메이팅 재생). 어떻게해야합니까? 360도 회전과 같은 모든 이미지가 단일 이미지를 회전시켜야합니다. http://www.mathieusavard.info/threesixty/demo.html –

+0

고마워요. 모든 이미지가 서버에서 온 것이므로 모든 이미지를 다운로드하여 표시해야합니다. 생각 좀 해봤 니? 나는 그 문제에 직면하고있다. 도와주세요. –

+0

'Handler.post()'를 사용하면 코드가 더 짧아집니다. 또 다른 문제는 UI 스레드에서 이미지를 디코딩한다는 것입니다.좀 더 우아한 해결책은 미리 백그라운드에서 다음 이미지를 디코딩하고 (AsyncTask를 사용하여) 200ms가 지난 후 또는 이미지가 디코딩 된 후에 표시하는 것입니다. – Mixaz

2

여러 이미지를로드하는 것은 매우 비쌉니다.

특정 애니메이션의 모든 동작을 포함하는 단일 이미지를로드하는 것이 더 좋습니다. 애니메이션 스트립.

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

아이디어는 비트 맵을 통과하는 것입니다.

+0

스프라이트를 :)처럼 이동하고자하는 사람에게 도움이 될 바랍니다 나의 아니다. 나는 내가 500 개가 넘는 이미지를 가지고 있다고 말했다. 첫째, 나는 500 장의 이미지를 만들 수 없다. 그러나 만약 내가 만든다면 그 거대한 스트립을 넣을 수 없거나 좋은 접근법이 될 수 없다고 생각한다. ... 더 좋은 아이디어를 찾고 ... –

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 가지가있다. 나는 혼란 스럽다. 첫째, 재활용 코드는 어디에 있습니까? 어떻게 이전 이미지를 재활용하고 새 이미지를로드합니까? 둘째, 나는 애니메이션을 만들고 싶다. 왼쪽 또는 오른쪽으로 약간 매끄러운 애니메이션 (새로운 이미지로드 및 오래된 이미지가 자동으로 언로드 됨)을 뒤집지 말라. ... 나는 Android에 익숙하지 않으며 JAVA에 대해 많이 모른다. 모든 코드 샘플은 정말 도움이 될 것입니다 ... :) –

+0

글쎄, 자바 가비지 컬렉터가 있으므로 수동으로 아이폰 등 obj-c 메모리를 해제 할 필요가 없습니다. 당신은 system.gc() 강제로 사용할 수 있습니다. 가비지 컬렉터를 시작하십시오. iv.setImageResource()는 imageview에서 이미지를 변경하고 스위치 애니메이션에 사용되는 2 개의 애니메이션 (이전 및 새 그림 용)을 선언합니다. 자동 애니메이션 대신 제스처를 사용하려면 몇 가지 타이머를 추가하고 매 2 초 또는 매월 같은 위의 방법을 사용하십시오. Ofc, xml에서 애니메이션을 선언하고 방향의 가치를 유지합니다 (제 경우에는 NEXT 또는 PREV가 필요했습니다). – yosh

+0

나는 당신의 코드를 읽고 다른 게시물/사이트에서 더 많은 것을 탐색 한 후에 뭔가를 해왔다. 내 질문을 편집하고 내 코드를 추가했습니다. 그 상쾌하게 toooooo 느립니다. 실제 애니메이션처럼 느껴지기를 원합니다. 어떠한 제안? 감사합니다 –

30

사용 FrameAnimationres/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> 

그 다음에 자바 :

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

OutOfMemoryException없이 500 이미지가 작동합니까? 각 이미지를 그린 후에 gc()를 호출합니까? PAUSE/RESUME/STOP/PLAY 같은 것들은 무엇입니까? 이 방법으로 이러한 기능을 만들 수 있습니까? –

+0

나는 많은 이미지를 시도하지는 않았지만 안드로이드 프레임 워크에 의해 처리되었으므로 현명해야한다. 나는 그것이 메모리를 훌륭하게 처리한다고 확신한다. 그렇다고 풀 프레임 비디오에 적합하지 않을 수도 있습니다 ... 이미지를 비디오로 변환하고 res/raw에 넣은 다음 MediaPlayer로 재생하면 어떨까요? 매우 쉽습니다. 재생, 추구하고 모든 것을. 그리고 압축은 더 나아질 것입니다, 아마도 훨씬 더 ... – olivierg

+0

고마워요. 비디오는 내 문제를 해결하지 못한다 나는 말하는 산타 같은 몇 가지 응용 프로그램을 개발하려하고 있다고 생각한다. 당신은 그것을 여기에서 확인할 수있다 [link] (http://www.appbrain.com/app/talking-santa-free/com.outfit7.talkingsantafree) –