用小 "rebound" 缩放动画
Scale animation with small "rebound"
我正在尝试使用 XML Animations 将视图从 0% 大小放大到 150% 大小(比 "real size" 大 50%)。然后将大小从 150% 缩小到 100% 的 "real size"。意图是有点 "rebound" 效果,其中视图将从无到有比预期更大,然后 "rebound" 或 "snap back" 到适当的大小。
这是一张说明我想要完成的时间表的图片。
我正在使用这个 XML 动画代码:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
<scale android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1.5"
android:toYScale="1.5"
android:duration="200"
android:pivotX="50%"
android:pivotY="100%"
android:fillAfter="false"
/>
<scale android:fromXScale="1.5"
android:fromYScale="1.5"
android:toXScale="1.0"
android:toYScale="1.0"
android:duration="100"
android:pivotX="50%"
android:pivotY="100%"
android:startOffset="200"
/>
</set>
我 运行 遇到的问题是,在第一个缩放动画完成后,视图正确地为 150% 大小,但是当它运行第二个动画时,它会相对于我们完成的大小进行缩放第一个动画在 (150%) 为 "real size" 100%,或 1.0。
因此,当第二个动画运行而不是我的视图从 150% 缩小到 100% 的实际大小时,它实际上是从 150% (225%) 的 150% 缩小到 150%。这意味着在动画结束时视图仍然太大,在我的例子中是实际大小的 150%。
有没有什么方法可以指示第二个动画或动画集忽略第一个动画的结束值,而只使用视图的 "real" 大小,以便代码更按字面解释并将从实际大小的 150% 缩小到实际大小的 100%。
我已经在每个比例动画和布景本身上尝试了我能想到的 fillBefore
、fillAfter
和 fillEnabled
的所有组合,但到目前为止我已经无法找到这些设置的组合,使其按照我的预期运行。
我发现 This Article 似乎与我的情况有关,这促使我测试了各种 fill
属性的更多组合。但是到现在我还是没能得到我想要的结果。
Facebook 有一个名为 Rebound 的 java 库,它可以模拟 spring 动力学并添加真实世界的物理特性。示例代码:
import com.facebook.rebound.BaseSpringSystem;
import com.facebook.rebound.SimpleSpringListener;
import com.facebook.rebound.Spring;
import com.facebook.rebound.SpringSystem;
import com.facebook.rebound.SpringUtil;
/**
* This Activity presents an ImageView that scales down when pressed and returns to full size when
* released. This demonstrates a very simple integrates a very Simple integration of a Rebound
* Spring model to drive a bouncy animation as the photo scales up and down. You can control the
* Spring configuration by tapping on the blue nub at the bottom of the screen to reveal the
* SpringConfiguratorView. From this view you can adjust the tension and friction of the animation
* spring and observe the effect these values have on the animation.
*/
public class MainActivity extends Activity {
private final BaseSpringSystem mSpringSystem = SpringSystem.create();
private final ExampleSpringListener mSpringListener = new ExampleSpringListener();
private FrameLayout mRootView;
private Spring mScaleSpring;
private View mImageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mRootView = (FrameLayout) findViewById(R.id.root_view);
mImageView = mRootView.findViewById(R.id.image_view);
// Create the animation spring.
mScaleSpring = mSpringSystem.createSpring();
// Add an OnTouchListener to the root view.
mRootView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// When pressed start solving the spring to 1.
mScaleSpring.setEndValue(1);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// When released start solving the spring to 0.
mScaleSpring.setEndValue(0);
break;
}
return true;
}
});
}
@Override
public void onResume() {
super.onResume();
// Add a listener to the spring when the Activity resumes.
mScaleSpring.addListener(mSpringListener);
}
@Override
public void onPause() {
super.onPause();
// Remove the listener to the spring when the Activity pauses.
mScaleSpring.removeListener(mSpringListener);
}
private class ExampleSpringListener extends SimpleSpringListener {
@Override
public void onSpringUpdate(Spring spring) {
// On each update of the spring value, we adjust the scale of the image view to match the
// springs new value. We use the SpringUtil linear interpolation function mapValueFromRangeToRange
// to translate the spring's 0 to 1 scale to a 100% to 50% scale range and apply that to the View
// with setScaleX/Y. Note that rendering is an implementation detail of the application and not
// Rebound itself. If you need Gingerbread compatibility consider using NineOldAndroids to update
// your view properties in a backwards compatible manner.
float mappedValue = (float) SpringUtil.mapValueFromRangeToRange(spring.getCurrentValue(), 0, 1, 1, 0.5);
mImageView.setScaleX(mappedValue);
mImageView.setScaleY(mappedValue);
}
}
}
不应该为动画工作使用一个简单的插值器,我的意思是您无法通过准确的时间对动画进行很好的控制,但是像这样的东西应该可以在没有那么多工作的情况下实现类似的技巧:
<scale android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1.0"
android:toYScale="1.0"
android:duration="300"
android:pivotX="50%"
android:pivotY="100%"
android:fillAfter="true"
android:interpolator="@android:anim/overshoot_interpolator"
/>
我正在尝试使用 XML Animations 将视图从 0% 大小放大到 150% 大小(比 "real size" 大 50%)。然后将大小从 150% 缩小到 100% 的 "real size"。意图是有点 "rebound" 效果,其中视图将从无到有比预期更大,然后 "rebound" 或 "snap back" 到适当的大小。
这是一张说明我想要完成的时间表的图片。
我正在使用这个 XML 动画代码:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
>
<scale android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1.5"
android:toYScale="1.5"
android:duration="200"
android:pivotX="50%"
android:pivotY="100%"
android:fillAfter="false"
/>
<scale android:fromXScale="1.5"
android:fromYScale="1.5"
android:toXScale="1.0"
android:toYScale="1.0"
android:duration="100"
android:pivotX="50%"
android:pivotY="100%"
android:startOffset="200"
/>
</set>
我 运行 遇到的问题是,在第一个缩放动画完成后,视图正确地为 150% 大小,但是当它运行第二个动画时,它会相对于我们完成的大小进行缩放第一个动画在 (150%) 为 "real size" 100%,或 1.0。
因此,当第二个动画运行而不是我的视图从 150% 缩小到 100% 的实际大小时,它实际上是从 150% (225%) 的 150% 缩小到 150%。这意味着在动画结束时视图仍然太大,在我的例子中是实际大小的 150%。
有没有什么方法可以指示第二个动画或动画集忽略第一个动画的结束值,而只使用视图的 "real" 大小,以便代码更按字面解释并将从实际大小的 150% 缩小到实际大小的 100%。
我已经在每个比例动画和布景本身上尝试了我能想到的 fillBefore
、fillAfter
和 fillEnabled
的所有组合,但到目前为止我已经无法找到这些设置的组合,使其按照我的预期运行。
我发现 This Article 似乎与我的情况有关,这促使我测试了各种 fill
属性的更多组合。但是到现在我还是没能得到我想要的结果。
Facebook 有一个名为 Rebound 的 java 库,它可以模拟 spring 动力学并添加真实世界的物理特性。示例代码:
import com.facebook.rebound.BaseSpringSystem;
import com.facebook.rebound.SimpleSpringListener;
import com.facebook.rebound.Spring;
import com.facebook.rebound.SpringSystem;
import com.facebook.rebound.SpringUtil;
/**
* This Activity presents an ImageView that scales down when pressed and returns to full size when
* released. This demonstrates a very simple integrates a very Simple integration of a Rebound
* Spring model to drive a bouncy animation as the photo scales up and down. You can control the
* Spring configuration by tapping on the blue nub at the bottom of the screen to reveal the
* SpringConfiguratorView. From this view you can adjust the tension and friction of the animation
* spring and observe the effect these values have on the animation.
*/
public class MainActivity extends Activity {
private final BaseSpringSystem mSpringSystem = SpringSystem.create();
private final ExampleSpringListener mSpringListener = new ExampleSpringListener();
private FrameLayout mRootView;
private Spring mScaleSpring;
private View mImageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mRootView = (FrameLayout) findViewById(R.id.root_view);
mImageView = mRootView.findViewById(R.id.image_view);
// Create the animation spring.
mScaleSpring = mSpringSystem.createSpring();
// Add an OnTouchListener to the root view.
mRootView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// When pressed start solving the spring to 1.
mScaleSpring.setEndValue(1);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
// When released start solving the spring to 0.
mScaleSpring.setEndValue(0);
break;
}
return true;
}
});
}
@Override
public void onResume() {
super.onResume();
// Add a listener to the spring when the Activity resumes.
mScaleSpring.addListener(mSpringListener);
}
@Override
public void onPause() {
super.onPause();
// Remove the listener to the spring when the Activity pauses.
mScaleSpring.removeListener(mSpringListener);
}
private class ExampleSpringListener extends SimpleSpringListener {
@Override
public void onSpringUpdate(Spring spring) {
// On each update of the spring value, we adjust the scale of the image view to match the
// springs new value. We use the SpringUtil linear interpolation function mapValueFromRangeToRange
// to translate the spring's 0 to 1 scale to a 100% to 50% scale range and apply that to the View
// with setScaleX/Y. Note that rendering is an implementation detail of the application and not
// Rebound itself. If you need Gingerbread compatibility consider using NineOldAndroids to update
// your view properties in a backwards compatible manner.
float mappedValue = (float) SpringUtil.mapValueFromRangeToRange(spring.getCurrentValue(), 0, 1, 1, 0.5);
mImageView.setScaleX(mappedValue);
mImageView.setScaleY(mappedValue);
}
}
}
不应该为动画工作使用一个简单的插值器,我的意思是您无法通过准确的时间对动画进行很好的控制,但是像这样的东西应该可以在没有那么多工作的情况下实现类似的技巧:
<scale android:fromXScale="0"
android:fromYScale="0"
android:toXScale="1.0"
android:toYScale="1.0"
android:duration="300"
android:pivotX="50%"
android:pivotY="100%"
android:fillAfter="true"
android:interpolator="@android:anim/overshoot_interpolator"
/>