안 드 로 이 드 이미지 로 딩 프레임 워 크 상세 설명 Fresco 기본 사용(2)

14859 단어 androidfresco
PS:최근 에 많은 사람들 이 연말 총결산 을 쓰기 시작 하 는 것 을 보 았 습 니 다.시간 이 빨리 지나 고 연말 이 되 었 습 니 다.또 한 살 이 되 었 습 니 다.
학습 내용:
1.진도 표
2.크기 조정
3.ControllerBuilder,ControllerListener,PostProcesser,Image Request
4.점진 적 JPEG 와 움 직 이 는 그림 표시
최근 이틀 동안 Fresco 의 공식 문 서 를 보면 차이 가 많 지 않 은 셈 이다.Fresco 의 기본 원리 와 okHttp 등 라 이브 러 리 를 결합 하여 어떻게 사용 하 는 지 에 대한 문제 만 남 았 다.비록 공식 문서 가 제시 한 기능 이 비교적 많 지만 예 를 들 어 사용자 정의 View,미리 보기 그림 표시 등 이다.이런 것들 은 나 도 대체적으로 대강 을 보 았 는데 실제 수요 가 그렇게 높 은 요구 가 없 을 것 이 라 고 생각한다.그래서 어떤 것들 은 제 가 여기 서 소개 하지 않 겠 습 니 다.상세 한 상황 은 공식 문 서 를 참고 할 수 있 습 니 다.저 는 사용 상황 이 비교적 많은 기능 에 대해 간단 한 소 개 를 할 뿐 입 니 다.
1.진도 표
진도 바 도 Fresco 의 한 기능 이 라 고 할 수 있 습 니 다.Fresco 내부 자체 에 Progress BarDrawable 류 를 제 공 했 습 니 다.효 과 는 사각형 의 파란색 진도 바 입 니 다.그림 이 로드 상태 에 있 을 때 진도 바 는 따라 로드 됩 니 다.그림 로드 가 끝 난 후에 진도 바 도 사라 집 니 다.그러나 이 진 도 는 실시 간 으로 업데이트 되 는 것 이 아 닙 니 다.만약 우리 가 정확 한 로드 진 도 를 원한 다 면,우 리 는 내부 의 방법 을 다시 써 야 한다.

class CustomProgressBar extends Drawable{

 @Override
 protected boolean onLevelChange(int level) {
  //doSomething
  return super.onLevelChange(level);
 }

}
사용자 정의 진도 바 는 onLevelChange 방법 을 실현 해 야 합 니 다.여기 서 간단 한 소개 만 할 수 있 습 니 다.진도 바 를 사용자 정의 하려 면 Progress BarDrawable 을 참조 하여 진도 바 를 다시 쓸 수 있 습 니 다.개인 적 으로 이 기능 이 별로 라 고 생각 합 니 다.그림 을 불 러 올 때 진도 바 를 사용 하 는 것 보다.ProgressBarImage 속성 을 사용 하여 그림 을 불 러 올 때 진행 그림 을 설정 하고 회전 속성 도 지원 합 니 다.
2.크기 조정
 DraweeView 의 크기 조정 과 ImageView 의 크기 조정 유형 은 기본적으로 같 습 니 다.fitXY,centerCrop.유일 하 게 ImageView 와 차이 가 있 는 것 은 matrix 속성 을 지원 하지 않 지만 matrix 속성 대신 focusCrop 속성 을 추 가 했 습 니 다.속성 을 설정 할 때,xml 는 fresco:actualcale Type 을 사용 하여 DraweeView 의 크기 조정 속성 을 설정 하거나 GenericDraweeHierarchy 속성 을 사용 하여 설정 합 니 다.

GenericDraweeHierarchyBuilder progressHierarchyBuilder = new GenericDraweeHierarchyBuilder(getResources());
GenericDraweeHierarchy progressHierarchy = progressHierarchyBuilder
    .setProgressBarImage(new ProgressBarDrawable(), ScalingUtils.ScaleType.CENTER_INSIDE)
    .build();
