2013-07-12 2 views
12

많은 이미지 위에 선을 그려주는 앱을 개발 중입니다. 이러한 이미지를 선택하려면 라디오 그룹이 있고 사용자가 라디오 버튼을 클릭 할 때마다 이미지에 모든 자체 드로잉이로드됩니다. 내 라디오 listenner에서ImageView가 Android에 완전히로드 될 때 얻는 방법

나는 다음과 같은 코드가 있습니다

bitmap = BitmapUtils.decodeSampledBitmapFromResource(root + DefinesAndroid.CAMINHO_SHOPPINGS_SDCARD + nomeImagemAtual, size.x, size.y); 
mImage.setImageBitmap(bitmap); 

mImage.setDrawLines(true); 
mImage.setImageBitmap(loadBitmapFromView(mImage)); 

나는 안드로이드 개발자에이 링크에서받은 decodeSampledBitmapFromResource 방법은 (더 effitiently 비트 맵을로드) 여기 http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

과 내가 전화하는 방법입니다 나는 임을 사용하고 있기 때문에

public static Bitmap loadBitmapFromView(View v) { 
     Bitmap b = Bitmap.createBitmap(v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.ARGB_8888);     
     Canvas c = new Canvas(b); 
     v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height); 
     v.draw(c); 
     return b; 
} 

내가 mImage의 이미지 비트 맵을 설정하고있어 뷰의 비트 맵을 얻기 위해 ageViewTouch 라이브러리 (ImageView를 통해 확대/축소를 가능하게 함)를 사용하지 않으면 확대/축소와 같은 모든 상호 작용을 통해 모든 캔버스 드로잉이 삭제됩니다.

오류 로그 내가 getBitmapFromView 메서드를 호출 할 때 이미지 비트 맵이 완전히로드되지 않습니다 원인이 오류가 발생하는 것을 거의 확신 다음

07-11 21:13:41.567: E/AndroidRuntime(20056): java.lang.IllegalArgumentException: width and height must be > 0 
07-11 21:13:41.567: E/AndroidRuntime(20056): at android.graphics.Bitmap.createBitmap(Bitmap.java:638) 
07-11 21:13:41.567: E/AndroidRuntime(20056): at android.graphics.Bitmap.createBitmap(Bitmap.java:620) 

입니다.

보기가 완전히로드 된 시점을 어떻게 알 수 있습니까? 이러한 방식

+0

음 나는 당신이 당신의 코드에서 다시 나를 설명 할 수없는? 처음 ImageImageBitmap을 설정했습니다. 왜 그것을 두 번째로 설정하고보기에서 높이 및 높이를 원하십니까? –

+0

처음으로 이미지를 깨끗하게로드하는 것입니다 (도면이없는 경우). 그런 다음 setDrawLines를 호출하여 이미지 위에 선을 그립니다. 일단 드로잉이 Canvas에 그려지면 이미지 + 드로잉의 고유 이미지 하나를 만들어야합니다. 두 번째로 imageBitmap을 호출하지만 이번에는 ,보기에서 비트 맵을 가져와야합니다 (도면에 그림이 있음) ..이 방법은 내가 함께 넣을 것입니다. –

+0

이것이 http://stackoverflow.com/questions/8831642/how-to-draw 인 것 같습니다. over-image-over-android는 당신이 원하는 것보다 더 많을 것입니다. –

답변

21

통화 loadBitmapFromView :

mImage.post(new Runnable() { 
    @Override 
    public void run() { 
     loadBitmapFromView(mImage); 
    } 
}); 

Runnablepost() 방법에 제공된 실제 폭과 높이를 반환보기 및 측정하고 설계 뒤에도 getWidth()getHeight() 및 실행한다.

당신이 할 수있는 다른 무엇, measure를 호출 한 다음 getMeasuredWidth()getMeasuredHeight()에서 결과를 고려하여, 수동으로 View을 측정한다. 그러나 나는이 방법을 추천하지 않는다.

+0

