/*

  • MIT License
  • Copyright (c) 2016 Knowledge, education for life.
  • Permission is hereby granted, free of charge, to any person obtaining a copy
  • of this software and associated documentation files (the 'Software'), to deal
  • in the Software without restriction, including without limitation the rights
  • to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  • copies of the Software, and to permit persons to whom the Software is
  • furnished to do so, subject to the following conditions:
  • The above copyright notice and this permission notice shall be included in all
  • copies or substantial portions of the Software.
  • THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  • IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  • FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  • AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  • LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  • OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  • SOFTWARE. */ package com.lb.video_trimmer_library.view;

import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.util.TypedValue; import android.view.MotionEvent; import android.view.View;

import androidx.annotation.ColorInt;

import com.lb.video_trimmer_library.interfaces.OnRangeSeekBarListener;

import java.util.HashSet;

public class RangeSeekBarView extends View { public enum ThumbType { LEFT(0), RIGHT(1);

    private final int index;

    ThumbType(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }
}

private final float thumbTouchExtraMultiplier = initThumbTouchExtraMultiplier();
private final Thumb[] thumbs = {new Thumb(ThumbType.LEFT.getIndex()), new Thumb(ThumbType.RIGHT.getIndex())};
private final HashSet<OnRangeSeekBarListener> listeners = new HashSet<>();
private float maxWidth;
private final int thumbWidth = initThumbWidth(getContext());
private int viewWidth;
private float pixelRangeMin;
private float pixelRangeMax;
private final float scaleRangeMax = 100f;
private boolean firstRun = true;
private final Paint shadowPaint = new Paint();
private final Paint strokePaint = new Paint();
private final Paint edgePaint = new Paint();
private int currentThumb = ThumbType.LEFT.getIndex();

public RangeSeekBarView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setFocusable(true);
    setFocusableInTouchMode(true);
    shadowPaint.setAntiAlias(true);
    shadowPaint.setColor(initShadowColor());
    strokePaint.setAntiAlias(true);
    strokePaint.setStyle(Paint.Style.STROKE);
    strokePaint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2f, context.getResources().getDisplayMetrics()));
    strokePaint.setColor(0xffffffff);
    edgePaint.setAntiAlias(true);
    edgePaint.setColor(0xffffffff);
}

public RangeSeekBarView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public RangeSeekBarView(Context context) {
    this(context, null);
}

@ColorInt
protected int initShadowColor() {
    return 0xB1000000;
}

protected float initThumbTouchExtraMultiplier() {
    return 1.0f;
}

protected int initThumbWidth(Context context) {
    return Math.max((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 27f, context.getResources().getDisplayMetrics()), 1);
}

public void initMaxWidth() {
    maxWidth = thumbs[ThumbType.RIGHT.getIndex()].pos - thumbs[ThumbType.LEFT.getIndex()].pos;
    onSeekStop(this, ThumbType.LEFT.getIndex(), thumbs[ThumbType.LEFT.getIndex()].value);
    onSeekStop(this, ThumbType.RIGHT.getIndex(), thumbs[ThumbType.RIGHT.getIndex()].value);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    viewWidth = getMeasuredWidth();
    pixelRangeMin = 0f;
    pixelRangeMax = viewWidth - thumbWidth;
    if (firstRun) {
        for (Thumb thumb : thumbs) {
            thumb.value = scaleRangeMax * thumb.index;
            thumb.pos = pixelRangeMax * thumb.index;
        }
        // Fire listener callback
        onCreate(this, currentThumb, getThumbValue(currentThumb));
        firstRun = false;
    }
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (thumbs.length == 0) {
        return;
    }
    // draw shadows outside of selected range
    for (Thumb thumb : thumbs) {
        if (thumb.index == ThumbType.LEFT.getIndex()) {
            float x = thumb.pos + getPaddingLeft();
            if (x > pixelRangeMin) {
                canvas.drawRect(thumbWidth, 0f, x + thumbWidth, getHeight(), shadowPaint);
            }
        } else {
            float x = thumb.pos - getPaddingRight();
            if (x < pixelRangeMax) {
                canvas.drawRect(x, 0f, viewWidth - thumbWidth, getHeight(), shadowPaint);
            }
        }
    }
    // draw stroke around selected range
    canvas.drawRect(thumbs[ThumbType.LEFT.getIndex()].pos + getPaddingLeft() + thumbWidth, 0f,
            thumbs[ThumbType.RIGHT.getIndex()].pos - getPaddingRight(), getHeight(), strokePaint);
    // draw edges
    float circleRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6f, getContext().getResources().getDisplayMetrics());
    canvas.drawCircle(thumbs[ThumbType.LEFT.getIndex()].pos + getPaddingLeft() + thumbWidth, getHeight() / 2f, circleRadius, edgePaint);
    canvas.drawCircle(thumbs[ThumbType.RIGHT.getIndex()].pos - getPaddingRight(), getHeight() / 2f, circleRadius, edgePaint);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    Thumb mThumb;
    Thumb mThumb2;
    float coordinate = ev.getX();
    int action = ev.getAction();
    switch (action) {
        case MotionEvent.ACTION_DOWN -> {
            // Remember where we started
            currentThumb = getClosestThumb(coordinate);
            if (currentThumb == -1)
                return false;
            mThumb = thumbs[currentThumb];
            mThumb.lastTouchX = coordinate;
            onSeekStart(this, currentThumb, mThumb.value);
            return true;
        }
        case MotionEvent.ACTION_UP -> {
            if (currentThumb == -1)
                return false;
            mThumb = thumbs[currentThumb];
            onSeekStop(this, currentThumb, mThumb.value);
            return true;
        }
        case MotionEvent.ACTION_MOVE -> {
            mThumb = thumbs[currentThumb];
            mThumb2 =
                    thumbs[currentThumb == ThumbType.LEFT.getIndex() ? ThumbType.RIGHT.getIndex() : ThumbType.LEFT.getIndex()];
            // Calculate the distance moved
            float dx = coordinate - mThumb.lastTouchX;
            float newX = mThumb.pos + dx;
            if (currentThumb == 0) {
                if (newX + thumbWidth >= mThumb2.pos) {
                    mThumb.pos = mThumb2.pos - thumbWidth;
                } else if (newX <= pixelRangeMin) {
                    mThumb.pos = pixelRangeMin;
                } else {
                    // Check if thumb is not out of max width
                    checkPositionThumb(mThumb, mThumb2, dx, true);
                    // Move the object
                    mThumb.pos = mThumb.pos + dx;
                    // Remember this touch position for the next move event
                    mThumb.lastTouchX = coordinate;
                }
            } else if (newX <= mThumb2.pos + thumbWidth) {
                mThumb.pos = mThumb2.pos + thumbWidth;
            } else if (newX >= pixelRangeMax) {
                mThumb.pos = pixelRangeMax;
            } else {
                // Check if thumb is not out of max width
                checkPositionThumb(mThumb2, mThumb, dx, false);
                // Move the object
                mThumb.pos = mThumb.pos + dx;
                // Remember this touch position for the next move event
                mThumb.lastTouchX = coordinate;
            }
            setThumbPos(currentThumb, mThumb.pos);
            // Invalidate to request a redraw
            invalidate();
            return true;
        }
    }
    return false;
}

private void checkPositionThumb(Thumb thumbLeft, Thumb thumbRight, float dx, boolean isLeftMove) {
    if (isLeftMove && dx < 0) {
        if (thumbRight.pos - (thumbLeft.pos + dx) > maxWidth) {
            thumbRight.pos = thumbLeft.pos + dx + maxWidth;
            setThumbPos(ThumbType.RIGHT.getIndex(), thumbRight.pos);
        }
    } else if (!isLeftMove && dx > 0) {
        if (thumbRight.pos + dx - thumbLeft.pos > maxWidth) {
            thumbLeft.pos = thumbRight.pos + dx - maxWidth;
            setThumbPos(ThumbType.LEFT.getIndex(), thumbLeft.pos);
        }
    }
}

