/* * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.interpolator; import android.animation.ObjectAnimator; import android.graphics.Path; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.SeekBar; import android.widget.Spinner; import android.widget.TextView; import com.example.android.common.logger.Log; /** * This sample demonstrates the use of animation interpolators and path animations for * Material Design. * It shows how an {@link android.animation.ObjectAnimator} is used to animate two properties of a * view (scale X and Y) along a path. */ public class InterpolatorFragment extends Fragment { /** * View that is animated. */ private View mView; /** * Spinner for selection of interpolator. */ private Spinner mInterpolatorSpinner; /** * SeekBar for selection of duration of animation. */ private SeekBar mDurationSeekbar; /** * TextView that shows animation selected in SeekBar. */ private TextView mDurationLabel; /** * Interpolators used for animation. */ private Interpolator mInterpolators[]; /** * Path for in (shrinking) animation, from 100% scale to 20%. */ private Path mPathIn; /** * Path for out (growing) animation, from 20% to 100%. */ private Path mPathOut; /** * Set to true if View is animated out (is shrunk). */ private boolean mIsOut = false; /** * Default duration of animation in ms. */ private static final int INITIAL_DURATION_MS = 750; /** * String used for logging. */ public static final String TAG = "InterpolatorplaygroundFragment"; public InterpolatorFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the fragment_animation layout View v = inflater.inflate(R.layout.interpolator_fragment, container, false); // Set up the 'animate' button, when it is clicked the view is animated with the options // selected: the Interpolator, duration and animation path Button button = (Button) v.findViewById(R.id.animateButton); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // Interpolator selected in the spinner Interpolator interpolator = mInterpolators[mInterpolatorSpinner.getSelectedItemPosition()]; // Duration selected in SeekBar long duration = mDurationSeekbar.getProgress(); // Animation path is based on whether animating in or out Path path = mIsOut ? mPathIn : mPathOut; // Log animation details Log.i(TAG, String.format("Starting animation: [%d ms, %s, %s]", duration, (String) mInterpolatorSpinner.getSelectedItem(), ((mIsOut) ? "Out (growing)" : "In (shrinking)"))); // Start the animation with the selected options startAnimation(interpolator, duration, path); // Toggle direction of animation (path) mIsOut = !mIsOut; } }); // Get the label to display the selected duration mDurationLabel = (TextView) v.findViewById(R.id.durationLabel); // Initialize Interpolators programmatically by loading them from their XML definitions // provided by the framework. mInterpolators = new Interpolator[]{ new AnimationUtils().loadInterpolator(getActivity(), android.R.interpolator.linear), new AnimationUtils().loadInterpolator(getActivity(), android.R.interpolator.fast_out_linear_in), new AnimationUtils().loadInterpolator(getActivity(), android.R.interpolator.fast_out_slow_in), new AnimationUtils().loadInterpolator(getActivity(), android.R.interpolator.linear_out_slow_in) }; // Load names of interpolators from a resource String[] interpolatorNames = getResources().getStringArray(R.array.interpolator_names); // Set up the Spinner with the names of interpolators mInterpolatorSpinner = (Spinner) v.findViewById(R.id.interpolatorSpinner); ArrayAdapter spinnerAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_spinner_dropdown_item, interpolatorNames); mInterpolatorSpinner.setAdapter(spinnerAdapter); // Set up SeekBar that defines the duration of the animation mDurationSeekbar = (SeekBar) v.findViewById(R.id.durationSeek); // Register listener to update the text label when the SeekBar value is updated mDurationSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { mDurationLabel.setText(getResources().getString(R.string.animation_duration, i)); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); // Set initial progress to trigger SeekBarChangeListener and update UI mDurationSeekbar.setProgress(INITIAL_DURATION_MS); // Get the view that will be animated mView = v.findViewById(R.id.square); // The following Path definitions are used by the ObjectAnimator to scale the view. // Path for 'in' animation: growing from 20% to 100% mPathIn = new Path(); mPathIn.moveTo(0.2f, 0.2f); mPathIn.lineTo(1f, 1f); // Path for 'out' animation: shrinking from 100% to 20% mPathOut = new Path(); mPathOut.moveTo(1f, 1f); mPathOut.lineTo(0.2f, 0.2f); return v; } /** * Start an animation on the sample view. * The view is animated using an {@link android.animation.ObjectAnimator} on the * {@link View#SCALE_X} and {@link View#SCALE_Y} properties, with its animation based on a path. * The only two paths defined here ({@link #mPathIn} and {@link #mPathOut}) scale the view * uniformly. * * @param interpolator The interpolator to use for the animation. * @param duration Duration of the animation in ms. * @param path Path of the animation * @return The ObjectAnimator used for this animation * @see android.animation.ObjectAnimator#ofFloat(Object, String, String, android.graphics.Path) */ public ObjectAnimator startAnimation(Interpolator interpolator, long duration, Path path) { // This ObjectAnimator uses the path to change the x and y scale of the mView object. ObjectAnimator animator = ObjectAnimator.ofFloat(mView, View.SCALE_X, View.SCALE_Y, path); // Set the duration and interpolator for this animation animator.setDuration(duration); animator.setInterpolator(interpolator); animator.start(); return animator; } /** * Return the array of loaded Interpolators available in this Fragment. * * @return Interpolators */ public Interpolator[] getInterpolators() { return mInterpolators; } /** * Return the animation path for the 'in' (shrinking) animation. * * @return */ public Path getPathIn() { return mPathIn; } /** * Return the animation path for the 'out' (growing) animation. * * @return */ public Path getPathOut() { return mPathOut; } }