Last active
November 9, 2018 17:47
-
-
Save pdegand/835d3598b4b3343ba545 to your computer and use it in GitHub Desktop.
Shinny TextView that glows like the "slide to unlock" text on iOS 7+
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2014 Pierre Degand | |
* | |
* 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 fr.pdegand.animatedgradient; | |
import android.animation.ValueAnimator; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.LinearGradient; | |
import android.graphics.PorterDuff; | |
import android.graphics.PorterDuffXfermode; | |
import android.graphics.Shader; | |
import android.graphics.drawable.PaintDrawable; | |
import android.util.AttributeSet; | |
import android.view.View; | |
import android.view.animation.LinearInterpolator; | |
import android.widget.TextView; | |
/** | |
* @author Pierre Degand | |
*/ | |
public class ShinnyTextView extends TextView { | |
private float mGradientDiameter = 0.3f; | |
private ValueAnimator mAnimator; | |
private float mGradientCenter; | |
private PaintDrawable mShineDrawable; | |
public ShinnyTextView(final Context context) { | |
this(context, null); | |
} | |
public ShinnyTextView(final Context context, final AttributeSet attrs) { | |
this(context, attrs, 0); | |
} | |
public ShinnyTextView(final Context context, final AttributeSet attrs, final int defStyleAttr) { | |
super(context, attrs, defStyleAttr); | |
setLayerType(View.LAYER_TYPE_SOFTWARE, null); | |
} | |
@Override | |
protected void onSizeChanged(final int w, final int h, final int oldw, final int oldh) { | |
super.onSizeChanged(w, h, oldw, oldh); | |
if (!isInEditMode()) { | |
if (mAnimator != null) { | |
mAnimator.cancel(); | |
} | |
mShineDrawable = new PaintDrawable(); | |
mShineDrawable.setBounds(0, 0, w, h); | |
mShineDrawable.getPaint().setShader(generateGradientShader(getWidth(), 0, 0, 0)); | |
mShineDrawable.getPaint().setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); | |
mAnimator = ValueAnimator.ofFloat(0, 1); | |
mAnimator.setDuration(5 * w); // custom | |
mAnimator.setRepeatCount(ValueAnimator.INFINITE); | |
mAnimator.setRepeatMode(ValueAnimator.RESTART); | |
mAnimator.setInterpolator(new LinearInterpolator()); // Custom | |
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { | |
@Override | |
public void onAnimationUpdate(final ValueAnimator animation) { | |
final float value = animation.getAnimatedFraction(); | |
mGradientCenter = (1 + 2 * mGradientDiameter) * value - mGradientDiameter; | |
final float gradientStart = mGradientCenter - mGradientDiameter; | |
final float gradientEnd = mGradientCenter + mGradientDiameter; | |
Shader shader = generateGradientShader(w, gradientStart, mGradientCenter, gradientEnd); | |
mShineDrawable.getPaint().setShader(shader); | |
invalidate(); | |
} | |
}); | |
mAnimator.start(); | |
} | |
} | |
@Override | |
protected void onDraw(final Canvas canvas) { | |
super.onDraw(canvas); | |
if (!isInEditMode() && mShineDrawable != null) { | |
mShineDrawable.draw(canvas); | |
} | |
} | |
private Shader generateGradientShader(int width, float... positions) { | |
int[] colorRepartition = {Color.GRAY, Color.WHITE, Color.GRAY}; | |
return new LinearGradient( | |
0, | |
0, | |
width, | |
0, | |
colorRepartition, | |
positions, | |
Shader.TileMode.REPEAT | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<fr.pdegand.animatedgradient.ShinnyTextView | |
android:id="@+id/button" | |
android:text="Get It!" | |
android:layout_width="match_parent" | |
android:layout_height="wrap_content" | |
android:drawableRight="@drawable/ic_chevron_right_black_36dp" | |
android:gravity="center" | |
android:textSize="22sp" | |
android:background="@drawable/bg_button_gradient"/> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment