2014-01-14 6 views
5

내가 사용 x=0에서 x=200에 단추를 애니메이션하다고 말하고 : 버튼을 x=100에있을 때애니메이션은

ObjectAnimator animator = ObjectAnimator.ofFloat(button, "x", 0f, 200f); 
animator.setInterpolator(new AccelerateDecelerateInterpolator()); 
animator.start(); 

지금, 나는 애니메이션을 취소 할 수 있습니다. animator.cancel()으로 전화하면 버튼이 갑자기 멈 춥니 다. 내가 달성하고자하는 것은 x 값이 점차적으로 느려지고 (다소 DecelerateInterpolator과 같음), x=120에 정차합니다.

물론, cancel() 애니메이션을 시작하고 새로운 감속 애니메이터를 시작할 수 있습니다. 그러나 이것은 계정의 현재 속도를 고려하지 않아 이상한 행동을 유발합니다.

어떻게하면됩니까?

답변

4

정확하게 @Gil이 지적한대로 사용자 정의 Interpolator 구현을 처리해야합니다. 좋은 소식은 실제로 모든 것을 직접 구현할 필요가 없다는 것입니다. 메인 애니메이션의 가속/감속과 인터폴 레이터의 감속을 취소하기 위해 두 가지 보간 수식을 결합 할 수 있습니다.

정상 감속/가속 애니메이션 : 당신이 중간에 어딘가에을 취소 enter image description here

귀하의 애니메이션 : 여기 enter image description here

내 빠른 보간입니다

은 본질적으로 그것은 당신이 찾고있는 무엇 구현 :

static class MyInterpolator extends AccelerateDecelerateInterpolator { 

    private float phaseShift = 0f; 
    private boolean isCancelled = false; 
    private float lastInput = 0f; 

    /** 
    * Maps a value representing the elapsed fraction of an animation to a value that represents 
    * the interpolated fraction. This interpolated value is then multiplied by the change in 
    * value of an animation to derive the animated value at the current elapsed animation time. 
    * 
    * @param input A value between 0 and 1.0 indicating our current point 
    *    in the animation where 0 represents the start and 1.0 represents 
    *    the end 
    * @return The interpolation value. This value can be more than 1.0 for 
    * interpolators which overshoot their targets, or less than 0 for 
    * interpolators that undershoot their targets. 
    */ 
    @Override 
    public float getInterpolation(float input) { 
     lastInput = input; 
     if(!isCancelled) 
     { 
      return super.getInterpolation(input); 
     } 
     else 
     { 
      return getCancellationInterpolation(input) - phaseShift; 
     } 
    } 

    public void cancel() 
    { 
     isCancelled = true; 
     this.phaseShift = getCancellationInterpolation(lastInput) - super.getInterpolation(lastInput); 

    } 

    private float getCancellationInterpolation(float input) 
    { 
     return (1.0f - (1.0f - input) * (1.0f - input)); 
    } 
} 

보시다시피 애니메이션을 취소 할 때 일반 애니메이션에 기본 보간법을 사용하고 전환시 감속도를 사용합니다. 물론이 코드는 (은 phaseShift 값과 반복 모드를 사용하는 경우 계산 착오가 발생 isCancelled 플래그를 재설정하지 않습니다) 완벽하지 않습니다,하지만 당신이 희망 알아낼 수 뭔가 자신 :) 내가 샘플 프로젝트 on GitHub을 만들어

, 당신 때문에 이

내가 수식 좀 더 연주와 DecelerateInterpolator 구현의 두 번째 부분을 촬영 후속처럼 보이는 방법을 볼 수 있습니다.나는 당신의 취소가 얼마나 빨리 일어나야 하는지를 제어하는 ​​데 도움이되는 factor 매개 변수를 도입했습니다 (어떤 종류의 견인). 1.5factor을 설정하면 나에게주는이 : enter image description here

당신이 볼 수 있듯이 나는 ~ 0.5 점에서 cancel을 쳤을 때, 애니메이션 (그래서 모든 방법의 거리의 0.7로 이동하지 않습니다 더 빨리 취소됩니다 이전 예제에서). 그것은 실제 대상에 대해 조금 더 나은 느낌을줍니다. factor이 높을수록 애니메이션이 더 빨라집니다.

static class MyInterpolator extends AccelerateDecelerateInterpolator { 

    ...... 
    private float factor = 1.5f; 
    ....... 

    private float getCancellationInterpolation(float input) 
    { 
     if(factor == 1) 
     { 
      return (1.0f - (1.0f - input) * (1.0f - input)); 
     } 
     else 
     { 
      return (float)(1.0f - Math.pow((1.0f - input), 2 * factor)); 
     } 
    } 
} 
+0

좋은 생각, 나는 그 라인에 뭔가 의미가있다. 'getCancellationInterpolation (float)'에서 수식을 어떻게 만들었습니까? 그래프는 다소 선형 적으로 보이지만 맛의 문제입니다. 어쨌든, 아직 없다면,이 단계를 더 진행하고 Niek이 암시 한 것처럼'DecelerateInterpolator.getInterpolation (float)'을 사용할 수 있습니다. –

+1

@Gil 수식은'DecelerateInterpolator' 소스 코드에서 가져옵니다. –

+1

내 직감이 정확했습니다. 귀하의 두 번째 upvote 내입니다 : –

1

애니메이션을 끝까지 실행하고 가속 후 "속도가 느려집니다"TimeInterpolator을 구현합니다.

당신은 방법 getInterpolation(float) 구현해야 : 당신이 x = 120x = 0에서 실행 싶으면이 0 예를 들어 1 사이의 정규화하여 위치 값의 X에 대한 시간 순간을 매핑하는 수학 함수를 나타냅니다를, 값 x = 100은에 해당 표준화 된 값

100/| 120 - 0 | = 0.83

올바른 기능을 찾으려면 어느 정도의 수학적 정교함과 추측이 필요하지만이 tutorial을 시작해야합니다.

+0

감사 :

여기에 업데이트 된 보간입니다! 나는 비밀리에 이런 일을 할 수있는 마법의 방법이 있기를 바라고 있었지만, 슬프게도, 보간 자들에게 직접 다이빙을해야 할 것 같아요. – nhaarman

+1

그런데 대부분의 경우 애니메이션을 '0'에서 '200'으로 애니메이션하고 싶지만 때로는 임의의 값으로 애니메이션을 취소하고 정상적으로 멈추고 싶습니다. 실행중인 애니메이션을 중단하고 새 애니메이션을 짧게 감속하는 것이 가장 힘든 부분입니다. – nhaarman

+0

파벨의 코드가 도움이됩니다. 나는 약간의 추가적인 피드백을 위해 그의 코드에 대해서도 간략히 언급 할 것이다. –