progressImageDraweeView.setHierarchy(progressHierarchy);
setScale Type()이나 xml 에서 android:scale Type 을 사용 하지 마 십시오.크기 조정 속성 을 설정 하 는 것 은 잘못 되 었 습 니 다.공식 적 으로 matrix 대신 focusCrop 을 제시 하 는 것 은 일리 가 있다.matrix 보다 효과 가 좋 을 것 이 라 고 말 하지만 효과 가 어떤 지 는 확실히 평가 할 수 없다.이 속성의 구체 적 인 작용 부터 말 해 봐.
 우 리 는 실제 수요 에서 이런 상황 을 만 날 수 있 습 니 다.사람의 얼굴 사진 을 표시 할 때 그림 을 가운데 로 표시 합 니 다.예전 에 저도 이런 수 요 를 만난 적 이 있 습 니 다.그러나 그 때 는 matrix 속성 으로 이 루어 졌 습 니 다.서버 는 우리 얼굴의 중심 좌표 위 치 를 전달 한 다음 에 클 라 이언 트 는 사람의 얼굴 중심 위치 에 따라 이미 지 를 평평 하 게 이동 해 야 합 니 다.그림 을 크기 조정 해 야 합 니 다.matrix 를 사용 하려 면 matrix.postscale()과 matrix.postTranslate()두 가지 방법 으로 이 루어 져 야 합 니 다.당시 의 처리 방식 을 간단히 붙이다. 

@Override
public void onLoadingComplete(String s, View view, Bitmap bitmap) {
 float bitmapWidth = bitmap.getWidth();
 float bitmapHeight = bitmap.getHeight();
 Scale[o] = (params[o].height / bitmapHeight >= params[o].width / bitmapWidth) ? params[o].height / bitmapHeight : params[o].width / bitmapWidth;
 float scaleBitmapWidth = Scale[o] * bitmapWidth;
 float scaleBitmapHeight = Scale[o] * bitmapHeight;
 Matrix matrix = new Matrix();
 matrix.postScale(Scale[o], Scale[o]);
 if (scaleBitmapWidth > scaleBitmapHeight) { //   
  if (imagedata.get(o).getFace_center_x() == 0 && imagedata.get(o).getFace_center_y() == 0) {
   if(scaleBitmapWidth - params[o].width < 0.5 * scaleBitmapWidth - params[o].width / 2){
    matrix.postTranslate( params[o].width - scaleBitmapWidth ,0);
   }else{
    matrix.postTranslate(-(0.5f * scaleBitmapWidth - params[o].width / 2), 0);
   }
  } else {
   if(scaleBitmapWidth - params[o].width < scaleBitmapWidth * imagedata.get(o).getFace_center_x() - params[o].width / 2) {
    matrix.postTranslate(params[o].width - scaleBitmapWidth, 0);
   } else {
    if (scaleBitmapWidth * imagedata.get(o).getFace_center_x() - params[o].width / 2 < 0) {
     matrix.postTranslate(0, 0);
    } else {
     matrix.postTranslate(-(scaleBitmapWidth * imagedata.get(o).getFace_center_x() - params[o].width / 2), 0);
    }
   }
  }
 } else { //   
  if (imagedata.get(o).getFace_center_x() == 0 && imagedata.get(o).getFace_center_y() == 0) {
   if(scaleBitmapHeight - params[o].height < 0.5 * scaleBitmapHeight - params[o].height / 2){
    matrix.postTranslate(0, params[o].height - scaleBitmapHeight);
   }else{
    matrix.postTranslate(0,-(0.5f * scaleBitmapHeight - params[o].height / 2));
   }
  } else {
   if (scaleBitmapHeight - params[o].height < scaleBitmapHeight * imagedata.get(o).getFace_center_y() - params[o].height / 2) {
    matrix.postTranslate(0, params[o].height - scaleBitmapHeight);
   } else {
    if (scaleBitmapHeight * imagedata.get(o).getFace_center_y() - params[o].height / 2 < 0) {
     matrix.postTranslate(0, 0);
    } else {
     matrix.postTranslate(0, -(scaleBitmapHeight * imagedata.get(o).getFace_center_y() - params[o].height / 2));
    }
   }
  }
 }
 vh.image[o].setImageMatrix(matrix);
}         

 이 형식 은 정말 아프다.이것 이 바로 그 당시 에 우리 의 실제 프로젝트 수 요 였 다.그 당시 에 GridView 였 는데 그 중 한 줄 에 세 장의 그림 이 있 었 다.세 장의 그림 을 동시에 제어 해 야 했다.만약 에 사람 사진 이 라면 두상 을 중앙 으로 옮 겨 야 했다.만약 에 사람 사진 이 아니라면 중앙 위 치 를 표시 하면 된다.그 당시 에 실현 한 것 은 매우 번 거 로 웠 다.너비 그림 과 높이 그림 을 판단 하 였 습 니 다.그림 은 너비 그림 과 높이 그림 으로 나 뉘 기 때문에 크기 조정 비율 을 계산 할 때 이들 에 대한 판단 이 필요 합 니 다.크기 조정 비율의 계산=실제 표 시 된 사이즈/그림 의 실제 크기 는 그림 에 따라 크기 조정 비율 을 설정 해 야 합 니 다.과도 한 크기 조정 문제 가 발생 하지 않 으 며,동시에 평평 하 게 이동 하 는 사 이 즈 는 과도 해 서 는 안 된다.
 예 를 들 어 우리 ImageView 의 실제 디 스 플레이 폭 은 100 입 니 다.우 리 는 그림 을 크기 조정 했 습 니 다.크기 를 조정 한 후에 그림 의 폭 은 110 입 니 다.그러면 우리 가 이동 할 수 있 는 최대 거 리 는 10 개의 단위 입 니 다.10 개의 단 위 를 초과 해 서 는 안 됩 니 다.그렇지 않 으 면 표시 할 때 문제 가 발생 할 수 있 습 니 다.그리고 우 리 는 그림 을 가능 한 한 가운데 로 표시 해 야 한다.즉,가능 한 한 그림 을 손실 시 키 는 단 위 를 작 게 해 야 한다.그러면 우 리 는 그림 을 5 개 단위 로 옮 길 수 밖 에 없다.즉,좌우 양쪽 에 각각 5 개 단 위 를 손실 하 는 것 이다.이런 표 시 는 완전히 한쪽 으로 치 우 쳐 10 개 단 위 를 손실 하 는 것 보다 훨씬 좋다.여기 서 볼 수 있 듯 이 matrix 를 사용 하 는 것 은 매우 복잡 하 다.또한 이곳 의 코드 는 최적화 할 수 있 지만 최적화 가 끝 난 후에 도 사실은 비교적 번거롭다.
 만약 우리 가 Fresco 의 focusCrop 속성 을 사용한다 면 일 은 매우 간단 해 질 것 이다.

