FairEmail/colorpicker/src/main/java/com/flask/colorpicker/slider/AbsCustomSlider.java

189 lines
5.1 KiB
Java

package com.flask.colorpicker.slider;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import androidx.annotation.DimenRes;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.flask.colorpicker.R;
public abstract class AbsCustomSlider extends View {
protected Bitmap bitmap;
protected Canvas bitmapCanvas;
protected Bitmap bar;
protected Canvas barCanvas;
protected OnValueChangedListener onValueChangedListener;
protected int barOffsetX;
protected int handleRadius = 20;
protected int barHeight = 5;
protected float value = 1;
protected boolean showBorder = false;
private boolean inVerticalOrientation = false;
public AbsCustomSlider(Context context) {
super(context);
init(context, null);
}
public AbsCustomSlider(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public AbsCustomSlider(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray styledAttrs = context.getTheme().obtainStyledAttributes(
attrs, R.styleable.AbsCustomSlider, 0, 0);
try {
inVerticalOrientation = styledAttrs.getBoolean(
R.styleable.AbsCustomSlider_inVerticalOrientation, inVerticalOrientation);
} finally {
styledAttrs.recycle();
}
}
protected void updateBar() {
handleRadius = getDimension(R.dimen.default_slider_handler_radius);
barHeight = getDimension(R.dimen.default_slider_bar_height);
barOffsetX = handleRadius;
if (bar == null)
createBitmaps();
drawBar(barCanvas);
invalidate();
}
protected void createBitmaps() {
int width;
int height;
if (inVerticalOrientation) {
width = getHeight();
height = getWidth();
} else {
width = getWidth();
height = getHeight();
}
bar = Bitmap.createBitmap(Math.max(width - barOffsetX * 2, 1), barHeight, Bitmap.Config.ARGB_8888);
barCanvas = new Canvas(bar);
if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
if (bitmap != null) bitmap.recycle();
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas(bitmap);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width;
int height;
if (inVerticalOrientation) {
width = getHeight();
height = getWidth();
canvas.rotate(-90);
canvas.translate(-width, 0);
} else {
width = getWidth();
height = getHeight();
}
if (bar != null && bitmapCanvas != null) {
bitmapCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
bitmapCanvas.drawBitmap(bar, barOffsetX, (height - bar.getHeight()) / 2, null);
float x = handleRadius + value * (width - handleRadius * 2);
float y = height / 2f;
drawHandle(bitmapCanvas, x, y);
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
protected abstract void drawBar(Canvas barCanvas);
protected abstract void onValueChanged(float value);
protected abstract void drawHandle(Canvas canvas, float x, float y);
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
updateBar();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int width = 0;
if (widthMode == MeasureSpec.UNSPECIFIED)
width = widthMeasureSpec;
else if (widthMode == MeasureSpec.AT_MOST)
width = MeasureSpec.getSize(widthMeasureSpec);
else if (widthMode == MeasureSpec.EXACTLY)
width = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int height = 0;
if (heightMode == MeasureSpec.UNSPECIFIED)
height = heightMeasureSpec;
else if (heightMode == MeasureSpec.AT_MOST)
height = MeasureSpec.getSize(heightMeasureSpec);
else if (heightMode == MeasureSpec.EXACTLY)
height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE: {
if (bar != null) {
if (inVerticalOrientation) {
value = 1 - (event.getY() - barOffsetX) / bar.getWidth();
} else {
value = (event.getX() - barOffsetX) / bar.getWidth();
}
value = Math.max(0, Math.min(value, 1));
onValueChanged(value);
invalidate();
}
break;
}
case MotionEvent.ACTION_UP: {
onValueChanged(value);
if (onValueChangedListener != null)
onValueChangedListener.onValueChanged(value);
invalidate();
}
}
return true;
}
protected int getDimension(@DimenRes int id) {
return getResources().getDimensionPixelSize(id);
}
public void setShowBorder(boolean showBorder) {
this.showBorder = showBorder;
}
public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
this.onValueChangedListener = onValueChangedListener;
}
}