ViewAnimationUtils.createCircularReveal() は、Viewを円形にくり抜くアニメーション(Animator)を作るユーティリティメソッドです。 例えばこんな感じ。
- public class SampleActivity extends AppCompatActivity {
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_sample);
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final View container = findViewById(R.id.container);
- final int width = container.getWidth();
- final int height = container.getHeight();
- float startRadius = (float) Math.sqrt(width * width + height * height) / 2;
- float endRadius = 0;
- final Animator animator = ViewAnimationUtils.createCircularReveal(container,
- width / 2, height / 2, startRadius, endRadius);
- animator.setDuration(3000);
- animator.start();
- }
- });
- }
- }
FAB の transforming
https://material.google.com/components/buttons-floating-action-button.html#buttons-floating-action-button-transitions の真ん中あたり、toolbar という項目のやつです。
アニメーション以外の本質的なコードは toolsContainer と fab の visibility の切り替えだけ(以下の部分)なんですけど、アニメーションのコード入れると長い...
- toolsContainer.setVisibility(View.VISIBLE);
- fab.setVisibility(View.INVISIBLE);
- public class MainActivity extends AppCompatActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- final View toolsContainer = findViewById(R.id.tools_container);
- final View tools = findViewById(R.id.tools);
- final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
- final ToggleButton toggleButton = (ToggleButton) findViewById(R.id.button);
- toggleButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- final int fabWidth = fab.getWidth();
- final int fabHeight = fab.getHeight();
- final int toolsWidth = toolsContainer.getWidth();
- final int toolsHeight = toolsContainer.getHeight();
- float startRadius = fabHeight / 2f;
- float endRadius = (float) (Math.sqrt(toolsWidth * toolsWidth + toolsHeight * toolsHeight));
- int[] outLocation = new int[2];
- toolsContainer.getLocationInWindow(outLocation);
- int[] fabOutLocation = new int[2];
- fab.getLocationInWindow(fabOutLocation);
- float diff = isChecked
- ? (outLocation[1] + toolsHeight / 2) - (fabOutLocation[1] + fabHeight / 2)
- : 0;
- int centerX = (int) (fabOutLocation[0] + fabWidth / 2 - outLocation[0] - diff);
- int centerY = toolsHeight / 2;
- final int FAB_DURATION = 100;
- final int TOOLS_DURATION = 300;
- if (isChecked) {
- final Animator fabAnimator1 = ObjectAnimator.ofFloat(fab, "translationY", diff);
- fabAnimator1.setDuration(FAB_DURATION);
- fabAnimator1.setInterpolator(new DecelerateInterpolator());
- final Animator fabAnimator2 = ObjectAnimator.ofFloat(fab, "translationX", -diff);
- fabAnimator2.setDuration(FAB_DURATION);
- fabAnimator2.setInterpolator(new AccelerateInterpolator());
- final ValueAnimator fabAnimator3 = ValueAnimator.ofInt(255, 0);
- fabAnimator3.setDuration(FAB_DURATION);
- fabAnimator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final int alpha = (int) animation.getAnimatedValue();
- final Drawable drawable = fab.getDrawable();
- drawable.setAlpha(alpha);
- }
- });
- final Animator toolsContainerAnimator = ViewAnimationUtils.createCircularReveal(toolsContainer,
- centerX, centerY, startRadius, endRadius);
- toolsContainerAnimator.setDuration(TOOLS_DURATION);
- toolsContainerAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- toolsContainer.setVisibility(View.VISIBLE);
- fab.setVisibility(View.INVISIBLE);
- }
- });
- tools.setPivotX(centerX);
- final Animator toolsAnimator = ObjectAnimator.ofPropertyValuesHolder(tools,
- PropertyValuesHolder.ofFloat("alpha", 0f, 1f),
- PropertyValuesHolder.ofFloat("scaleX", 0.8f, 1f));
- toolsAnimator.setDuration(TOOLS_DURATION);
- AnimatorSet set = new AnimatorSet();
- set.play(toolsContainerAnimator).with(toolsAnimator)
- .after(fabAnimator1).after(fabAnimator2).after(fabAnimator3);
- set.start();
- } else {
- final Animator fabAnimator1 = ObjectAnimator.ofFloat(fab, "translationY", 0);
- fabAnimator1.setDuration(FAB_DURATION);
- fabAnimator1.setInterpolator(new AccelerateInterpolator());
- final Animator fabAnimator2 = ObjectAnimator.ofFloat(fab, "translationX", 0);
- fabAnimator2.setDuration(FAB_DURATION);
- fabAnimator2.setInterpolator(new DecelerateInterpolator());
- final ValueAnimator fabAnimator3 = ValueAnimator.ofInt(0, 255);
- fabAnimator3.setDuration(FAB_DURATION);
- fabAnimator3.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- final int alpha = (int) animation.getAnimatedValue();
- final Drawable drawable = fab.getDrawable();
- drawable.setAlpha(alpha);
- }
- });
- final Animator toolsContainerAnimator = ViewAnimationUtils.createCircularReveal(
- toolsContainer, centerX, centerY, endRadius, startRadius);
- toolsContainerAnimator.setDuration(TOOLS_DURATION);
- toolsContainerAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- toolsContainer.setVisibility(View.INVISIBLE);
- fab.setVisibility(View.VISIBLE);
- }
- });
- tools.setPivotX(centerX);
- final Animator toolsAnimator = ObjectAnimator.ofPropertyValuesHolder(tools,
- PropertyValuesHolder.ofFloat("alpha", 0f),
- PropertyValuesHolder.ofFloat("scaleX", 0.8f));
- toolsAnimator.setDuration(TOOLS_DURATION);
- AnimatorSet set = new AnimatorSet();
- set.play(toolsContainerAnimator).with(toolsAnimator)
- .before(fabAnimator1).before(fabAnimator2).before(fabAnimator3);
- set.start();
- }
- }
- });
- toolsContainer.setVisibility(toggleButton.isChecked() ? View.VISIBLE : View.INVISIBLE);
- tools.setAlpha(toggleButton.isChecked() ? 1f : 0f);
- }
- }
それを解消するために Transition API が使えます(Transition API はもともとそういうための用意されたもののようです)。それは次回に。
↓実行結果
0 件のコメント:
コメントを投稿