Android LayoutTransiton 간단 한 녹화 버튼 구현

최근 에 회사 에서 해 야 할 프로젝트 에서 간단 한 영상 녹화 기능 을 실현 하 는 구성 요 소 를 요구 합 니 다.저 는 간단하게 디자인 했 습 니 다.주요 기능 은 바로 시작,정지,녹화 시간 을 표시 하 는 것 입 니 다.우선 효과 도 를 살 펴 보 자.

아주 간단 한 애니메이션 효 과 를 볼 수 있 습 니 다.편리 하 게 사용 하기 위해 저 는 그 를 aar 로 만 들 고 jCenter 에 발 표 했 습 니 다.집적 방식:

compile 'com.rangaofei:sakarecordview:0.0.2'
구성 요소 에 사용 되 는 라 이브 러 리 도 매우 간단 합 니 다.databinding,속성 애니메이션 과 layottransition 을 포함 합 니 다.이 간단 한 라 이브 러 리 를 통 해 Layout Transition 의 용법 을 간단하게 소개 합 니 다.그 중에서 도 간단 한 databinding 과 속성 애니메이션 의 지식 점 을 삽입 할 수 있 습 니 다.어려움 이 있 으 면 스스로 해결 하 십시오.
사용 방법:xml 파일 에 사용자 정의 컨트롤 추가:

<com.hanlinbode.sakarecordview.RecordView
    android:id="@+id/rv_saka"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_margin="30dp"
    app:record_view_time_string="HHMMSS" />
record_view_time_string속성 은 매 거 진 유형 으로 시간 표시 형식 을 나타 낸다.
HHMMSS 00:00:00
MMSS 00:00
HH_MM_SS 00-00-00
MM_SS 00-00

//    
void updateTime(long)
/*     , 
  void onInitial();

  void onStartRecord();

  void onPauseRecord();

  void onResumeRecord();

  void onStopRecord();*/
void setRecordListener(RecordListener)

