mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
beautify slider element.
This commit is contained in:
@@ -60,8 +60,7 @@
|
||||
|
||||
|
||||
<org.thoughtcrime.securesms.components.rangeslider.TimeRangeSlider
|
||||
|
||||
android:layout_marginTop="10dp"
|
||||
android:id="@+id/timeRangeSlider"
|
||||
android:layout_marginBottom="10dp"
|
||||
|
||||
android:paddingStart="32dp"
|
||||
|
||||
@@ -17,15 +17,16 @@ import java.util.ArrayList;
|
||||
public class RangeSliderView extends View {
|
||||
|
||||
private static final String TAG = RangeSliderView.class.getName();
|
||||
private int trackTintColor;
|
||||
private int trackHighlightTintColor;
|
||||
private float trackHeight;
|
||||
private float thumbRadius;
|
||||
private float thumbOutlineSize;
|
||||
private float displayTextFontSize;
|
||||
private float displayTextBasicOffsetY;
|
||||
private int sliderPaddingLeft;
|
||||
private int sliderPaddingRight;
|
||||
|
||||
protected int trackTintColor;
|
||||
protected int trackHighlightTintColor;
|
||||
protected float trackHeight;
|
||||
protected float thumbRadius;
|
||||
protected float thumbOutlineSize;
|
||||
protected float displayTextFontSize;
|
||||
protected float displayTextBasicOffsetY;
|
||||
protected int sliderPaddingLeft;
|
||||
protected int sliderPaddingRight;
|
||||
|
||||
private ThumbLayer minValueThumb;
|
||||
private TextLayer minValueDisplayLabel;
|
||||
@@ -39,7 +40,7 @@ public class RangeSliderView extends View {
|
||||
|
||||
protected int minValue;
|
||||
protected int maxValue;
|
||||
protected int steps;
|
||||
protected float delta;
|
||||
|
||||
private float beginTrackOffsetX;
|
||||
|
||||
@@ -123,9 +124,10 @@ public class RangeSliderView extends View {
|
||||
for (int index = 1; index <= 100; index++) {
|
||||
values.add(index);
|
||||
}
|
||||
delta = 0;
|
||||
}
|
||||
|
||||
public void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
|
||||
void setOnValueChangedListener(OnValueChangedListener onValueChangedListener) {
|
||||
this.onValueChangedListener = onValueChangedListener;
|
||||
invalidate();
|
||||
}
|
||||
@@ -149,39 +151,49 @@ public class RangeSliderView extends View {
|
||||
float offsetY = getHeight() / 2;
|
||||
float minValueOffsetX = getPositionFromIndex(minValue);
|
||||
float maxValueOffsetX = getPositionFromIndex(maxValue);
|
||||
float displayLabelOffsetY = offsetY - thumbRadius - displayTextBasicOffsetY;
|
||||
float displayLabelOffsetAbove = offsetY - thumbRadius - displayTextBasicOffsetY;
|
||||
float displayLabelOffsetBelow = offsetY + thumbRadius + thumbOutlineSize + displayTextFontSize;
|
||||
|
||||
Log.d(TAG, "onDraw minValueOffsetX: " + minValueOffsetX + ", maxValueOffsetX: " + maxValueOffsetX);
|
||||
track.draw(canvas, getWidth(), minValueOffsetX, maxValueOffsetX, offsetY - trackHeight / 2);
|
||||
track.draw(canvas, getWidth(), minValueOffsetX, maxValueOffsetX, offsetY - trackHeight / 2, getDeltaInPixel());
|
||||
|
||||
minValueThumb.draw(canvas, minValueOffsetX, offsetY);
|
||||
maxValueThumb.draw(canvas, maxValueOffsetX, offsetY);
|
||||
|
||||
if (onValueChangedListener != null) {
|
||||
minValueDisplayLabel.draw(
|
||||
canvas,
|
||||
onValueChangedListener.parseMinValueDisplayText(minValue),
|
||||
minValueOffsetX,
|
||||
displayLabelOffsetY
|
||||
displayLabelOffsetBelow
|
||||
);
|
||||
} else {
|
||||
minValueDisplayLabel.draw(canvas, String.valueOf(minValue), minValueOffsetX, displayLabelOffsetY);
|
||||
}
|
||||
|
||||
maxValueThumb.draw(canvas, maxValueOffsetX, offsetY);
|
||||
if (onValueChangedListener != null) {
|
||||
maxValueDisplayLabel.draw(
|
||||
canvas,
|
||||
onValueChangedListener.parseMaxValueDisplayText(maxValue),
|
||||
maxValueOffsetX,
|
||||
displayLabelOffsetY
|
||||
displayLabelOffsetAbove
|
||||
);
|
||||
|
||||
|
||||
} else {
|
||||
maxValueDisplayLabel.draw(canvas, String.valueOf(maxValue), maxValueOffsetX, displayLabelOffsetY);
|
||||
minValueDisplayLabel.draw(canvas, String.valueOf(minValue), minValueOffsetX, displayLabelOffsetBelow);
|
||||
maxValueDisplayLabel.draw(canvas, String.valueOf(maxValue), maxValueOffsetX, displayLabelOffsetAbove);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) {
|
||||
if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
minValueThumb.isHighlight = false;
|
||||
maxValueThumb.isHighlight = false;
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.getAction() == MotionEvent.ACTION_UP && (minValueThumb.isHighlight || maxValueThumb.isHighlight)) {
|
||||
if (onValueChangedListener != null) {
|
||||
onValueChangedListener.onValueChanged(minValue, maxValue);
|
||||
}
|
||||
minValueThumb.isHighlight = false;
|
||||
maxValueThumb.isHighlight = false;
|
||||
invalidate();
|
||||
@@ -244,9 +256,6 @@ public class RangeSliderView extends View {
|
||||
}
|
||||
|
||||
if (minValueThumb.isHighlight || maxValueThumb.isHighlight) {
|
||||
if (onValueChangedListener != null) {
|
||||
onValueChangedListener.onValueChanged(minValue, maxValue);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
break;
|
||||
@@ -256,13 +265,24 @@ public class RangeSliderView extends View {
|
||||
}
|
||||
|
||||
protected int getIndexFromPosition(int offsetX) {
|
||||
int count = values.size();
|
||||
return ((offsetX - sliderPaddingLeft) * count / getSliderWidth());
|
||||
return ((offsetX - sliderPaddingLeft) * getCount() / getSliderWidth());
|
||||
}
|
||||
protected float getPositionFromIndex(int value) {
|
||||
int count = values.size();
|
||||
Log.d(TAG, "value: " + value +", position: " + (getSliderWidth() / count) * value + sliderPaddingLeft);
|
||||
return (getSliderWidth() / count) * value + sliderPaddingLeft;
|
||||
Log.d(TAG, "value: " + value +", position: " + (getSliderWidth() / getCount()) * value + sliderPaddingLeft);
|
||||
return (getSliderWidth() / getCount()) * value + sliderPaddingLeft;
|
||||
}
|
||||
|
||||
public float getDeltaInPixel() {
|
||||
// '* 2' is just an offset factor to increase the visibility
|
||||
return (getSliderWidth() / getCount()) * delta + (2 * thumbRadius + thumbOutlineSize);
|
||||
}
|
||||
|
||||
public float getDeltaInValues() {
|
||||
return delta;
|
||||
}
|
||||
|
||||
public int getCount() {
|
||||
return values.size();
|
||||
}
|
||||
|
||||
public int getSliderWidth() {
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.components.rangeslider;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@@ -15,12 +16,14 @@ import java.util.Locale;
|
||||
*/
|
||||
|
||||
public class TimeRangeSlider extends RangeSliderView implements RangeSliderView.OnValueChangedListener {
|
||||
// timeframe in seconds
|
||||
private static final int DEFAULT_TIMEFRAME_2D = 60 * 60 * 24 * 2;
|
||||
private static final int DEFAULT_STEPS = 60 * 10;
|
||||
int timeFrame;
|
||||
private static final int DEFAULT_TIMEFRAME_2D = 60 * 60 * 24 * 2; // 2d
|
||||
private static final float DEFAULT_DELTA = 1000*60*30; // 30 min
|
||||
int timeFrame; // timeframe in seconds
|
||||
|
||||
Locale locale;
|
||||
OnTimestampChangedListener listener;
|
||||
private TextLayer minRangeDisplayLabel;
|
||||
private TextLayer maxRangeDisplayLabel;
|
||||
|
||||
|
||||
public TimeRangeSlider(Context context) {
|
||||
@@ -42,6 +45,41 @@ public class TimeRangeSlider extends RangeSliderView implements RangeSliderView.
|
||||
|
||||
locale = DynamicLanguage.getSelectedLocale(context);
|
||||
super.setOnValueChangedListener(this);
|
||||
minRangeDisplayLabel = new TextLayer(displayTextFontSize, trackHighlightTintColor);
|
||||
maxRangeDisplayLabel = new TextLayer(displayTextFontSize, trackHighlightTintColor);
|
||||
delta = DEFAULT_DELTA / (timeFrame * 1000) * getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
float offsetY = getHeight() / 2;
|
||||
float minValueOffsetX = getPositionFromIndex(minValue);
|
||||
float maxValueOffsetX = getPositionFromIndex(maxValue);
|
||||
float displayLabelOffsetBelow = offsetY + thumbRadius + thumbOutlineSize + displayTextFontSize;
|
||||
|
||||
if (minValue == maxValue) {
|
||||
if (minValueOffsetX - getDeltaInPixel() >= sliderPaddingLeft
|
||||
) {
|
||||
minRangeDisplayLabel.draw(
|
||||
canvas,
|
||||
getDeltaInTime(getContext()),
|
||||
minValueOffsetX - getDeltaInPixel(),
|
||||
displayLabelOffsetBelow
|
||||
);
|
||||
}
|
||||
|
||||
if (maxValueOffsetX + getDeltaInPixel() <= (getWidth() - sliderPaddingRight)) {
|
||||
maxRangeDisplayLabel.draw(
|
||||
canvas,
|
||||
getDeltaInTime(getContext()),
|
||||
maxValueOffsetX + getDeltaInPixel(),
|
||||
displayLabelOffsetBelow
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnTimestampChangedListener {
|
||||
@@ -62,6 +100,9 @@ public class TimeRangeSlider extends RangeSliderView implements RangeSliderView.
|
||||
|
||||
@Override
|
||||
public String parseMinValueDisplayText(int minValue) {
|
||||
if (minValue == maxValue) {
|
||||
return "";
|
||||
}
|
||||
return getStringForValue(minValue);
|
||||
}
|
||||
|
||||
@@ -76,7 +117,11 @@ public class TimeRangeSlider extends RangeSliderView implements RangeSliderView.
|
||||
}
|
||||
|
||||
private long getTimestampForValue(int value) {
|
||||
return System.currentTimeMillis() - ((timeFrame / 100) * (100 - value) * 1000);
|
||||
return System.currentTimeMillis() - ((timeFrame / getCount()) * (getCount() - value) * 1000);
|
||||
}
|
||||
|
||||
public String getDeltaInTime(Context context) {
|
||||
return DateUtils.getFormattedTimespan(context, (int) (timeFrame * 1000 / getCount() * getDeltaInValues()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,9 +32,26 @@ class TrackLayer {
|
||||
this.paddingRight = paddingRight;
|
||||
}
|
||||
|
||||
void draw(Canvas canvas, int width, float offsetLeft, float offsetRight, float offsetY) {
|
||||
void draw(Canvas canvas, int width, float offsetLeft, float offsetRight, float offsetY, float delta) {
|
||||
draw(canvas, backgoundPaint, paddingLeft, width - paddingRight, offsetY);
|
||||
draw(canvas, centerPaint, offsetLeft, offsetRight, offsetY);
|
||||
if (offsetLeft == offsetRight) {
|
||||
float maxEndX = width - paddingRight;
|
||||
float minStartX = paddingLeft;
|
||||
float offsetDeltaLeft = offsetLeft - delta;
|
||||
float offsetDeltaRight = offsetRight + delta;
|
||||
|
||||
if (offsetLeft - delta < minStartX) {
|
||||
offsetDeltaLeft = minStartX;
|
||||
} else if (offsetRight + delta > maxEndX) {
|
||||
offsetDeltaRight = maxEndX;
|
||||
}
|
||||
|
||||
draw(canvas, centerPaint, offsetDeltaLeft, offsetDeltaRight, offsetY);
|
||||
}
|
||||
else {
|
||||
draw(canvas, centerPaint, offsetLeft, offsetRight, offsetY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void draw(Canvas canvas, Paint paint, float startX, float endX, float offsetY) {
|
||||
|
||||
@@ -175,4 +175,9 @@ public class DateUtils extends android.text.format.DateUtils {
|
||||
TimeUnit.MILLISECONDS.toMinutes(millis),
|
||||
TimeUnit.MILLISECONDS.toSeconds(millis-(TimeUnit.MILLISECONDS.toMinutes(millis)*60000)));
|
||||
}
|
||||
|
||||
public static String getFormattedTimespan(Context c, int timestamp) {
|
||||
int mins = timestamp / (1000 * 60);
|
||||
return c.getResources().getQuantityString(R.plurals.n_minutes, mins, mins);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user