Skip to content

Commit

Permalink
fix lollipop bug & hardware acceleration
Browse files Browse the repository at this point in the history
  • Loading branch information
ozodrukh committed Nov 19, 2014
1 parent 2e088f0 commit 607c2ca
Show file tree
Hide file tree
Showing 5 changed files with 266 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import butterknife.ButterKnife;
import butterknife.InjectView;
import io.codetail.animation.Animator;
import io.codetail.animation.ViewAnimationUtils;
import io.codetail.circualrevealsample.widget.FloatingActionButton;
import io.codetail.circualrevealsample.widget.ViewUtils;
Expand Down Expand Up @@ -59,7 +60,6 @@ protected void onCreate(Bundle savedInstanceState) {
mCardsGroup.setClipToPadding(false);
mCardsGroup.setAdapter(mCardsAdapter);
mCardsGroup.setLayoutManager(mLayoutManager);
mCardsGroup.setOnScrollListener(new HideExtraOnScroll(mToolbar));

mToolbar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
Expand Down Expand Up @@ -88,17 +88,33 @@ public void onClick(View v) {
// get the final radius for the clipping circle
int finalRadius = Math.max(myView.getWidth(), myView.getHeight()) + 100;

ObjectAnimator animator = (ObjectAnimator)
Animator animator =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
animator.setInterpolator(new AccelerateInterpolator());
animator.setDuration(500);
animator.setAutoCancel(true);

if(Animator.LOLLIPOP){
android.animation.ObjectAnimator a = (android.animation.ObjectAnimator)
animator.getNativeAnimator();
a.setAutoCancel(true);
}else{
ObjectAnimator a = (ObjectAnimator)
animator.getSupportAnimator();
a.setAutoCancel(true);
}

animator.start();
}
});

}

@Override
protected void onStart() {
super.onStart();
mCardsGroup.setOnScrollListener(new HideExtraOnScroll(mToolbar));
}