void setDebug(boolean)
LayoutTransition 안내
공식 문서 에서 유래 하 다
LayoutTransition 은 viewgroup 의 레이아웃 이 변 할 때 애니메이션 효 과 를 낼 수 있 습 니 다.ViewGroup.setLayoutTransition(LayoutTransition transition)를 통 해 과도 한 효 과 를 설정 할 수 있다.이 방법 을 사용 하면 내 장 된 과도 애니메이션(alpha 값 변화,xy 위치 변화 등)을 사용 합 니 다.개발 자 는'LayoutTransition.setAnimator(int transition Type,Animator animator)를 통 해 자신의 과도 효 과 를 설정 할 수 있 습 니 다.애니메이션 을 출발 할 수 있 는 상황 은 두 가지 가 있 습 니 다.
  • 아 이 템 추가(보기 설정 가능)
  • 아 이 템 제거(뷰 설정.GON 도 가능)
  • viewgroup 에서 상기 두 가지 행위 가 발생 하거나 삭 제 를 추가 하여 다른 item 변 화 를 일 으 키 면 애니메이션 이 실 행 됩 니 다.
    과도 애니메이션 의 트리거 종류
    이 종 류 는 어떤 행위 가 발생 했 을 때(예 를 들 어 item 추가 또는 삭제)5 가지 가 있 습 니 다.CHANGE_APPEARING,CHANGE_DISAPPERING,APPEARING,DISAPPEARING,CHANGING모든 상태 에 자신의 비트 표시 가 있 습 니 다.
    CHANGE_APPEARING
    지시 애니메이션 은 새로운 컨트롤 이 viewgroup 에 추 가 될 때 다른 view 변 화 를 일 으 킵 니 다.그것 의 표지 위 치 는 0x 01 이다.즉,addview 나 비 VISIBLE 상태의 view 를 VISIBILE 상태 로 설정 할 때 다른 view 가 영향 을 받 으 면 트리거 됩 니 다.
    CHANGE_DISAPPEARING
    지시 애니메이션 은 viewgroup 에서 컨트롤 을 삭제 할 때 다른 view 변 화 를 일 으 킬 것 입 니 다.플래그 위 치 는 0x 02 입 니 다.즉,removeview 나 VISIBLE 상태의 view 를 비 VISIBLE 상태 로 설정 할 때 다른 view 가 영향 을 받 아 촉발 된다.
    APPEARING
    새 view 가 viewgroup 에 추 가 될 때 터치 합 니 다.그것 의 표지 위 치 는 0x 04 이다.즉,addview 나 비 VISIBLE 상태의 view 를 VISIBILE 상태 로 설정 할 때 촉발 합 니 다.
    DISAPPERAING
    지시 애니메이션 은 viewgroup 에서 컨트롤 을 삭제 할 때 실 행 됩 니 다.플래그 위 치 는 0x 08 입 니 다.즉,removeview 나 VISIBLE 상태의 view 를 비 VISIBLE 상태 로 설정 할 때 촉발 합 니 다.
    CHANGING
    앞 에 있 는 네 가지 로 나 가면 레이아웃 이 바 뀌 면 애니메이션 이 실 행 됩 니 다.그것 의 표지 위 치 는 0x 10 이다.이 플래그 위 치 는 기본적으로 활성화 되 지 않 지만 enableTransiton Type(int)을 통 해 활성화 할 수 있 습 니 다.
    이런 것들 을 알 게 되면 이 라 이브 러 리 는 기본적으로 실 현 될 수 있다.
    RecordView 분석

    왼쪽 시작 과 일시 정지 단 추 는 checkbox 로 이 루어 집 니 다.간단 한 selector 를 통 해 그림 을 전환 하고 오른쪽 레이아웃 이 나타 나 고 사라 질 때 크기 조정 애니메이션 이 있 습 니 다.간단 한 ObjectAnimator 모니터 를 설정 해서 이 크기 를 조정 할 수 있 습 니 다.
    
    ObjectAnimator animShow = ObjectAnimator.ofFloat(null, "scaleX", 0, 1);
      animShow.setInterpolator(new OvershootInterpolator());
      animShow.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          if (isDebug()) {
            Log.e(TAG, "show anim value=" + (float) animation.getAnimatedValue());
          }
          recordState.setPlayScale(1 + (float) animation.getAnimatedValue() / 5);
        }
      });
      layoutTransition.setAnimator(LayoutTransition.APPEARING, animShow);
      ObjectAnimator animHide = ObjectAnimator.ofFloat(null, "alpha", 1, 0);
      animHide.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
          if (isDebug()) {
            Log.e(TAG, "hide anim value=" + (float) animation.getAnimatedValue());
          }
          recordState.setPlayScale(1 + (float) animation.getAnimatedValue() / 5);
        }
      });
      layoutTransition.addTransitionListener(this);
      layoutTransition.setAnimator(LayoutTransition.DISAPPEARING, animHide);
      binding.rootView.setLayoutTransition(layoutTransition);
      binding.rootContainer.setLayoutTransition(layoutTransition);
    record 는 표 시 된 그림 과 시간 을 설정 하고 크기 조정 상 태 를 저장 하 는 클래스 입 니 다.
    
    public class RecordState extends BaseObservable implements Parcelable {
      private boolean recording;
      private String time = "00:00:00";
      private float playScale = 1;
    
      @DrawableRes
      private int playDrawable;
      @DrawableRes
      private int stopDrawable;
    
      public RecordState(int playDrawable, int stopDrawable) {
        this.playDrawable = playDrawable;
        this.stopDrawable = stopDrawable;
      }
    
      @Bindable
      public boolean isRecording() {
        return recording;
      }
    
      public void setRecording(boolean recording) {
        this.recording = recording;
        notifyPropertyChanged(BR.recording);
      }
    
      //     getter setter
    
      @Bindable
      public float getPlayScale() {
        return playScale;
      }
    
      public void setPlayScale(float playScale) {
        this.playScale = playScale;
        notifyPropertyChanged(BR.playScale);
      }
    
      //  parcelable  
    }
    여기 서 view 의 한계점 을 제시 해 야 합 니 다.x 또는 y 의 크기 만 바 꿀 수 있 고 동시에 바 꿀 수 없 기 때문에 X 와 Y 의 scale 값 을 동시에 변경 하 는 adapter 를 만 들 었 습 니 다.
    
    public class CheckboxAttrAdapter {
      @BindingAdapter("checkListener")
      public static void setCheckBoxListener(CheckBox view, CompoundButton.OnCheckedChangeListener listener) {
        view.setOnCheckedChangeListener(listener);
      }
    
      @BindingAdapter("android:button")
      public static void setButton(CheckBox view, @DrawableRes int drawableId) {
        view.setButtonDrawable(drawableId);
      }
    
      @BindingAdapter("recordScale")
      public static void setRecordScale(CheckBox view, float scale) {
        view.setScaleX(scale);
        view.setScaleY(scale);
      }
    }
    그리고 xml 파일 에서 속성 을 직접 마 실 수 있 습 니 다:
    
    <CheckBox
      android:id="@+id/start"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerVertical="true"
      android:layout_marginLeft="30dp"
      android:button="@{state.playDrawable}"
      android:checked="@{state.recording}"
      app:checkListener="@{checkListener}"
      app:recordScale="@{state.playScale}" />
    이렇게 하면 애니메이션 작업 을 기본적으로 완성 한 다음 에 인 터 페 이 스 를 노출 하면 됩 니 다.
    
    public interface RecordListener {
      void onInitial();
    
      void onStartRecord();
    
      void onPauseRecord();
    
      void onResumeRecord();
    
      void onStopRecord();
    
    }
    이렇게 해서 가장 간단 한 RecordView 를 완성 했다.
    원리 탐구
    본인 의 수준 이 제한 되 어 있 습 니 다.여 기 는 가장 간단 한 분석 만 진행 합 니 다.
    LayoutTransition 은 일련의 기본 값 을 설정 합 니 다.이 기본 값 은 기본 animator,animator 의 duration,애니메이션 시작 지연 시간,애니메이션 의 오 작 동 간격,플러그 인,view 를 실행 하 는 애니메이션 map 관계,표시 되 거나 사라 지 는 view 애니메이션 의 map 관계,view 와 view 의 onlayoutchangestener 대응 관계 등 이 있 습 니 다.
    기본 방법 과 변수
    
    public LayoutTransition() {
      if (defaultChangeIn == null) {
        PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);
        PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);
        PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1);
        PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1);
        PropertyValuesHolder pvhScrollX = PropertyValuesHolder.ofInt("scrollX", 0, 1);
        PropertyValuesHolder pvhScrollY = PropertyValuesHolder.ofInt("scrollY", 0, 1);
        defaultChangeIn = ObjectAnimator.ofPropertyValuesHolder((Object)null,
            pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScrollX, pvhScrollY);
        defaultChangeIn.setDuration(DEFAULT_DURATION);
        defaultChangeIn.setStartDelay(mChangingAppearingDelay);
        defaultChangeIn.setInterpolator(mChangingAppearingInterpolator);
        defaultChangeOut = defaultChangeIn.clone();
        defaultChangeOut.setStartDelay(mChangingDisappearingDelay);
        defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator);
        defaultChange = defaultChangeIn.clone();
        defaultChange.setStartDelay(mChangingDelay);
        defaultChange.setInterpolator(mChangingInterpolator);
    
        defaultFadeIn = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f);
        defaultFadeIn.setDuration(DEFAULT_DURATION);
        defaultFadeIn.setStartDelay(mAppearingDelay);
        defaultFadeIn.setInterpolator(mAppearingInterpolator);
        defaultFadeOut = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
        defaultFadeOut.setDuration(DEFAULT_DURATION);
        defaultFadeOut.setStartDelay(mDisappearingDelay);
        defaultFadeOut.setInterpolator(mDisappearingInterpolator);
      }
      mChangingAppearingAnim = defaultChangeIn;
      mChangingDisappearingAnim = defaultChangeOut;
      mChangingAnim = defaultChange;
      mAppearingAnim = defaultFadeIn;
      mDisappearingAnim = defaultFadeOut;
    }
    이 를 통 해 알 수 있 듯 이 기본 애니메이션 이 가지 고 있 는 속성 은 left,top,right,bottom,scrollY 와 scrollX 입 니 다.여기 서 startDelay 라 는 방법 을 주의 하면 이 시작 지연 시간 이 다 르 고 대응 하 는 관 계 는 다음 과 같 습 니 다.
    
    private long mAppearingDelay = DEFAULT_DURATION;
    private long mDisappearingDelay = 0;
    private long mChangingAppearingDelay = 0;
    private long mChangingDisappearingDelay = DEFAULT_DURATION;
    private long mChangingDelay = 0;
    공식 문서 에서 특별히 설명 했다.
    By default, the DISAPPEARING animation begins immediately, as does the CHANGE_APPEARING animation. The other animations begin after a delay that is set to the default duration of the animations.
    DISAPPEARING 과 CHANGEAPPEARING 은 지연 시간 이 없고 다른 애니메이션 은 300 ms 지연 된다.이렇게 하 는 목적 은 애니메이션 을 전시 할 때 순서대로 보 여 주 는 시각 적 효 과 를 가지 고 논리 에 더욱 부합 되 게 보이 기 위해 서 이다.
    하나의 item 이 viewgroup 에 추 가 될 때 다른 아 드 item 은 먼저 이동 하여 새로 추 가 된 item 디 스 플레이 를 조정 한 다음 에 새로 추 가 된 item 디 스 플레이 애니메이션 을 실행 해 야 합 니 다.아 이 템 을 제거 할 때 역방향 과정 입 니 다.
    다른 유용 한 변 수 를 보십시오
    
    private int mTransitionTypes = FLAG_CHANGE_APPEARING | FLAG_CHANGE_DISAPPEARING |
          FLAG_APPEARING | FLAG_DISAPPEARING;
    이 mTransition Types 는 뒤에 있 는 실행 애니메이션 에서 사용 해 야 할 변수 입 니 다.기본적으로 네 가지 종 류 를 활성화 시 켰 습 니 다.앞에서 언급 한 FLAG 만 있 습 니 다.CHAGE 가 활성화 되 지 않 았 습 니 다.
    개발 자가 제어 할 수 있 는 변수
    여기 서 몇 가지 방법 을 집중 적 으로 이야기 합 니 다.
    
    //           
    public void setDuration(long duration)
    //             :CHANGE_APPEARING,CHANGE_DISAPPEARING,APPEARING,DISAPPEARRING,CHANGING
    public void setDuration(int transitionType, long duration)
    //             
    public long getDuration(int transitionType)
    //   CHANGEINGXX        
    public void setStagger(int transitionType, long duration)
    //   CHANGEINGXX        
    public long getStagger(int transitionType)
    //             
    public void setInterpolator(int transitionType, TimeInterpolator interpolator)
    //              
    public TimeInterpolator getInterpolator(int transitionType)
    //          
    public void setAnimator(int transitionType, Animator animator)
    //  viewgroup       view      ,  viewgroup    wrapcontent,  view         
    public void setAnimateParentHierarchy(boolean animateParentHierarchy)
    //              
    public boolean isChangingLayout()
    //          
    public boolean isRunning()
    //  item
    public void addChild(ViewGroup parent, View child)
    //  item
    public void removeChild(ViewGroup parent, View child)
    //  item
    public void showChild(ViewGroup parent, View child, int oldVisibility)
    //  item
    public void hideChild(ViewGroup parent, View child, int newVisibility)
    //     
    public void addTransitionListener(TransitionListener listener)
    //     
    public void removeTransitionListener(TransitionListener listener)
    //     
    public List<TransitionListener> getTransitionListeners()
    이 방법 들 은 모두 비교적 간단 하 다.
    실행 절차
    먼저 간단 한 그림 을 보 세 요.

    위의 방법 에서 볼 수 있 듯 이 flag 가 모두 활성화 되 지 않 으 면 표시 되 거나 숨겨 진 애니메이션 이 없습니다.CHANGE_DISAPPEARINGCHANGE_APPEARING는 부모 view 와 새로 view 를 추가 하지 않 은 애니메이션 을 제어 하고APPEARINGDISAPPEARING는 새로 view 를 추가 한 애니메이션 을 제어 합 니 다.
    mAnimateParent Hierarchy 이 변 수 는 부모 레이아웃 의 변경 애니메이션 을 표시 할 지 여 부 를 제어 합 니 다.따라서 이 변 수 는 true 뒷부분 레이아웃CHANGE_DISAPPEARINGCHANGE_APPEARING으로 설정 해 야 합 니 다.false 로 설정 한 후 부모 레이아웃 만 애니메이션 이 없 으 며,하위 컨트롤 에 새로 추 가 된 view 가 아 닌 애니메이션 효 과 를 사용 합 니 다.
    viewgroup 에서 호출
    addview()는 view roup 에 부모 컨트롤 이 없 는 view 를 추가 하 는 데 사 용 됩 니 다.이 방법 은 최종 적 으로 호출 된 것 입 니 다.
    
    private void addViewInner(View child, int index, LayoutParams params,
          boolean preventRequestLayout){
            //    
      if (mTransition != null) {
        // Don't prevent other add transitions from completing, but cancel remove
        // transitions to let them complete the process before we add to the container
        mTransition.cancel(LayoutTransition.DISAPPEARING);
      }
      //    
      if (mTransition != null) {
        mTransition.addChild(this, child);
      }
      //    
      //    
      
    }
    view 의 표시 나 숨 김 을 설정 할 때 다음 방법 을 사용 합 니 다.
    
    protected void onChildVisibilityChanged(View child, int oldVisibility, int newVisibility) {
        if (mTransition != null) {
          if (newVisibility == VISIBLE) {
            mTransition.showChild(this, child, oldVisibility);
          } else {
            mTransition.hideChild(this, child, newVisibility);
            if (mTransitioningViews != null && mTransitioningViews.contains(child)) {
              // Only track this on disappearing views - appearing views are already visible
              // and don't need special handling during drawChild()
              if (mVisibilityChangingChildren == null) {
                mVisibilityChangingChildren = new ArrayList<View>();
              }
              mVisibilityChangingChildren.add(child);
              addDisappearingView(child);
            }
          }
        }
    
        // in all cases, for drags
        if (newVisibility == VISIBLE && mCurrentDragStartEvent != null) {
          if (!mChildrenInterestedInDrag.contains(child)) {
            notifyChildOfDragStart(child);
          }
        }
      }
    view group 에서 위 그림 에서 언급 한 방법 호출 과 일치 하 는 것 을 볼 수 있 습 니 다.
    ViewGroup.setLayoutTransition(LayoutTransition transition)을 호출 할 때 자신 에 게 Transition Listener 를 설 치 했 습 니 다.이 곳 은 애니메이션 을 진행 하고 있 는 view 를 캐 시 하기 위해 서 입 니 다.분석 하지 않 습 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기