private float pixelToScale(int index, float pixelValue) {
    float scale = pixelValue * 100 / pixelRangeMax;
    if (index == 0) {
        float pxThumb = scale * thumbWidth / 100;
        return scale + pxThumb * 100 / pixelRangeMax;
    } else {
        float pxThumb = (100 - scale) * thumbWidth / 100;
        return scale - pxThumb * 100 / pixelRangeMax;
    }
}

private float scaleToPixel(int index, float scaleValue) {
    float px = scaleValue * pixelRangeMax / 100;
    if (index == 0) {
        float pxThumb = scaleValue * thumbWidth / 100;
        return px - pxThumb;
    } else {
        float pxThumb = (100 - scaleValue) * thumbWidth / 100;
        return px + pxThumb;
    }
}

private void calculateThumbValue(int index) {
    if (index < thumbs.length && thumbs.length != 0) {
        Thumb th = thumbs[index];
        th.value = pixelToScale(index, th.pos);
        onSeek(this, index, th.value);
    }
}

private void calculateThumbPos(int index) {
    if (index < thumbs.length && thumbs.length != 0) {
        Thumb th = thumbs[index];
        th.pos = scaleToPixel(index, th.value);
    }
}

private float getThumbValue(int index) {
    return thumbs[index].value;
}

public void setThumbValue(int index, float value) {
    thumbs[index].value = value;
    calculateThumbPos(index);
    // Tell the view we want a complete redraw
    invalidate();
}

private void setThumbPos(int index, float pos) {
    thumbs[index].pos = pos;
    calculateThumbValue(index);
    // Tell the view we want a complete redraw
    invalidate();
}

private int getClosestThumb(float xPos) {
    if (thumbs.length == 0)
        return -1;
    int closest = -1;
    float minDistanceFound = Float.MAX_VALUE;
    float x = xPos - thumbWidth;//+ paddingLeft

// Log.d("AppLog", "xPos:$xPos -> x: $x"); for (Thumb thumb : thumbs) { float thumbPos = thumb.index == ThumbType.LEFT.getIndex() ? thumb.pos : thumb.pos - thumbWidth; // Log.d("AppLog", "thumb ${thumb.index} pos: $thumbPos"); // Find thumb closest to x coordinate float xMin = thumbPos - thumbWidth * thumbTouchExtraMultiplier; float xMax = thumbPos + thumbWidth * thumbTouchExtraMultiplier; if (x >= xMin && x <= xMax) { float distance = Math.abs(thumbPos - x); if (distance < minDistanceFound) { closest = thumb.index; // Log.d("AppLog", "x: $x distance: $distance selectedThumb:$closest"); minDistanceFound = distance; } } } return closest; }

public void addOnRangeSeekBarListener(OnRangeSeekBarListener listener) {
    listeners.add(listener);
}

private void onCreate(RangeSeekBarView rangeSeekBarView, int index, float value) {
    for (OnRangeSeekBarListener item : listeners) {
        item.onCreate(rangeSeekBarView, index, value);
    }
}

private void onSeek(RangeSeekBarView rangeSeekBarView, int index, float value) {
    for (OnRangeSeekBarListener item : listeners) {
        item.onSeek(rangeSeekBarView, index, value);
    }
}

private void onSeekStart(RangeSeekBarView rangeSeekBarView, int index, float value) {
    for (OnRangeSeekBarListener item : listeners) {
        item.onSeekStart(rangeSeekBarView, index, value);
    }
}

private void onSeekStop(RangeSeekBarView rangeSeekBarView, int index, float value) {
    for (OnRangeSeekBarListener item : listeners) {
        item.onSeekStop(rangeSeekBarView, index, value);
    }
}

public static class Thumb {
    private final int index;
    private float value;
    private float pos;
    private float lastTouchX;

    public Thumb(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }

    public float getValue() {
        return value;
    }

    public void setValue(float value) {
        this.value = value;
    }

    public float getPos() {
        return pos;
    }

    public void setPos(float pos) {
        this.pos = pos;
    }

    public float getLastTouchX() {
        return lastTouchX;
    }

    public void setLastTouchX(float lastTouchX) {
        this.lastTouchX = lastTouchX;
    }
}

}

Kotlin to Java Conversion: RangeSeekBarView Class

原文地址: https://www.cveoy.top/t/topic/eDUe 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录