Android 에서 필드 전환 애니메이션 의 실현 과 호환성 처리

머리말
안 드 로 이 드 5.0 이전에 우 리 는 이미overridePendingTransition() 방법 으로 전환 효 과 를 실현 했다.하지만 안 드 로 이 드 5.0 이후 에는 더욱 시 크 한 전환 효과 가 나 타 났 다.
예 를 들 어 다음 애니메이션:

1.Android L 의 전환 애니메이션
필드 전환 애니메이션 을 실현 하려 면 세 단계 만 필요 합 니 다.
       res/디 렉 터 리 에 transition 폴 더 를 만 들 고 이 폴 더 에서 인터페이스 전환 애니메이션 과 요 소 를 공유 하 는 애니메이션 을 정의 합 니 다.
       res/value/style 파일 에서 모든 Activity 에 전환 애니메이션 의 style 을 지정 하고 AndroidManifest.xml 파일 에서 모든 Activity 에 대응 하 는 android:theme 를 설정 합 니 다.
       Activity 호출startActivity()에서 애니메이션 을 전환 하기 전에 Activity OptionsCompat 를 사용 하여 전환 애니메이션 을 만 들 때 공유 대상 을 만 듭 니 다.
다음은 이 세 단계 에 대해 상세 하 게 설명 하 겠 습 니 다.
2.전환 애니메이션 정의
res/디 렉 터 리 에 transition 자원 폴 더 를 만 든 후 이 폴 더 에서 모든 애니메이션 을 정의 할 수 있 습 니 다.
일반적으로 Activity 에 대한 과도 애니메이션 은 다음 과 같은 형식 으로 쓸 수 있 습 니 다.

<explode xmlns:android="http://schemas.android.com/apk/res/android">
 <targets>
  <target android:excludeId="@android:id/statusBarBackground"/>
  <target android:excludeId="@android:id/navigationBarBackground"/>
 </targets>
</explode>
그 중에서 애니메이션 효과 의 이름 입 니 다.Android 5.0(API 레벨 21)은 이러한 진입 과 종료 변환 을 지원 합 니 다.
       1.분해(explode):장면 중심 에서 보 기 를 이동 하거나 이동 합 니 다.
       2.미끄럼(slide):장면 가장자리 에서 보 기 를 이동 하거나 이동 합 니 다.
       3.페이드아웃(fade):투명 도 를 조정 하여 장면 에 보 기 를 추가 하거나 제거 합 니 다.
모든 애니메이션 효 과 는 추가 속성 이 있 습 니 다.예 를 들 어 슬라이드 를 미 끄 러 뜨리 면android:slideEdge="top" 미끄럼 방향 을 설정 할 수 있 습 니 다.페 이 드 아웃(fade)사용 가능android:fadingMode="fade_in" 설정 은 페 이 드 아웃(fadein)아니면 페 이 드(fadeout)기다 리 세 요.
탭 에 서 는 필드 전환(또는 필드 전환 필요 없 음)이 필요 한 대상 id 를 정의 합 니 다.이 id 는 시스템 이 자체 적 으로 가 져 올 수도 있 고 우리 가 보기에 있 는 view 의 id 일 수도 있 습 니 다.모든 id 는 탭 에 따로 정의 해 야 합 니 다.android:targetId 목표 ID 가 과도 적 으로 전환 해 야 하 는 view 를 표시 합 니 다. android:excludeId 우 리 는 이 ID 의 view 가 과도 적 으로 전환 할 필요 가 없다 고 표시 합 니 다.위의 코드 는 상태 표시 줄 과 네 비게 이 션 표시 줄 을 제외 한 모든 view 가 explode 애니메이션 을 실행 한 다 는 뜻 입 니 다.
만약 에 우리 가 같은 과도 상태 에서 두 가지 또는 여러 가지 애니메이션 효 과 를 실현 하려 면 어떻게 합 니까?또한 간단 합 니 다.루트 탭 을 교체 한 다음 에 모든 애니메이션 효 과 를 정의 합 니 다.마지막 으로 루트 탭 에서android:transitionOrdering 이 몇 가지 애니메이션 의 프 리 젠 테 이 션 순 서 를 표시 하고 sequential 은 순 서 를 실행 하 며 together 는 동시에 실행 하 는 것 을 기억 합 니 다.
예 를 들 어 아래 코드 와 같다.