마침내 작동한다 !!! run() 메서드 내에서 setImageBitmap을 사용하면 모든 것이 잘되었습니다. 나는 그것을 매우 고맙게 생각한다! 내가 할 수 있다면 당신의 대답에 10 번 투표 할 것입니다! :) –

+0

펠리페 (Felipe)와 동의 ... 나는 오랜 시간 동안 비슷한 방법을 찾으려고 노력했다. 고맙습니다! – RiddlerDev

+1

@RiddlerDev는 'OnPreDrawListener'를 사용하여 다른 솔루션 (나에게 게시 됨)을 확인합니다. –

8

실제로는 ViewTreeObserver.OnPreDrawListener을 사용하여 신뢰할 수있는 또 다른 방법이 있습니다.

mImage.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){ 

    @Override 
    public boolean onPreDraw() { 
     try { 
      loadBitmapFromView(mImage);    
      return true; //note, that "true" is important, since you don't want drawing pass to be canceled 
     } finally { 
      mImage.getViewTreeObserver().removeOnPreDrawListener(this); //we don't need any further notifications 
     } 
    } 
}); 

모든 조회수가 이미 대부분 측정 layouted 때 View#post(Runnable) 그냥 Runnable을 실행하면서 View이 측정 layouted했다 것을 OnPreDrawListener보증을 사용 : 그리고 여기 예입니다.

+0

이것은 래그없이 작동하는 유일한 솔루션입니다. – Vyacheslav

1

다음은 Dmitry의 메서드를 위에 통합 한 작업 NotifyImageView 클래스이며 ImageView를 실제로 사용할 수있게 된 후에 만 ​​알리는 코드를 추가합니다.

유용하게 사용하시기 바랍니다.

`

public interface NotifyImageHolder { 
    public void notifyImageChanged(final NotifyImageView thePosterImage, final int width, final int height); 
} 

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.view.ViewTreeObserver; 
import android.widget.ImageView; 

public class NotifyImageView extends ImageView { 
    private boolean mImageChanged; 
    private NotifyImageHolder mHolder; 
    private boolean mImageFinished; 

    public NotifyImageView(Context context) { 
     super(context); 
     init(); 
    } 

    public NotifyImageView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public NotifyImageView(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(); 
    } 

    protected void init() { 
     mImageChanged = false; 
     mImageFinished = false; 
     mHolder = null; 
     monitorPreDraw(); 
    } 

    // so we can tell when the image finishes loading.. 
    protected void monitorPreDraw() { 
     final NotifyImageView thePosterImage = this; 
     getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 

      @Override 
      public boolean onPreDraw() { 
       try { 
        return true; //note, that "true" is important, since you don't want drawing pass to be canceled 
       } finally { 
        getViewTreeObserver().removeOnPreDrawListener(this); // we don't need any further notifications 
        thePosterImage.buildDrawingCache(); 
        mImageFinished = true; 
       } 
      } 
     }); 
    } 

    public void setNotifyImageHolder(NotifyImageHolder holder) { 
     this.mHolder = holder; 
    } 

    public boolean isImageChanged() { 
     return mImageChanged; 
    } 

    public boolean isImageFinished() { 
     return mImageFinished; 
    } 

    public void notifyOff() { 
     mHolder = null; 
    } 

    // the change notify happens here.. 
    @Override 
    public void setImageDrawable(Drawable noPosterImage) { 
     super.setImageDrawable(noPosterImage); 
     if (mHolder != null && mImageFinished) { 
      mImageFinished = false; // we send a single change-notification only 
      final NotifyImageView theNotifyImageView = this; 

      theNotifyImageView.post(new Runnable() { 
       @Override 
       public void run() { 
        if (mHolder != null) { 
         int width = getMeasuredWidth(); 
         int height = getMeasuredHeight(); 
         mImageChanged = true; 
         mHolder.notifyImageChanged(theNotifyImageView, width, height); 
        } 
       } 
      }); 

     } 
    } 

} 

`

+0

실제로 뷰 트리 옵저버를 사용할 필요는 없습니다. 뷰 구현에 대한 전체 액세스 권한을 갖고 있으므로'onDraw()'메소드에서 크기를 얻을 수 있습니다. –

관련 문제