| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- package com.ht.gate;
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.content.res.TypedArray;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.DrawFilter;
- import android.graphics.LinearGradient;
- import android.graphics.Paint;
- import android.graphics.PaintFlagsDrawFilter;
- import android.graphics.Path;
- import android.graphics.Rect;
- import android.graphics.RectF;
- import android.graphics.Shader;
- import android.graphics.Typeface;
- import android.text.TextUtils;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.util.TypedValue;
- import android.view.MotionEvent;
- import android.view.View;
- import androidx.annotation.Nullable;
- import androidx.core.content.res.ResourcesCompat;
- public class UnlockView extends View {
- private Paint borderPaint;
- private Paint linePaint;
- private Paint textPaint;
- private Shader lineShader;
- private Path borderPath;
- private float borderWidth;
- private Bitmap bmUnlock;
- private Bitmap bmUnlocked;
- private float distance = 0;
- private float padding = 0;
- private boolean down;
- private float lastX;
- private Rect src, src1;
- private RectF dst, dst1;
- private DrawFilter drawFilter;
- private Typeface source_han_sans_sc_normal;
- private Typeface source_han_sans_sc_light;
- private int colorLight = 0xFFFFFFFF;
- private int colorDark = 0xFF222639;
- private int colorUnlockedLight = 0x11C1C3CD;
- private int colorUnlockedDark = 0x1E222639;
- private boolean dark;
- private boolean preUnlock = false;
- private String hint;
- private UnlockListener unlockListener;
- private boolean unlocked;
- public interface UnlockListener {
- void onUnlock();
- }
- public void setUnlockListener(UnlockListener unlockListener) {
- this.unlockListener = unlockListener;
- }
- public UnlockView(Context context) {
- this(context, null);
- }
- public UnlockView(Context context, @Nullable AttributeSet attrs) {
- this(context, attrs, 0);
- }
- public UnlockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
- public UnlockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- TypedArray t = getContext().obtainStyledAttributes(attrs,
- R.styleable.UnlockView);
- hint = t.getString(R.styleable.UnlockView_hint);
- if (TextUtils.isEmpty(hint)) {
- hint = "滑动解锁";
- }
- dark = t.getBoolean(R.styleable.UnlockView_darkMode, false);
- t.recycle();
- source_han_sans_sc_normal = ResourcesCompat.getFont(getContext(), R.font.source_han_sans_sc_normal);
- source_han_sans_sc_light = ResourcesCompat.getFont(getContext(), R.font.source_han_sans_sc_light);
- borderPaint = new Paint();
- borderPaint.setAntiAlias(true);
- borderWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getContext().getResources().getDisplayMetrics());
- borderPaint.setStrokeWidth(borderWidth);
- borderPaint.setStyle(Paint.Style.STROKE);
- borderPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
- borderPath = new Path();
- padding = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 7, getContext().getResources().getDisplayMetrics());
- bmUnlock = BitmapFactory.decodeResource(getResources(), dark ? R.mipmap.icon_unlock_dark : R.mipmap.icon_unlock);
- bmUnlocked = BitmapFactory.decodeResource(getResources(), dark ? R.mipmap.icon_unlocked_dark : R.mipmap.icon_unlocked);
- src = new Rect(0, 0, bmUnlock.getWidth(), bmUnlock.getHeight());
- dst = new RectF();
- src1 = new Rect(0, 0, bmUnlocked.getWidth(), bmUnlocked.getHeight());
- dst1 = new RectF();
- drawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- linePaint = new Paint();
- linePaint.setAntiAlias(true);
- linePaint.setStrokeCap(Paint.Cap.ROUND);
- textPaint = new Paint();
- textPaint.setAntiAlias(true);
- textPaint.setTextSize(sp2px(25));
- textPaint.setStyle(Paint.Style.FILL);
- textPaint.setTypeface(source_han_sans_sc_light);
- }
- public void setUnlocked(boolean unlocked) {
- this.unlocked = unlocked;
- postInvalidate();
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
- @SuppressLint("DrawAllocation")
- @Override
- protected void onDraw(Canvas canvas) {
- canvas.setDrawFilter(drawFilter);
- float width = getWidth();
- float height = getHeight();
- float d = (height - borderWidth);
- float r = d / 2;
- if (unlocked) {
- borderPaint.setColor(dark ? colorUnlockedDark : colorUnlockedLight);
- borderPaint.setStyle(Paint.Style.FILL);
- textPaint.setColor(dark ? colorDark : colorLight);
- canvas.drawRoundRect(0, 0, width, height, height / 2, height / 2, borderPaint);
- float textWidth = textPaint.measureText("已解锁");
- float baseLineY = Math.abs(textPaint.ascent() + textPaint.descent()) / 2 + getHeight() / 2f;
- canvas.drawText("已解锁", (getWidth() + dp2px(32)) / 2f - textWidth / 2, baseLineY, textPaint);
- dst1.left = (width - textPaint.measureText("已解锁") - dp2px(32)) / 2;
- dst1.top = (height - dp2px(26)) / 2;
- dst1.right = dst1.left + dp2px(21);
- dst1.bottom = dst1.top + dp2px(26);
- canvas.drawBitmap(bmUnlocked, src1, dst1, null);
- return;
- } else {
- borderPaint.setStyle(Paint.Style.STROKE);
- if (dark) {
- borderPaint.setColor(colorDark);
- textPaint.setColor(colorDark);
- } else {
- borderPaint.setColor(colorLight);
- textPaint.setColor(colorLight);
- }
- }
- borderPath.reset();
- borderPath.moveTo(r + borderWidth / 2, borderWidth / 2);
- borderPath.lineTo(r + borderWidth / 2, borderWidth / 2);
- borderPath.lineTo(width - r, borderWidth / 2);
- borderPath.arcTo(width - d - borderWidth / 2, borderWidth / 2, width - borderWidth / 2, height - borderWidth / 2, -90, 180, true);
- borderPath.lineTo(r + borderWidth / 2, height - borderWidth / 2);
- borderPath.arcTo(borderWidth / 2, borderWidth / 2, d + borderWidth / 2, height - borderWidth / 2, 90, 180, true);
- canvas.drawPath(borderPath, borderPaint);
- float size = height - padding * 2;
- int dd = (int) Math.max(0, Math.min(distance, getWidth() - padding * 2 - size));
- linePaint.setStrokeWidth(height - padding * 2);
- lineShader = dark ? new LinearGradient(0, 0, width, 0,
- new int[]{0x00222639,
- 0x1F222639,
- 0x78222639,
- 0xD4222639},
- new float[]{0, 0.19f, 0.42f, 1}, Shader.TileMode.CLAMP)
- : new LinearGradient(0, 0, width, 0,
- new int[]{Color.argb(0, 255, 255, 255),
- Color.argb(30, 255, 255, 255),
- Color.argb(117, 255, 255, 255),
- Color.argb(255, 255, 255, 255)},
- new float[]{0, 0.19f, 0.42f, 1}, Shader.TileMode.CLAMP);
- linePaint.setShader(lineShader);
- canvas.drawLine(r, height / 2, r + dd, height / 2, linePaint);
- drawCenterText(canvas, textPaint, hint);
- dst.left = (int) padding + dd;
- dst.top = (int) padding;
- dst.right = (int) (padding + size + dd);
- dst.bottom = (int) (padding + size);
- canvas.drawBitmap(bmUnlock, src, dst, null);
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- if (event.getX() < getHeight() && event.getY() < getHeight()) {
- down = true;
- lastX = event.getX();
- }
- break;
- case MotionEvent.ACTION_UP:
- distance = 0;
- down = false;
- preUnlock = false;
- postInvalidate();
- break;
- case MotionEvent.ACTION_MOVE:
- if (down) {
- distance += event.getX() - lastX;
- lastX = event.getX();
- if (distance >= getWidth() - padding * 2 - (getHeight() - padding * 2) && !preUnlock) {
- preUnlock = true;
- if (unlockListener != null) {
- unlockListener.onUnlock();
- }
- }
- postInvalidate();
- }
- break;
- }
- return true;
- }
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- if (bmUnlock != null && !bmUnlock.isRecycled()) {
- bmUnlock.recycle();
- bmUnlock = null;
- }
- }
- private void drawCenterText(Canvas canvas, Paint paint, String text) {
- // 文本宽
- float textWidth = paint.measureText(text);
- // 文本baseline在y轴方向的位置
- float baseLineY = Math.abs(paint.ascent() + paint.descent()) / 2 + getHeight() / 2f;
- canvas.drawText(text, getWidth() / 2f - textWidth / 2, baseLineY, paint);
- }
- public int sp2px(float sp) {
- return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
- getContext().getResources().getDisplayMetrics());
- }
- public int dp2px(float dp) {
- return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
- getContext().getResources().getDisplayMetrics());
- }
- }
|