<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
 <slide android:slideEdge="bottom">
  <targets>
   <target android:targetId="@id/cardview"/>
  </targets>
 </slide>

 <fade>
  <targets>
   <target android:excludeId="@android:id/statusBarBackground"/>
   <target android:excludeId="@android:id/navigationBarBackground"/>
   <target android:excludeId="@id/cardview"/>
  </targets>
 </fade>
</transitionSet>
이 코드 의 뜻 은 매우 간단 합 니 다.이 xml 는 두 개의 과도 애니메이션 을 정의 하고 동시에 실 행 됩 니 다.첫 번 째 애니메이션 은 id 가 cardView 인 view 를 대상 으로 미 끄 러 지 는 것 입 니 다.두 번 째 애니메이션 은 상태 표시 줄,네 비게 이 션 표시 줄,cardview 를 제외 한 view 를 페이드아웃 합 니 다.
3.모든 Activity 에 전환 스타일 정의
이곳 의 모든 애니메이션 은 인터페이스 전환 과 도 를 할 때 두 인터페이스의 상 태 를 말한다.예 를 들 어 Activity A 와 Activity B 라 는 두 화면 에 대해 가능 한 상 태 는 다음 과 같다.
       1.인터페이스 A 가 인터페이스 B 로 전환:이때 인터페이스 A 는 종료(exit)과도 상태 이 고 해당 하 는 인터페이스 B 는 진입(enter)과도 상태 이다.
       2.인터페이스 B 가 인터페이스 A 로 되 돌아 갑 니 다.이때 인터페이스 A 는 다시(reenter)로 넘 어가 고 해당 하 는 인터페이스 B 는 되 돌아 가기(return)로 넘 어 갑 니 다.
일반적으로 모든 Activity 과도 애니메이션 은 다음 과 같은 형식 으로 정의 할 수 있다.

<style name="BaseAppTheme" parent="android:Theme.Material">
 <!--        -->
 <item name="android:windowContentTransitions">true</item>

 <!--       /       -->
 <item name="android:windowEnterTransition">@transition/explode</item>
 <item name="android:windowExitTransition">@transition/explode</item>

 <!--         /        -->
 <item name="android:windowSharedElementEnterTransition">
 @transition/change_image_transform</item>
 <item name="android:windowSharedElementExitTransition">
 @transition/change_image_transform</item>
</style>
물론,당신 은 모든 것 을 쓰 지 않 아 도 됩 니 다.예 를 들 어 나의 Demo 에서 한 인터페이스의 전환 애니메이션 파일 은 다음 과 같 습 니 다.

<style name="AppTheme.Detail">
 <item name="windowActionBar">false</item>
 <item name="android:windowNoTitle">true</item>
 <item name="android:windowTranslucentStatus">true</item>
 <item name="android:windowAllowEnterTransitionOverlap">false</item>
 <item name="android:windowEnterTransition">@transition/detail_enter</item>
</style>
4.Activity OptionsCompat 호출
필드 전환 애니메이션 은 두 인터페이스의 점프 가 되 돌아 올 때 발생 하기 때문에 intent 점프 인터페이스 를 사용 할 때 Activity Options Compat 를 사용 하여 애니메이션 의 운행 을 지정 해 야 합 니 다.
일반적으로 Activity OptionsCompat 를 호출 하 는 템 플 릿 코드 는 다음 과 같 습 니 다.

//               ActivityOptions   
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, view, getString(R.string.image_transition_name));