@Override
protected void onStop() {
super.onStop();
Expand Down
230 changes: 230 additions & 0 deletions circualreveal/src/main/java/io/codetail/animation/Animator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
package io.codetail.animation;


import android.annotation.TargetApi;
import android.os.Build;
import android.view.animation.Interpolator;

import java.util.ArrayList;

public class Animator {

public final static boolean LOLLIPOP = Build.VERSION.SDK_INT >= 21;

android.animation.Animator mNativeAnimator;
com.nineoldandroids.animation.Animator mSupportAnimator;

/**
* @hide
*/
public Animator(com.nineoldandroids.animation.Animator animator) {
mSupportAnimator = animator;
}

/**
* @hide
*/
public Animator(android.animation.Animator animator){
mNativeAnimator = animator;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public Animator setInterpolator(Interpolator interpolator){
if(LOLLIPOP){
mNativeAnimator.setInterpolator(interpolator);
}else{
mSupportAnimator.setInterpolator(interpolator);
}
return this;
}

/**
* Sets the duration of the animation.
*
* @param duration The length of the animation, in milliseconds.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public Animator setDuration(int duration){
if(LOLLIPOP){
mNativeAnimator.setDuration(duration);
}else{
mSupportAnimator.setDuration(duration);
}
return this;
}

public Animator addListener(com.nineoldandroids.animation.Animator.AnimatorListener listener){
mSupportAnimator.addListener(listener);
return this;
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public Animator addListener(android.animation.Animator.AnimatorListener listener){
mNativeAnimator.addListener(listener);
return this;
}

public Animator addPauseListener(com.nineoldandroids.animation.Animator.AnimatorPauseListener pauseListener){
mSupportAnimator.addPauseListener(pauseListener);
return this;
}

@TargetApi(Build.VERSION_CODES.KITKAT)
public Animator addPauseListener(android.animation.Animator.AnimatorPauseListener pauseListener){
mNativeAnimator.addPauseListener(pauseListener);
return this;
}


/**
* Gets the duration of the animation.
*
* @return The length of the animation, in milliseconds.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public long getDuration(){
if(LOLLIPOP){
return mNativeAnimator.getDuration();
}else{
return mSupportAnimator.getDuration();
}
}

/**
* Returns whether this Animator is currently running (having been started and gone past any
* initial startDelay period and not yet ended).
*
* @return Whether the Animator is running.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public boolean isRunning(){
if(LOLLIPOP){
return mNativeAnimator.isRunning();
}else{
return mSupportAnimator.isRunning();
}
}

/**
* Returns whether this Animator has been started and not yet ended. This state is a superset
* of the state of {@link #isRunning()}, because an Animator with a nonzero
* will return true for {@link #isStarted()} during the
* delay phase, whereas {@link #isRunning()} will return true only after the delay phase
* is complete.
*
* @return Whether the Animator has been started and not yet ended.
*/
public boolean isStarted() {
// Default method returns value for isRunning(). Subclasses should override to return a
// real value.
return isRunning();
}

/**
* Removes a listener from the set listening to this animation.
*
* @param listener the listener to be removed from the current set of listeners for this
* animation.
*/
public void removeListener(com.nineoldandroids.animation.Animator.AnimatorListener listener) {
mSupportAnimator.removeListener(listener);
}

/**
* Removes a listener from the set listening to this animation.
*
* @param listener the listener to be removed from the current set of listeners for this
* animation.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void removeListener(android.animation.Animator.AnimatorListener listener) {
mNativeAnimator.removeListener(listener);
}

/**
* Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
* listening for events on this <code>Animator</code> object.
*
* @return ArrayList<AnimatorListener> The set of listeners.
*/
public ArrayList<com.nineoldandroids.animation.Animator.AnimatorListener> getSupportListeners() {
return mSupportAnimator.getListeners();
}

/**
* Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
* listening for events on this <code>Animator</code> object.
*
* @return ArrayList<AnimatorListener> The set of listeners.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public ArrayList<android.animation.Animator.AnimatorListener> getNativeListeners() {
return mNativeAnimator.getListeners();
}

/**
* Removes a pause listener from the set listening to this animation.
*
* @param listener the listener to be removed from the current set of pause
* listeners for this animation.
*/
public void removePauseListener(com.nineoldandroids.animation.Animator.AnimatorPauseListener listener) {
mSupportAnimator.removePauseListener(listener);
}

/**
* Removes a pause listener from the set listening to this animation.
*
* @param listener the listener to be removed from the current set of pause
* listeners for this animation.
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public void removePauseListener(android.animation.Animator.AnimatorPauseListener listener) {
mNativeAnimator.removePauseListener(listener);
}

/**
* Removes all {@link #addListener(com.nineoldandroids.animation.Animator.AnimatorListener)} listeners}
* and {@link #addPauseListener(com.nineoldandroids.animation.Animator.AnimatorPauseListener)}
* pauseListeners} from this object.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void removeAllListeners() {
if(LOLLIPOP){
mNativeAnimator.removeAllListeners();
}else{
mSupportAnimator.removeAllListeners();
}
}

/**
* Starts this animation. If the animation has a nonzero startDelay, the animation will start
* running after that delay elapses. A non-delayed animation will have its initial
* value(s) set immediately, followed by calls to AnimationUpdate for any listeners of this animator.
*
* <p>The animation started by calling this method will be run on the thread that called
* this method. This thread should have a Looper on it (a runtime exception will be thrown if
* this is not the case). Also, if the animation will animate
* properties of objects in the view hierarchy, then the calling thread should be the UI
* thread for that view hierarchy.</p>
*
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void start() {
if(LOLLIPOP){
mNativeAnimator.start();
}else{
mSupportAnimator.start();
}
}


public com.nineoldandroids.animation.Animator getSupportAnimator(){
return mSupportAnimator;
}

public android.animation.Animator getNativeAnimator(){
return mNativeAnimator;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ public class ViewAnimationUtils {
* @param startRadius The starting radius of the animating circle.
* @param endRadius The ending radius of the animating circle.
*/
public static Animator createCircularReveal(View view,
public static io.codetail.animation.Animator createCircularReveal(View view,
int centerX, int centerY,
float startRadius, float endRadius) {

if(io.codetail.animation.Animator.LOLLIPOP){
return new io.codetail.animation.Animator(android.view.ViewAnimationUtils
.createCircularReveal(view, centerX, centerY, startRadius, endRadius));
}

if(!(view.getParent() instanceof RevealAnimator)){
throw new IllegalArgumentException("View must be inside dreamers.widget.RevealLayout.");
}
Expand All @@ -46,10 +51,10 @@ public static Animator createCircularReveal(View view,
Rect bounds = new Rect();
view.getHitRect(bounds);

Animator reveal = ObjectAnimator.ofFloat(revealLayout, "revealRadius", startRadius, endRadius);
ObjectAnimator reveal = ObjectAnimator.ofFloat(revealLayout, "revealRadius", startRadius, endRadius);
reveal.addListener(new RevealAnimator.RevealFinished(revealLayout, bounds));

return reveal;
return new io.codetail.animation.Animator(reveal);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@

import java.util.ArrayList;

import io.codetail.animation.Animator;
import io.codetail.view.R;

// Port of FrameLayout for Android 2.3 Gingerbread
public class FrameLayoutCompat extends ViewGroup{

private static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
private static final boolean FEATURES_HONEYCOMB = Build.VERSION.SDK_INT > 10;
private static final boolean FEATURES_KITKAT = Build.VERSION.SDK_INT > 16;
private static final boolean FEATURES_LOLLIPOP = Build.VERSION.SDK_INT > 16;
static final int DEFAULT_CHILD_GRAVITY = Gravity.TOP | Gravity.START;
static final boolean FEATURES_HONEYCOMB = Build.VERSION.SDK_INT > 10;
static final boolean FEATURES_KITKAT = Build.VERSION.SDK_INT > 16;
static final boolean FEATURES_LOLLIPOP = Animator.LOLLIPOP;

boolean mMeasureAllChildren = false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public RevealFrameLayout(Context context, AttributeSet attrs) {
public RevealFrameLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

if(FEATURES_HONEYCOMB && !FEATURES_KITKAT){
setLayerType(LAYER_TYPE_SOFTWARE, null);
}

mRevealPath = new Path();
}

Expand Down

0 comments on commit 607c2ca

Please sign in to comment.