Add files
This commit is contained in:
1 parent
217c81a6d1
commit
d1650c4ec5
297 files changed
+105101
-116
No files matched your search
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* 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 com.hippo.widget;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.anani.AnimationUtils;
|
||||
import com.hippo.anani.SimpleAnimatorListener;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.hotspot.HotspotTouchHelper;
|
||||
import com.hippo.hotspot.Hotspotable;
|
||||
import com.hippo.yorozuya.MathUtils;
|
||||
|
||||
public class CheckTextView extends TextView implements OnClickListener, Hotspotable {
|
||||
|
||||
private static final String STATE_KEY_SUPER = "super";
|
||||
private static final String STATE_KEY_CHECKED = "checked";
|
||||
|
||||
private static final long ANIMATION_DURATION = 200;
|
||||
|
||||
private int mMaskColor;
|
||||
|
||||
private boolean mChecked = false;
|
||||
private boolean mPrepareAnimator = false;
|
||||
|
||||
private Paint mPaint;
|
||||
private float mRadius = 0f;
|
||||
private float mX;
|
||||
private float mY;
|
||||
|
||||
Animator mAnimator;
|
||||
|
||||
private float mMaxRadius;
|
||||
|
||||
public CheckTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public CheckTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CheckTextView);
|
||||
mMaskColor = a.getColor(R.styleable.CheckTextView_maskColor, Color.WHITE);
|
||||
a.recycle();
|
||||
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
|
||||
mPaint.setColor(mMaskColor);
|
||||
|
||||
setOnClickListener(this);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
HotspotTouchHelper.setHotspotTouchHelper(this, new HotspotTouchHelper(this));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHotspot(float x, float y) {
|
||||
mX = x;
|
||||
mY = y;
|
||||
mMaxRadius = MathUtils.coverageRadius(getWidth(), getHeight(), x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawableHotspotChanged(float x, float y) {
|
||||
super.drawableHotspotChanged(x, y);
|
||||
|
||||
mX = x;
|
||||
mY = y;
|
||||
mMaxRadius = MathUtils.coverageRadius(getWidth(), getHeight(), x, y);
|
||||
}
|
||||
|
||||
public void setRadius(float radius) {
|
||||
float bigger = Math.max(mRadius, radius);
|
||||
mRadius = radius;
|
||||
invalidate((int) (mX - bigger), (int) (mY - bigger), (int) (mX + bigger), (int) (mY + bigger));
|
||||
}
|
||||
|
||||
public float getRadius() {
|
||||
return mRadius;
|
||||
}
|
||||
|
||||
private Animator.AnimatorListener mAnimatorListener = new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimator = null;
|
||||
}
|
||||
};
|
||||
|
||||
public void prepareAnimations() {
|
||||
mPrepareAnimator = true;
|
||||
}
|
||||
|
||||
private void createAnimations() {
|
||||
float startRadius;
|
||||
float endRadius;
|
||||
Interpolator interpolator;
|
||||
if (mChecked) {
|
||||
startRadius = 0;
|
||||
endRadius = mMaxRadius;
|
||||
interpolator = AnimationUtils.FAST_SLOW_INTERPOLATOR;
|
||||
} else {
|
||||
startRadius = mMaxRadius;
|
||||
endRadius = 0;
|
||||
interpolator = AnimationUtils.SLOW_FAST_INTERPOLATOR;
|
||||
}
|
||||
mRadius = startRadius;
|
||||
|
||||
final ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this, "radius", startRadius, endRadius);
|
||||
radiusAnim.setDuration(ANIMATION_DURATION);
|
||||
radiusAnim.setInterpolator(interpolator);
|
||||
radiusAnim.addListener(mAnimatorListener);
|
||||
radiusAnim.start();
|
||||
mAnimator = radiusAnim;
|
||||
}
|
||||
|
||||
private void cancelAnimations() {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
setChecked(!mChecked);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(@NonNull Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
if (mPrepareAnimator) {
|
||||
mPrepareAnimator = false;
|
||||
cancelAnimations();
|
||||
createAnimations();
|
||||
}
|
||||
|
||||
if (mAnimator != null) {
|
||||
canvas.drawCircle(mX, mY, mRadius, mPaint);
|
||||
} else {
|
||||
if (mChecked) {
|
||||
canvas.drawColor(mMaskColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setChecked(boolean checked) {
|
||||
setChecked(checked, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the checked state of this CheckTextView.
|
||||
*
|
||||
* @param checked checked true to check the CheckTextView, false to uncheck it
|
||||
* @param animation true for show animation
|
||||
*/
|
||||
public void setChecked(boolean checked, boolean animation) {
|
||||
if (mChecked != checked) {
|
||||
mChecked = checked;
|
||||
|
||||
if (animation) {
|
||||
prepareAnimations();
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the checked state of it.
|
||||
*
|
||||
* @return true is it is checked
|
||||
*/
|
||||
public boolean isChecked() {
|
||||
return mChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
final Bundle state = new Bundle();
|
||||
state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState());
|
||||
state.putBoolean(STATE_KEY_CHECKED, mChecked);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
if (state instanceof Bundle) {
|
||||
final Bundle savedState = (Bundle) state;
|
||||
super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER));
|
||||
setChecked(savedState.getBoolean(STATE_KEY_CHECKED), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user