fresco:actualImageScaleType="focusCrop"
xml 에서 크기 조정 형식 을 focusCrop 으로 설정 한 다음 자바 코드 에 설정 합 니 다.

PointF focusPoint;
// your app populates the focus point
mSimpleDraweeView
 .getHierarchy()
 .setActualImageFocusPoint(focusPoint);
여기 서 focusPoint 는 바로 우리 중심 점 의 상대 적 인 위치 입 니 다.float 유형,(0.5,0.5)은 centerCrop 중앙 위치 에 해당 합 니 다.(1.0,1.0)즉 그림 의 맨 아래 에 있 는 위치 입 니 다.그러면 사람 사진 을 표시 할 때 문제 가 매우 가 볍 고 이미지 중심 에 있 는 상대 적 인 위치 만 전달 하면 프레스 코 는 자동 으로 좌표 점 을 중심 으로 표 시 됩 니 다.보아하니 꽤 간단 한 것 같다.
 가끔 은 기 존의 Scale Type 이 당신 의 요구 에 부합 되 지 않 을 때 가 있 습 니 다.저 희 는 Scaling Utils.Scale Type 을 실현 하여 확장 할 수 있 습 니 다.이 인터페이스 에는 하나의 방법 만 있 습 니 다.getTransform 은 다음 과 같은 매개 변 수 를 바탕 으로 행렬 을 계산 하고 공식 적 으로 제 시 된 예 를 간단하게 설명 합 니 다.
 
공식 적 인 예 는 바로 이 렇 습 니 다.실제 View 에 사 이 즈 를 표시 한 다음 에 그림 의 디 스 플레이 사 이 즈 를 주 었 습 니 다.만약 에 그림 을 직접 깔 면 그림 이 완전 하 게 표 시 될 수 있 지만 픽 셀 점 이 손실 되 었 습 니 다.그러면 이 때 는 너비 의 줄 크기 를 400 으로 조정 해 야 합 니 다.그러면 이때 가로 로 화면 에 완전히 표시 할 수 있 습 니 다.그러나 높이 는 낮 아 졌 고 그림 은 210 에서 200 으로 바 뀌 었 으 나 실제 표 시 된 높이 는 300 이다.이때 fitCenter 를 사용 하여 너비 와 높이 를 유지 하고 축소 하거나 확대 하여 그림 을 표시 경계 에 완전히 표시 하고 너비 나 높이 가 일치 하 게 경 계 를 표시 한다.가운데 보이 기.전체적으로 차이 가 많 지 않다 는 것 이 바로 이 뜻 이다.그러나 자신 은 의미 가 없다 고 느 꼈 다.높이 는 확실히 축소 되 었 지만 너비 도 축소 되 었 다.그러면 너 비 는 픽 셀 을 잃 게 될 것 이다.확 대 된 픽 셀 에 불과 합 니 다.
여기 가 바로 공식 적 으로 제시 한 예 입 니 다.여기 서 min 이 표시 하 는 것 이 가장 작 아야 합 니 다.공식 번역 은 가장 큰 것 입 니 다.아래 의 방법 을 구체 적 으로 연구 하지 않 았 기 때문에 느낌 과 matrix 를 사용 하 는 것 은 차이 가 많 지 않 지만 확실히 많이 간소화 되 었 다.