//    Intent     ,         
Intent intent = new Intent(this, DetailActivity.class);
startActivity(intent, optionsCompat.toBundle());
Activity Options Compat 는 support v4 패키지 안에 있 습 니 다.사실은 Activity Options 의 호 환 입 니 다(Activity Options 는 API 16 이 도입 한 것 입 니 다).
그 다음 에 우 리 는 두 번 째 Activity 에서 전환 한 그림 을 가 져 와 인터페이스 에 표시 해 야 한다.
여러 공유 요소 의 과도 실현
때때로 우 리 는 여러 요소 가 애니메이션 효 과 를 낼 수 있 도록 Pair<>를 사용 하여 실현 할 수 있 습 니 다.

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(view1, "agreedName1"), Pair.create(view2, "agreedName2"));
5.수 동 으로 전환 애니메이션 을 실현 합 니 다.
현재 시장 에서 안 드 로 이 드 5.0 이하 의 핸드폰 시스템 은 일정한 시장 점유 율 이 있 기 때문에 이런 사용 자 를 배려 하기 위해 우 리 는 공유 요소 의 전환 애니메이션 효 과 를 수 동 으로 실현 할 수 밖 에 없다.
실현 하 는 사고방식 도 비교적 간단 하 다.대략적인 절 차 는 다음 과 같다.
        1.첫 번 째 인터페이스의 공유 요 소 를 확정 하고 그 정 보 를 두 번 째 화면 에 전달 합 니 다.
        2.두 번 째 화면 은 정 보 를 수신 하고 시작 할 때 화면 을 투명 하 게 설정 하 며 공유 요소 만 표시 합 니 다.
        3.두 번 째 인터페이스의 공유 요 소 를 애니메이션 으로 처리 합 니 다.
그럼 우 리 는 한 걸음 한 걸음 위의 절 차 를 실현 하기 시작 했다.
공유 요소 위치 정보 가 져 오기
첫 번 째 인터페이스 에서 우 리 는 공유 요소 의 위치 정 보 를 얻 고 이 를 다음 인터페이스 에 전달 해 야 한다.그래서 우 리 는 첫 번 째 인터페이스 요소 클릭 이벤트 에서 이렇게 쓸 수 있 습 니 다.

public void imageClick(View view) {
 Intent intent = new Intent(AnimeActivity.this, AnimeDetailActivity.class);
 //      rect              
 Rect rect = new Rect();
 //         
 view.getGlobalVisibleRect(rect);
 //          intent  
 intent.setSourceBounds(rect);
 CustomImage customImage = (CustomImage) view;
 intent.putExtra(AnimeDetailActivity.EXTRA_IMAGE, customImage.getImageId());
 startActivity(intent);
 //    Activity       
 overridePendingTransition(0, 0);
}
그 중에서getGlobalVisibleRect() 방법 은 보 이 는 상태 표시 줄 높이+보 이 는 제목 표시 줄 높이+Rect 왼쪽 상단 에서 제목 표시 줄 아래쪽 까지 의 거 리 를 가 져 오 는 것 입 니 다.제목 표시 줄 이 숨겨 지면 제목 표시 줄 높이 는 0 입 니 다.
다음은 두 번 째 인터페이스 에서 위치 정 보 를 받 아 이 그림 을 보 여 준다.
아 날로 그 필드 애니메이션
두 번 째 인터페이스 에서 우 리 는 다음 과 같은 조작 을 해 야 한다.
       1.공유 요소 정 보 를 가 져 옵 니 다.
       2.공유 요소 의 크기 조정 비율 과 변위 거 리 를 계산 합 니 다.
       3.애니메이션 을 호출 하여 아 날로 그 전환 효 과 를 완성 합 니 다.
나 는 위의 세 단계 의 코드 를 아래 와 같다.

