Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.leanback.widget;
     18 
     19 import android.animation.ObjectAnimator;
     20 import android.animation.PropertyValuesHolder;
     21 import android.util.Property;
     22 import android.view.animation.LinearInterpolator;
     23 
     24 /**
     25  * ParallaxTarget is responsible for updating the target through the {@link #update(float)} method
     26  * or the {@link #directUpdate(Number)} method when {@link #isDirectMapping()} is true.
     27  * When {@link #isDirectMapping()} is false, {@link ParallaxEffect} transforms the values of
     28  * {@link Parallax}, which represents the current state of UI, into a float value between 0 and 1.
     29  * That float value is passed into {@link #update(float)} method.
     30  */
     31 public abstract class ParallaxTarget {
     32 
     33     /**
     34      * Implementation class is supposed to update target with the provided fraction
     35      * (between 0 and 1). The fraction represents percentage of completed change (e.g. scroll) on
     36      * target. Called only when {@link #isDirectMapping()} is false.
     37      *
     38      * @param fraction Fraction between 0 to 1.
     39      * @see #isDirectMapping()
     40      */
     41     public void update(float fraction) {
     42     }
     43 
     44     /**
     45      * Returns true if the ParallaxTarget is directly mapping from source value,
     46      * {@link #directUpdate(Number)} will be used to update value, otherwise update(fraction) will
     47      * be called to update value. Default implementation returns false.
     48      *
     49      * @return True if direct mapping, false otherwise.
     50      * @see #directUpdate(Number)
     51      * @see #update(float)
     52      */
     53     public boolean isDirectMapping() {
     54         return false;
     55     }
     56 
     57     /**
     58      * Directly update the target using a float or int value. Called when {@link #isDirectMapping()}
     59      * is true.
     60      *
     61      * @param value Either int or float value.
     62      * @see #isDirectMapping()
     63      */
     64     public void directUpdate(Number value) {
     65     }
     66 
     67     /**
     68      * PropertyValuesHolderTarget is an implementation of {@link ParallaxTarget} that uses
     69      * {@link PropertyValuesHolder} to update the target object.
     70      */
     71     public static final class PropertyValuesHolderTarget extends ParallaxTarget {
     72 
     73         /**
     74          * We simulate a parallax effect on target object using an ObjectAnimator. PSEUDO_DURATION
     75          * is used on the ObjectAnimator.
     76          */
     77         private static final long PSEUDO_DURATION = 1000000;
     78 
     79         private final ObjectAnimator mAnimator;
     80         private float mFraction;
     81 
     82         public PropertyValuesHolderTarget(Object targetObject, PropertyValuesHolder values) {
     83             mAnimator = ObjectAnimator.ofPropertyValuesHolder(targetObject, values);
     84             mAnimator.setInterpolator(new LinearInterpolator());
     85             mAnimator.setDuration(PSEUDO_DURATION);
     86         }
     87 
     88         @Override
     89         public void update(float fraction) {
     90             mFraction = fraction;
     91             mAnimator.setCurrentPlayTime((long) (PSEUDO_DURATION * fraction));
     92         }
     93 
     94     }
     95 
     96     /**
     97      * DirectPropertyTarget is to support direct mapping into either Integer Property or Float
     98      * Property. App uses convenient method {@link ParallaxEffect#target(Object, Property)} to
     99      * add a direct mapping.
    100      * @param <T> Type of target object.
    101      * @param <V> Type of value, either Integer or Float.
    102      */
    103     public static final class DirectPropertyTarget<T extends Object, V extends Number>
    104             extends ParallaxTarget {
    105 
    106         Object mObject;
    107         Property<T, V> mProperty;
    108 
    109         /**
    110          * @param targetObject Target object for perform Parallax
    111          * @param property     Target property, either an Integer Property or a Float Property.
    112          */
    113         public DirectPropertyTarget(Object targetObject, Property<T, V> property) {
    114             mObject = targetObject;
    115             mProperty = property;
    116         }
    117 
    118         /**
    119          * Returns true as DirectPropertyTarget receives a number to update Property in
    120          * {@link #directUpdate(Number)}.
    121          */
    122         @Override
    123         public boolean isDirectMapping() {
    124             return true;
    125         }
    126 
    127         @Override
    128         public void directUpdate(Number value) {
    129             mProperty.set((T) mObject, (V) value);
    130         }
    131     }
    132 }
    133