public static abstract class AbstractScaleType implements ScaleType {
 @Override
 public Matrix getTransform(Matrix outTransform, Rect parentRect, int childWidth, int childHeight, float focusX, float focusY) {
  //                    
  final float sX = (float) parentRect.width() / (float) childWidth;
  final float sY = (float) parentRect.height() / (float) childHeight;
  float scale = Math.min(scaleX, scaleY);
  
  //           ,     x、y     
  float dx = parentRect.left + (parentRect.width() - childWidth * scale) * 0.5f;
  float dy = parentRect.top + (parentRect.height() - childHeight * scale) * 0.5f;
  
  //        
  outTransform.setScale(scale, scale);
  outTransform.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
  return outTransform;
 }
}
3.ControllerBuilder,ControllerListener,PostProcesser,Image Request
Controller Builder 는 Controller 를 구축 하 는 데 사 용 됩 니 다.지난번 에 Controller 를 간단하게 소 개 했 습 니 다.주로 컨트롤 러,그림 의 uri 를 설정 하고 다시 불 러 올 수 있 는 지 등 이 있 습 니 다.그러면 Controller Builder 는 build 모드 로 Controller 를 구축 하 는 것 입 니 다.
Controller Listener 는 다운로드 한 감청 사건 을 제어 하 는 데 사 용 됩 니 다.그림 다운로드 가 완료 되 거나 그 후에 모든 속성 을 설정 해 야 한다 면 Controller Listener 는 이 기능 을 실현 하 는 데 도움 을 줄 수 있 습 니 다.그러나 이 감청 사건 에 서 는 그림 을 수정 할 수 없습니다.그림 을 수정 해 야 한다 면 PostProcesser 프로세서 로 그림 을 수정 해 야 합 니 다.ImageRequest 는 더 많은 속성 을 설정 하 는 데 사 용 됩 니 다.관련 uri 를 설정 할 수도 있 습 니 다.점진 적 로 딩 을 지원 하 는 지,또는 사후 처리 장 치 를 설정 할 수도 있 습 니 다.이 몇 가 지 는 필연 적 인 관계 가 있 음 을 알 수 있 기 때문에 이 세 가지 기능 을 함께 놓 고 소개 한다.
여기 서 gif 그림 에 Controller Listener 를 설정 하 였 습 니 다.그림 이 성공 하고 그림 에 애니메이션 효과 가 존재 한다 면 애니메이션 효 과 를 재생 합 니 다.그렇지 않 으 면 toast 메 시 지 를 재생 합 니 다.

 ControllerListener controllerListener = new BaseControllerListener(){

  @Override
  public void onFinalImageSet(String id, Object imageInfo, Animatable animatable) {
   if(animatable!=null){
    animatable.start();
   }
  }

  @Override
  public void onFailure(String id, Throwable throwable) {
   Toast.makeText(context,"      ",Toast.LENGTH_SHORT).show();
  }

 };

 DraweeController gifController = Fresco.newDraweeControllerBuilder()
    .setUri(Uri.parse("http://img.huofar.com/data/jiankangrenwu/shizi.gif"))
    .setOldController(gifImageView.getController())
    .setControllerListener(controllerListener)
    .build();
 gifImageView.setController(gifController);

이해 하기 가 쉬 워 요.그럼 여기 서 다시 사용 한 후 처리 장 치 를 간단하게 처리 하 겠 습 니 다.

 Postprocessor redMeshPostProcessor = new BasePostprocessor() {
  @Override
  public void process(Bitmap bitmap) {
   for (int x = 0; x < bitmap.getWidth(); x+=2) {
    for (int y = 0; y < bitmap.getHeight(); y+=2) {
     bitmap.setPixel(x, y, Color.TRANSPARENT);
    }
   }
  }

  @Override
  public String getName() {
   return super.getName();
  }
 };
 ImageRequest processorImageRequest = ImageRequestBuilder
   .newBuilderWithSource(Uri.parse("http://avatar.csdn.net/4/E/8/1_y1scp.jpg"))
   .setPostprocessor(redMeshPostProcessor)
   .build();
 DraweeController processorController = Fresco.newDraweeControllerBuilder()
   .setImageRequest(processorImageRequest)
   .setOldController(processImageView.getController())
   .build();
 processImageView.setController(processorController);

