Skip to content

Instantly share code, notes, and snippets.

@pdegand
Last active November 9, 2018 17:47
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pdegand/835d3598b4b3343ba545 to your computer and use it in GitHub Desktop.
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+
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="6dp" />
<stroke
android:width="2dp"
android:color="@android:color/black" />
<solid android:color="@android:color/transparent" />
<padding
android:bottom="8dp"
android:top="8dp" />
</shape>
/*
* 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
);
}
}
<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