new widgets
This commit is contained in:
parent
7aec0d0c3e
commit
0e2a85ae9e
31
res/layout-land/number_picker.xml
Normal file
31
res/layout-land/number_picker.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
~ For more information, please, contact se.solovyev@gmail.com
|
||||||
|
~ or visit http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<org.solovyev.android.view.widgets.NumberPickerButton android:id="@+id/increment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/timepicker_up_btn" />
|
||||||
|
|
||||||
|
<EditText android:id="@+id/timepicker_input"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:singleLine="true"
|
||||||
|
style="?android:attr/textAppearanceLargeInverse"
|
||||||
|
android:textColor="@android:color/primary_text_light"
|
||||||
|
android:textSize="30sp"
|
||||||
|
android:background="@drawable/timepicker_input" />
|
||||||
|
|
||||||
|
<org.solovyev.android.view.widgets.NumberPickerButton android:id="@+id/decrement"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/timepicker_down_btn" />
|
||||||
|
|
||||||
|
</merge>
|
@ -1,7 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<declare-styleable name="DragButton">
|
<declare-styleable name="DragButton">
|
||||||
<attr name="textUp" format="string" />
|
<attr name="textUp" format="string"/>
|
||||||
<attr name="textDown" format="string" />
|
<attr name="textDown" format="string"/>
|
||||||
|
</declare-styleable>
|
||||||
|
|
||||||
|
<declare-styleable name="NumberRangeSeekBar">
|
||||||
|
<attr name="min" format="string"/>
|
||||||
|
<attr name="max" format="string"/>
|
||||||
</declare-styleable>
|
</declare-styleable>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,15 +1,27 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android">
|
<PreferenceScreen xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:range="http://schemas.android.com/apk/res/org.solovyev.android.calculator">
|
||||||
<PreferenceCategory a:title="@string/c_prefs_drag_button_category">
|
<PreferenceCategory a:title="@string/c_prefs_drag_button_category">
|
||||||
|
|
||||||
<!-- <org.solovyev.android.view.prefs.SeekBarPreference a:key="duration"
|
<org.solovyev.android.view.prefs.SeekBarPreference a:key="duration"
|
||||||
a:title="Duration of something"
|
a:title="Duration of something"
|
||||||
a:summary="How long something will last"
|
a:summary="How long something will last"
|
||||||
a:dialogMessage="Something duration"
|
a:dialogMessage="Something duration"
|
||||||
a:defaultValue="5"
|
a:defaultValue="5"
|
||||||
a:text=" minutes"
|
a:text=" minutes"
|
||||||
a:max="60"/>-->
|
a:max="60"/>
|
||||||
|
|
||||||
|
|
||||||
|
<org.solovyev.android.view.prefs.IntegerRangeSeekBarPreference
|
||||||
|
a:key="touch.duration"
|
||||||
|
a:title="Duration of something"
|
||||||
|
a:summary="How long something will last"
|
||||||
|
a:dialogMessage="Something duration"
|
||||||
|
a:defaultValue="5"
|
||||||
|
a:text=" minutes"
|
||||||
|
range:min="10"
|
||||||
|
range:max="600"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
@ -21,6 +21,7 @@ import org.solovyev.android.view.widgets.*;
|
|||||||
import org.solovyev.common.collections.ManyValuedHashMap;
|
import org.solovyev.common.collections.ManyValuedHashMap;
|
||||||
import org.solovyev.common.collections.ManyValuedMap;
|
import org.solovyev.common.collections.ManyValuedMap;
|
||||||
import org.solovyev.common.utils.Interval;
|
import org.solovyev.common.utils.Interval;
|
||||||
|
import org.solovyev.common.utils.IntervalImpl;
|
||||||
import org.solovyev.common.utils.MathUtils;
|
import org.solovyev.common.utils.MathUtils;
|
||||||
import org.solovyev.common.utils.Point2d;
|
import org.solovyev.common.utils.Point2d;
|
||||||
|
|
||||||
@ -237,7 +238,7 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
final float max = preferences.getFloat(preferenceType.name() + "_" + dragDirection.name() + "_" + PREFERENCES_MAX, defaultMax);
|
final float max = preferences.getFloat(preferenceType.name() + "_" + dragDirection.name() + "_" + PREFERENCES_MAX, defaultMax);
|
||||||
|
|
||||||
if (min != DEFAULT_VALUE && max != DEFAULT_VALUE) {
|
if (min != DEFAULT_VALUE && max != DEFAULT_VALUE) {
|
||||||
final DragPreference directionPreference = new DragPreference(dragDirection, new Interval(min, max));
|
final DragPreference directionPreference = new DragPreference(dragDirection, new IntervalImpl<Float>(min, max));
|
||||||
|
|
||||||
Preference preference = result.getPreferencesMap().get(preferenceType);
|
Preference preference = result.getPreferencesMap().get(preferenceType);
|
||||||
if (preference == null) {
|
if (preference == null) {
|
||||||
@ -262,10 +263,10 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
private DragDirection direction;
|
private DragDirection direction;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Interval interval;
|
private Interval<Float> interval;
|
||||||
|
|
||||||
|
|
||||||
public DragPreference(@NotNull DragDirection direction, @NotNull Interval interval) {
|
public DragPreference(@NotNull DragDirection direction, @NotNull Interval<Float> interval) {
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
}
|
}
|
||||||
@ -280,11 +281,11 @@ public class DragButtonCalibrationActivity extends Activity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Interval getInterval() {
|
public Interval<Float> getInterval() {
|
||||||
return interval;
|
return interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInterval(@NotNull Interval interval) {
|
public void setInterval(@NotNull Interval<Float> interval) {
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ import android.content.Context;
|
|||||||
import android.preference.DialogPreference;
|
import android.preference.DialogPreference;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -20,19 +20,19 @@ public class AbstractDialogPreference extends DialogPreference {
|
|||||||
protected static final String androidns = "http://schemas.android.com/apk/res/android";
|
protected static final String androidns = "http://schemas.android.com/apk/res/android";
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected TextView splashText, valueText;
|
protected TextView valueTextView;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected final Context context;
|
protected final Context context;
|
||||||
|
|
||||||
protected String dialogMessage, suffix;
|
@Nullable
|
||||||
|
protected String dialogMessage;
|
||||||
|
|
||||||
public AbstractDialogPreference(Context context, AttributeSet attrs) {
|
public AbstractDialogPreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
dialogMessage = attrs.getAttributeValue(androidns, "dialogMessage");
|
dialogMessage = attrs.getAttributeValue(androidns, "dialogMessage");
|
||||||
suffix = attrs.getAttributeValue(androidns, "text");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -42,18 +42,19 @@ public class AbstractDialogPreference extends DialogPreference {
|
|||||||
layout.setOrientation(LinearLayout.VERTICAL);
|
layout.setOrientation(LinearLayout.VERTICAL);
|
||||||
layout.setPadding(6, 6, 6, 6);
|
layout.setPadding(6, 6, 6, 6);
|
||||||
|
|
||||||
splashText = new TextView(context);
|
final TextView splashText = new TextView(context);
|
||||||
if (dialogMessage != null)
|
if (dialogMessage != null) {
|
||||||
splashText.setText(dialogMessage);
|
splashText.setText(dialogMessage);
|
||||||
|
}
|
||||||
layout.addView(splashText);
|
layout.addView(splashText);
|
||||||
|
|
||||||
valueText = new TextView(context);
|
valueTextView = new TextView(context);
|
||||||
valueText.setGravity(Gravity.CENTER_HORIZONTAL);
|
valueTextView.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||||
valueText.setTextSize(32);
|
valueTextView.setTextSize(32);
|
||||||
params = new LinearLayout.LayoutParams(
|
params = new LinearLayout.LayoutParams(
|
||||||
LinearLayout.LayoutParams.FILL_PARENT,
|
LinearLayout.LayoutParams.FILL_PARENT,
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||||
layout.addView(valueText, params);
|
layout.addView(valueTextView, params);
|
||||||
|
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.view.prefs;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.common.utils.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/19/11
|
||||||
|
* Time: 10:04 PM
|
||||||
|
*/
|
||||||
|
public class IntegerRangeSeekBarPreference extends RangeSeekBarPreference<Integer> {
|
||||||
|
|
||||||
|
public IntegerRangeSeekBarPreference(@NotNull Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
Converter<String, Integer> getConverter() {
|
||||||
|
return new Converter<String, Integer>() {
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Integer convert(@NotNull String value) {
|
||||||
|
return Integer.valueOf(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
package org.solovyev.android.view.prefs;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.solovyev.android.view.widgets.AbstractRangeSeekBar;
|
||||||
|
import org.solovyev.android.view.widgets.NumberRangeSeekBar;
|
||||||
|
import org.solovyev.common.utils.CollectionsUtils;
|
||||||
|
import org.solovyev.common.utils.Converter;
|
||||||
|
import org.solovyev.common.utils.StringMapper;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/19/11
|
||||||
|
* Time: 12:27 PM
|
||||||
|
*/
|
||||||
|
public abstract class RangeSeekBarPreference<T extends Number> extends AbstractDialogPreference implements AbstractRangeSeekBar.OnRangeSeekBarChangeListener<T> {
|
||||||
|
|
||||||
|
public final static String localNameSpace = "http://schemas.android.com/apk/res/org.solovyev.android.calculator";
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private AbstractRangeSeekBar<T> rangeSeekBar;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private T min;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private T max;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private T selectedMin;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private T selectedMax;
|
||||||
|
|
||||||
|
|
||||||
|
public RangeSeekBarPreference(@NotNull Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
|
||||||
|
|
||||||
|
final Converter<String, T> c = getConverter();
|
||||||
|
|
||||||
|
String minString = attrs.getAttributeValue(localNameSpace, "min");
|
||||||
|
min = c.convert(minString == null ? "0" : minString);
|
||||||
|
String maxString = attrs.getAttributeValue(localNameSpace, "max");
|
||||||
|
max = c.convert(maxString == null ? "100" : maxString);
|
||||||
|
|
||||||
|
|
||||||
|
this.rangeSeekBar = new NumberRangeSeekBar<T>(min, max, context);
|
||||||
|
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMin(@NotNull String min) {
|
||||||
|
this.min = getConverter().convert(min);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMax(@NotNull String max) {
|
||||||
|
this.max = getConverter().convert(max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
abstract Converter<String, T> getConverter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected LinearLayout onCreateDialogView() {
|
||||||
|
final LinearLayout result = super.onCreateDialogView();
|
||||||
|
|
||||||
|
this.rangeSeekBar = new NumberRangeSeekBar<T>(min, max, context);
|
||||||
|
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
||||||
|
initRangeSeekBar();
|
||||||
|
|
||||||
|
result.addView(rangeSeekBar);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindDialogView(View v) {
|
||||||
|
super.onBindDialogView(v);
|
||||||
|
initRangeSeekBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initRangeSeekBar() {
|
||||||
|
rangeSeekBar.setSelectedMinValue(selectedMin);
|
||||||
|
rangeSeekBar.setSelectedMaxValue(selectedMax);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSetInitialValue(boolean restore, Object defaultValue) {
|
||||||
|
super.onSetInitialValue(restore, defaultValue);
|
||||||
|
|
||||||
|
final List<String> values;
|
||||||
|
if (restore) {
|
||||||
|
values = CollectionsUtils.split(getPersistedString("0;100"), ";", new StringMapper());
|
||||||
|
} else {
|
||||||
|
values = CollectionsUtils.split(String.valueOf(defaultValue), ";", new StringMapper());
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedMin = getConverter().convert(values.get(0));
|
||||||
|
selectedMax = getConverter().convert(values.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rangeSeekBarValuesChanged(T minValue, T maxValue) {
|
||||||
|
final String value = CollectionsUtils.formatValue(Arrays.asList(String.valueOf(minValue), String.valueOf(maxValue)), ";", new StringMapper());
|
||||||
|
if (shouldPersist()) {
|
||||||
|
persistString(value);
|
||||||
|
}
|
||||||
|
callChangeListener(value);
|
||||||
|
}
|
||||||
|
}
|
@ -1,45 +0,0 @@
|
|||||||
package org.solovyev.android.view.prefs;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.solovyev.android.view.widgets.AbstractRangeSeekBar;
|
|
||||||
import org.solovyev.android.view.widgets.NumberRangeSeekBar;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User: serso
|
|
||||||
* Date: 9/19/11
|
|
||||||
* Time: 12:27 PM
|
|
||||||
*/
|
|
||||||
public abstract class RangeSeekPreference<T extends Number> extends AbstractDialogPreference implements AbstractRangeSeekBar.OnRangeSeekBarChangeListener<T> {
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final AbstractRangeSeekBar<T> rangeSeekBar;
|
|
||||||
|
|
||||||
public RangeSeekPreference(@NotNull Context context, AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
this.rangeSeekBar = new NumberRangeSeekBar<T>(getMinValue(), getMaxValue(), context);
|
|
||||||
rangeSeekBar.setOnRangeSeekBarChangeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
abstract T getMinValue();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
abstract T getMaxValue();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected LinearLayout onCreateDialogView() {
|
|
||||||
final LinearLayout result = super.onCreateDialogView();
|
|
||||||
|
|
||||||
result.addView(rangeSeekBar);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void rangeSeekBarValuesChanged(T minValue, T maxValue) {
|
|
||||||
//To change body of implemented methods use File | Settings | File Templates.
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,15 +6,13 @@
|
|||||||
|
|
||||||
package org.solovyev.android.view.prefs;
|
package org.solovyev.android.view.prefs;
|
||||||
|
|
||||||
import android.preference.DialogPreference;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|
||||||
/* The following code was written by Matthew Wiggins
|
/* The following code was written by Matthew Wiggins
|
||||||
@ -30,17 +28,20 @@ public class SeekBarPreference extends AbstractDialogPreference implements SeekB
|
|||||||
|
|
||||||
private int defaultValue, max, value = 0;
|
private int defaultValue, max, value = 0;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
protected String valueText;
|
||||||
|
|
||||||
public SeekBarPreference(Context context, AttributeSet attrs) {
|
public SeekBarPreference(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
|
||||||
defaultValue = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
|
defaultValue = attrs.getAttributeIntValue(androidns, "defaultValue", 0);
|
||||||
max = attrs.getAttributeIntValue(androidns, "max", 100);
|
max = attrs.getAttributeIntValue(androidns, "max", 100);
|
||||||
|
valueText = attrs.getAttributeValue(androidns, "text");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected LinearLayout onCreateDialogView() {
|
protected LinearLayout onCreateDialogView() {
|
||||||
final LinearLayout layout = onCreateDialogView();
|
final LinearLayout layout = super.onCreateDialogView();
|
||||||
|
|
||||||
seekBar = new SeekBar(context);
|
seekBar = new SeekBar(context);
|
||||||
seekBar.setOnSeekBarChangeListener(this);
|
seekBar.setOnSeekBarChangeListener(this);
|
||||||
@ -49,17 +50,20 @@ public class SeekBarPreference extends AbstractDialogPreference implements SeekB
|
|||||||
if (shouldPersist())
|
if (shouldPersist())
|
||||||
value = getPersistedInt(defaultValue);
|
value = getPersistedInt(defaultValue);
|
||||||
|
|
||||||
seekBar.setMax(max);
|
initSeekBar();
|
||||||
seekBar.setProgress(value);
|
|
||||||
|
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initSeekBar() {
|
||||||
|
seekBar.setMax(max);
|
||||||
|
seekBar.setProgress(value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onBindDialogView(View v) {
|
protected void onBindDialogView(View v) {
|
||||||
super.onBindDialogView(v);
|
super.onBindDialogView(v);
|
||||||
seekBar.setMax(max);
|
initSeekBar();
|
||||||
seekBar.setProgress(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -73,7 +77,7 @@ public class SeekBarPreference extends AbstractDialogPreference implements SeekB
|
|||||||
|
|
||||||
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
|
public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) {
|
||||||
String t = String.valueOf(value);
|
String t = String.valueOf(value);
|
||||||
valueText.setText(suffix == null ? t : t.concat(suffix));
|
valueTextView.setText(valueText == null ? t : t.concat(valueText));
|
||||||
if (shouldPersist())
|
if (shouldPersist())
|
||||||
persistInt(value);
|
persistInt(value);
|
||||||
callChangeListener(new Integer(value));
|
callChangeListener(new Integer(value));
|
||||||
|
@ -14,6 +14,7 @@ import android.widget.ImageView;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.common.math.LinearNormalizer;
|
||||||
import org.solovyev.common.utils.Converter;
|
import org.solovyev.common.utils.Converter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -53,7 +54,8 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final T minValue, maxValue;
|
private final T minValue, maxValue;
|
||||||
|
|
||||||
private final double dMinValue, dMaxValue;
|
@NotNull
|
||||||
|
private final LinearNormalizer normalizer;
|
||||||
|
|
||||||
private double normalizedMinValue = 0d;
|
private double normalizedMinValue = 0d;
|
||||||
|
|
||||||
@ -84,8 +86,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
this.toDoubleConverter = getToDoubleConverter();
|
this.toDoubleConverter = getToDoubleConverter();
|
||||||
this.toTConverter = getToTConverter();
|
this.toTConverter = getToTConverter();
|
||||||
|
|
||||||
dMinValue = toDoubleConverter.convert(minValue);
|
normalizer = new LinearNormalizer(toDoubleConverter.convert(minValue), toDoubleConverter.convert(maxValue));
|
||||||
dMaxValue = toDoubleConverter.convert(maxValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -141,14 +142,9 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
*
|
*
|
||||||
* @param value The Number value to set the minimum value to. Will be clamped to given absolute minimum/maximum range.
|
* @param value The Number value to set the minimum value to. Will be clamped to given absolute minimum/maximum range.
|
||||||
*/
|
*/
|
||||||
public void setSelectedMinValue(T value) {
|
public void setSelectedMinValue(@NotNull T value) {
|
||||||
// in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
|
|
||||||
if (0 == (dMaxValue - dMinValue)) {
|
|
||||||
setNormalizedMinValue(0d);
|
|
||||||
} else {
|
|
||||||
setNormalizedMinValue(normalizeValue(value));
|
setNormalizedMinValue(normalizeValue(value));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currently selected max value.
|
* Returns the currently selected max value.
|
||||||
@ -164,14 +160,9 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
*
|
*
|
||||||
* @param value The Number value to set the maximum value to. Will be clamped to given absolute minimum/maximum range.
|
* @param value The Number value to set the maximum value to. Will be clamped to given absolute minimum/maximum range.
|
||||||
*/
|
*/
|
||||||
public void setSelectedMaxValue(T value) {
|
public void setSelectedMaxValue(@NotNull T value) {
|
||||||
// in case absoluteMinValue == absoluteMaxValue, avoid division by zero when normalizing.
|
|
||||||
if (0 == (dMaxValue - dMinValue)) {
|
|
||||||
setNormalizedMaxValue(1d);
|
|
||||||
} else {
|
|
||||||
setNormalizedMaxValue(normalizeValue(value));
|
setNormalizedMaxValue(normalizeValue(value));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers given listener callback to notify about changed selected values.
|
* Registers given listener callback to notify about changed selected values.
|
||||||
@ -330,7 +321,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private T denormalizeValue(double normalized) {
|
private T denormalizeValue(double normalized) {
|
||||||
return toTConverter.convert(dMinValue + normalized * (dMaxValue - dMinValue));
|
return toTConverter.convert(normalizer.denormalize(normalized));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -340,8 +331,7 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
* @return The normalized double.
|
* @return The normalized double.
|
||||||
*/
|
*/
|
||||||
private double normalizeValue(T value) {
|
private double normalizeValue(T value) {
|
||||||
assert 0 != dMaxValue - dMinValue;
|
return normalizer.normalize(toDoubleConverter.convert(value));
|
||||||
return (toDoubleConverter.convert(value) - dMinValue) / (dMaxValue - dMinValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -390,27 +380,4 @@ public abstract class AbstractRangeSeekBar<T> extends ImageView {
|
|||||||
MIN, MAX
|
MIN, MAX
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LinearNormalizer {
|
|
||||||
|
|
||||||
private final double minValue;
|
|
||||||
private final double maxValue;
|
|
||||||
|
|
||||||
private LinearNormalizer(double minValue, double maxValue) {
|
|
||||||
this.minValue = minValue;
|
|
||||||
this.maxValue = maxValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double normalize(double value){
|
|
||||||
if ((dMaxValue - dMinValue) != 0d) {
|
|
||||||
return (value - dMinValue) / (dMaxValue - dMinValue);
|
|
||||||
} else {
|
|
||||||
return 1d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double denormalize(double value){
|
|
||||||
return dMinValue + value * (dMaxValue - dMinValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,9 @@ package org.solovyev.android.view.widgets;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.solovyev.common.utils.Converter;
|
import org.solovyev.common.utils.Converter;
|
||||||
import org.solovyev.common.utils.Mapper;
|
|
||||||
import org.solovyev.common.utils.NumberValuer;
|
import org.solovyev.common.utils.NumberValuer;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 9/19/11
|
* Date: 9/19/11
|
||||||
@ -38,6 +34,7 @@ public class NumberRangeSeekBar<T extends Number> extends AbstractRangeSeekBar<T
|
|||||||
@Override
|
@Override
|
||||||
protected Converter<Double, T> getToTConverter() {
|
protected Converter<Double, T> getToTConverter() {
|
||||||
return new Converter<Double, T>() {
|
return new Converter<Double, T>() {
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public T convert(@NotNull Double aDouble) {
|
public T convert(@NotNull Double aDouble) {
|
||||||
return (T) numberType.toNumber(aDouble);
|
return (T) numberType.toNumber(aDouble);
|
||||||
@ -52,60 +49,4 @@ public class NumberRangeSeekBar<T extends Number> extends AbstractRangeSeekBar<T
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility enumeration used to convert between Numbers and doubles.
|
|
||||||
*
|
|
||||||
* @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
|
|
||||||
*/
|
|
||||||
private static enum NumberType {
|
|
||||||
|
|
||||||
LONG(Long.class),
|
|
||||||
DOUBLE(Double.class),
|
|
||||||
INTEGER(Integer.class),
|
|
||||||
FLOAT(Float.class),
|
|
||||||
SHORT(Short.class),
|
|
||||||
BYTE(Byte.class),
|
|
||||||
BIG_DECIMAL(BigDecimal.class);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final Class underlyingClass;
|
|
||||||
|
|
||||||
private NumberType(@NotNull Class underlyingClass) {
|
|
||||||
this.underlyingClass = underlyingClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static <E extends Number> NumberType fromNumber(E value) throws IllegalArgumentException {
|
|
||||||
|
|
||||||
for (NumberType numberType : NumberType.values()) {
|
|
||||||
if (numberType.underlyingClass.isInstance(value)) {
|
|
||||||
return numberType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Number class '" + value.getClass().getName() + "' is not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Number> T toNumber(double value) {
|
|
||||||
|
|
||||||
switch (this) {
|
|
||||||
case LONG:
|
|
||||||
return (T)new Long((long) value);
|
|
||||||
case DOUBLE:
|
|
||||||
return (T)new Double(value);
|
|
||||||
case INTEGER:
|
|
||||||
return (T)new Integer((int) value);
|
|
||||||
case FLOAT:
|
|
||||||
return (T)new Float((float) value);
|
|
||||||
case SHORT:
|
|
||||||
return (T)new Short((short) value);
|
|
||||||
case BYTE:
|
|
||||||
return (T)new Byte((byte) value);
|
|
||||||
case BIG_DECIMAL:
|
|
||||||
return (T)new BigDecimal(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new InstantiationError("can't convert " + this + " to a Number object");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.android.view.widgets;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility enumeration used to convert between Numbers and doubles.
|
||||||
|
*
|
||||||
|
* @author Stephan Tittel (stephan.tittel@kom.tu-darmstadt.de)
|
||||||
|
*/
|
||||||
|
enum NumberType {
|
||||||
|
|
||||||
|
LONG(Long.class),
|
||||||
|
DOUBLE(Double.class),
|
||||||
|
INTEGER(Integer.class),
|
||||||
|
FLOAT(Float.class),
|
||||||
|
SHORT(Short.class),
|
||||||
|
BYTE(Byte.class),
|
||||||
|
BIG_DECIMAL(BigDecimal.class);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Class underlyingClass;
|
||||||
|
|
||||||
|
NumberType(@NotNull Class underlyingClass) {
|
||||||
|
this.underlyingClass = underlyingClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static <E extends Number> NumberType fromNumber(E value) throws IllegalArgumentException {
|
||||||
|
|
||||||
|
for (NumberType numberType : NumberType.values()) {
|
||||||
|
if (numberType.underlyingClass.isInstance(value)) {
|
||||||
|
return numberType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Number class '" + value.getClass().getName() + "' is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Number> T toNumber(double value) {
|
||||||
|
|
||||||
|
switch (this) {
|
||||||
|
case LONG:
|
||||||
|
return (T)new Long((long) value);
|
||||||
|
case DOUBLE:
|
||||||
|
return (T)new Double(value);
|
||||||
|
case INTEGER:
|
||||||
|
return (T)new Integer((int) value);
|
||||||
|
case FLOAT:
|
||||||
|
return (T)new Float((float) value);
|
||||||
|
case SHORT:
|
||||||
|
return (T)new Short((short) value);
|
||||||
|
case BYTE:
|
||||||
|
return (T)new Byte((byte) value);
|
||||||
|
case BIG_DECIMAL:
|
||||||
|
return (T)new BigDecimal(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InstantiationError("can't convert " + this + " to a Number object");
|
||||||
|
}
|
||||||
|
}
|
@ -85,8 +85,8 @@ public class SimpleOnDragListener implements OnDragListener, DragPreferencesChan
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInInterval(@NotNull Interval interval, float value) {
|
private boolean isInInterval(@NotNull Interval<Float> interval, float value) {
|
||||||
return interval.getStart() - MathUtils.MIN_AMOUNT <= value && value <= interval.getEnd() + MathUtils.MIN_AMOUNT;
|
return interval.getLeftBorder() - MathUtils.MIN_AMOUNT <= value && value <= interval.getRightBorder() + MathUtils.MIN_AMOUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
36
src/main/java/org/solovyev/common/math/LinearNormalizer.java
Normal file
36
src/main/java/org/solovyev/common/math/LinearNormalizer.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
|
* or visit http://se.solovyev.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.solovyev.common.math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/19/11
|
||||||
|
* Time: 9:31 PM
|
||||||
|
*/
|
||||||
|
public class LinearNormalizer {
|
||||||
|
|
||||||
|
private final double min;
|
||||||
|
private final double max;
|
||||||
|
|
||||||
|
public LinearNormalizer(double min, double max) {
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double normalize(double value){
|
||||||
|
if ((max - min) != 0d) {
|
||||||
|
return (value - min) / (max - min);
|
||||||
|
} else {
|
||||||
|
return 1d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double denormalize(double value){
|
||||||
|
return min + value * (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user