package com.looklook.xinghongfei.looklook.widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.support.annotation.ColorInt; import android.support.annotation.FloatRange; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.util.Property; import android.widget.TextView; import com.looklook.xinghongfei.looklook.R; import com.looklook.xinghongfei.looklook.util.AnimUtils; import com.looklook.xinghongfei.looklook.util.ColorUtils; /** * Created by xinghongfei on 16/8/20. */ public class TranslateYTextView extends TextView { private static final int[] STATE_PINNED = {R.attr.state_pinned}; private Paint scrimPaint; private int imageOffset; private int minOffset; private float scrimAlpha = 0f; private float maxScrimAlpha = 1f; private int scrimColor = 0x00000000; private float parallaxFactor = -0.5f; private boolean isPinned = false; private boolean immediatePin = false; public static final Property<MyParallaxScrimageView, Float> OFFSET = new AnimUtils .FloatProperty<MyParallaxScrimageView>("offset") { @Override public void setValue(MyParallaxScrimageView parallaxScrimageView, float value) { parallaxScrimageView.setOffset(value); } @Override public Float get(MyParallaxScrimageView parallaxScrimageView) { return parallaxScrimageView.getOffset(); } }; public TranslateYTextView(Context context, AttributeSet attrs) { super(context, attrs); final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable .ParallaxScrimageView); if (a.hasValue(R.styleable.ParallaxScrimageView_scrimColor)) { scrimColor = a.getColor(R.styleable.ParallaxScrimageView_scrimColor, scrimColor); } if (a.hasValue(R.styleable.ParallaxScrimageView_scrimAlpha)) { scrimAlpha = a.getFloat(R.styleable.ParallaxScrimageView_scrimAlpha, scrimAlpha); } if (a.hasValue(R.styleable.ParallaxScrimageView_maxScrimAlpha)) { maxScrimAlpha = a.getFloat(R.styleable.ParallaxScrimageView_maxScrimAlpha, maxScrimAlpha); } if (a.hasValue(R.styleable.ParallaxScrimageView_parallaxFactor)) { parallaxFactor = a.getFloat(R.styleable.ParallaxScrimageView_parallaxFactor, parallaxFactor); } a.recycle(); scrimPaint = new Paint(); scrimPaint.setColor(ColorUtils.modifyAlpha(scrimColor, scrimAlpha)); } public TranslateYTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public TranslateYTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public float getOffset() { return getTranslationY(); } public void setOffset(float offset) { offset = Math.max(minOffset, offset); if (offset != getTranslationY()) { setTranslationY(offset); imageOffset = (int) (offset * parallaxFactor); setScrimAlpha(Math.min((-offset / getMinimumHeight()) * maxScrimAlpha, maxScrimAlpha)); ViewCompat.postInvalidateOnAnimation(this); } setPinned(offset == minOffset); } public void setScrimColor(@ColorInt int scrimColor) { if (this.scrimColor != scrimColor) { this.scrimColor = scrimColor; ViewCompat.postInvalidateOnAnimation(this); } } public void setScrimAlpha(@FloatRange(from = 0f, to = 1f) float alpha) { if (scrimAlpha != alpha) { scrimAlpha = alpha; scrimPaint.setColor(ColorUtils.modifyAlpha(scrimColor, scrimAlpha)); ViewCompat.postInvalidateOnAnimation(this); } } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); if (h > getMinimumHeight()) { minOffset = getMinimumHeight() - h; } } @Override public void setTextColor(int color) { } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } @Override public int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isPinned) { mergeDrawableStates(drawableState, STATE_PINNED); } return drawableState; } public boolean isPinned() { return isPinned; } public void setPinned(boolean isPinned) { if (this.isPinned != isPinned) { this.isPinned = isPinned; refreshDrawableState(); if (isPinned && immediatePin) { jumpDrawablesToCurrentState(); } } } public boolean isImmediatePin() { return immediatePin; } /** * As the pinned state is designed to work with a {@see StateListAnimator}, we may want to short * circuit this animation in certain situations e.g. when flinging a list. */ public void setImmediatePin(boolean immediatePin) { this.immediatePin = immediatePin; } }