private void initial() {
 //             
 mRect = getIntent().getSourceBounds();
 mRescourceId = getIntent().getExtras().getInt(EXTRA_IMAGE);

 //         ,        
 mOriginWidth = mRect.right - mRect.left;
 mOriginHeight = mRect.bottom - mRect.top;

 //    ImageView    ,                
 FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mOriginWidth, mOriginHeight);
 params.setMargins(mRect.left, mRect.top - getStatusBarHeight(), mRect.right, mRect.bottom);
 mImageView.setLayoutParams(params);

 //    ImageView         
 mImageView.setImageResource(mRescourceId);
 mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);

 //                ID,      Bitmap   。
 BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(mRescourceId);
 Bitmap bitmap = bitmapDrawable.getBitmap();

 //              
 getBundleInfo(bitmap);

 //      Pallette   
 mImagePalette = Palette.from(bitmap).generate();
 //    Palette       
 mContainer.setBackgroundColor(
   mImagePalette.getVibrantColor(ContextCompat.getColor(this, android.R.color.black)));
}
12 줄 에서 Margin 형식 을 설정 하여 그림 의 위 치 를 확인 합 니 다.주의해 야 할 것 은 상태 표시 줄 이 부모 컨트롤 FramLayout 이외 이기 때문에 Rect.top 의 값 을 상태 표시 줄 의 높이 를 줄 여야 합 니 다.이것 이 화면 에 대한 절대적 인 위치 입 니 다.그리고getBundleInfo() 방법의 코드 는 다음 과 같다.

private void getBundleInfo(Bitmap bitmap) {
 //         ,     bundle  
 if (bitmap.getWidth() >= bitmap.getHeight()) {
  mScaleBundle.putFloat(SCALE_WIDTH, (float) mScreenWidth / mOriginWidth);
  mScaleBundle.putFloat(SCALE_HEIGHT, (float) bitmap.getHeight() / mOriginHeight);
 } else {
  mScaleBundle.putFloat(SCALE_WIDTH, (float) bitmap.getWidth() / mOriginWidth);
  mScaleBundle.putFloat(SCALE_HEIGHT, (float) mScreenHeight / mOriginHeight);
 }
 //       ,        bundle  
 mTransitionBundle.putFloat(TRANSITION_X, mScreenWidth / 2 - (mRect.left + (mRect.right - mRect.left) / 2));
 mTransitionBundle.putFloat(TRANSITION_Y, mScreenHeight / 2 - (mRect.top + (mRect.bottom - mRect.top) / 2));
}
애니메이션 처리
마지막 으로 우 리 는 애니메이션 을 사용 하여 전환 효 과 를 모 의 해 야 한다.코드 는 다음 과 같다.

private void runEnterAnim() {
 mImageView.animate()
    .setInterpolator(DEFAULT_INTERPOLATOR)
    .setDuration(DURATION)
    .scaleX(mScaleBundle.getFloat(SCALE_WIDTH))
    .scaleY(mScaleBundle.getFloat(SCALE_HEIGHT))
    .translationX(mTransitionBundle.getFloat(TRANSITION_X))
    .translationY(mTransitionBundle.getFloat(TRANSITION_Y))
    .start();
}
간단 합 니 다.이로부터 입장 애니메이션 효 과 는 기본적으로 시 뮬 레이 션 이 끝 났 습 니 다.
퇴장 애니메이션 은 더욱 간단 합 니 다.바로 코드 를 올 립 니 다.

private void runExitAnim() {
 mImageView.animate()
    .setInterpolator(DEFAULT_INTERPOLATOR)
    .setDuration(DURATION)
    .scaleX(1)
    .scaleY(1)
    .translationX(0)
    .translationY(0)
    .withEndAction(new Runnable() {
     @Override
     public void run() {
      finish();
      overridePendingTransition(0, 0);
     }
    })
    .start();
}
총결산
이상 은 안 드 로 이 드 에서 필드 전환 애니메이션 을 실현 하 는 모든 내용 이기 때문에 간단 하지 않 습 니까?이 글 의 내용 이 안 드 로 이 드 개발 자 여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 면 댓 글 을 남 겨 주 십시오.

좋은 웹페이지 즐겨찾기