그림 에 작은 원점 을 그 렸 습 니 다.이 속성 설정 은 ImageRequest 를 사용 하여 설정 후 프로세서 가 필요 합 니 다.
ImageRequest 의 최저 요청 단계
1.메모리 캐 시 를 검사 합 니 다.예 를 들 어 즉시 되 돌려 줍 니 다.이 조작 은 실시 간 이다.
2.디 코딩 되 지 않 은 그림 캐 시 를 확인 하고 있 으 면 디 코딩 하고 되 돌려 줍 니 다.
3.디스크 캐 시 를 확인 하고 로 딩,디 코딩 이 있 으 면 되 돌려 줍 니 다.
4.로 컬 파일 을 다운로드 하거나 불 러 옵 니 다.크기 와 회전 을 조정 하고 디 코딩 을 하고 되 돌려 줍 니 다.네트워크 그림 에 있어 서 이 절 차 는 내 려 오 는 데 가장 시간 이 걸린다.
setLowest Permitted RequestLevel 은 최소 요청 단 계 를 설정 할 수 있 습 니 다.요청 단 계 는 위 와 대응 하 는 몇 가지 값 이 있 습 니 다.
  • BITMAP_MEMORY_CACHE
  • ENCODED_MEMORY_CACHE
  • DISK_CACHE
  • FULL_FETCH
  •  만약 당신 이 즉시 그림 을 찾 거나 비교적 짧 은 시간 안에 그림 을 찾 아야 한다 면,그렇지 않 으 면 표시 되 지 않 는 상황 에서 이것 은 매우 유용 합 니 다.
    4.점진 적 JPEG 설정,움 직 이 는 그림 표시.
     점진 적 JPEG 는 우리 가 그림 을 불 러 올 때 네트워크 가 느 리 면 그림 이 모호 함 에서 선명 함 으로 점점 나타 나 는 것 을 점진 적 JPEG 라 고 한다.구체 적 인 사용 은 다음 과 같다.
    
      /**
       *      JPEG Config
       * */
      ProgressiveJpegConfig config = new ProgressiveJpegConfig() {
       @Override
       public int getNextScanNumberToDecode(int scanNumber) {
        return 0;
       }
    
       @Override
       public QualityInfo getQualityInfo(int scanNumber) {
        return null;
       }
      };
      /**
       *     ImagePipeline Config
       * */
      ImagePipelineConfig imagePipelineConfig = ImagePipelineConfig.newBuilder(context)
        .setProgressiveJpegConfig(config)
        .setDownsampleEnabled(true)
        .build();
      /**
       *      Fresco     JPEG   
       * */
      Fresco.initialize(this,imagePipelineConfig);
    
    
    초기 화 할 때 이 설정 을 해 야 합 니 다.그렇지 않 으 면 점진 적 인 JPEG 가 나타 나 지 않 습 니 다. 
    
    ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse("http://pooyak.com/p/progjpeg/jpegload.cgi"))
      .setProgressiveRenderingEnabled(true) //       JPEG
      .build();
    DraweeController progressiveJPEGController = Fresco.newDraweeControllerBuilder()
      .setImageRequest(request)
      .setOldController(progressiveJpegImageView.getController())
      .build();
    progressiveJpegImageView.setController(progressiveJPEGController);
    
    
    움 직 이 는 그림 은 사실 할 말 이 없 으 며,Controller 도 너무 많은 설정 을 할 필요 가 없다.
    
    DraweeController gifController = Fresco.newDraweeControllerBuilder()
        .setUri(Uri.parse("http://img.huofar.com/data/jiankangrenwu/shizi.gif"))
        .setAutoPlayAnimations(true) //       
        .setOldController(gifImageView.getController())
        .build();
    gifImageView.setController(gifController);
    setAutoPlayAnimations()를 true 로 설정 하면 불 러 온 후에 자동 으로 재생 할 수 있 습 니 다.수 동 으로 제어 하려 면 Controller Listener 로 제어 하거나 contrller 로 animations 에 직접 접근 하면 됩 니 다.
    
    Animatable animatable = mSimpleDraweeView.getController().getAnimatable();
    if (animatable != null) {
     animatable.start();
     // later
     animatable.stop();
    }
     메모:그림 을 높 은 버 전의 Fresco 에 설정 하려 면 gradle 을 도입 하여 애니메이션 속성 을 지원 해 야 합 니 다.
    compile 'com.facebook.fresco:animated-gif:0.14.0'
    마지막 으로 데모:데모 다운로드를 놓 습 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기