Меняйте значение плавно увеличивая скорость, удерживая нажатой кнопку

Я парился над этим несколько дней. Я пытаюсь иметь селектор для большого диапазона чисел... в пределах int-limits. Вы должны удерживать кнопку, и значение должно меняться медленно, и чем дольше вы нажимаете, тем быстрее оно изменяется. Вы все знаете такую ​​кнопку, не так ли?! :D Ввод числа должен быть точным, но быстрым. Я использую OnTouchListener. Событие позволяет .getDownTime().

Я много пробовал, но всегда получалось только пропускать числа (не совсем, но слишком быстро для использования) или не многократно увеличивать значение, удерживая кнопку. Если запустить без изменений, то довольно быстро, но было бы неплохо, если бы он начал делать 10 100 или 1000-прыжков, если его удерживать достаточно долго.

Я подготовил небольшой SSCCE, выглядящий так:

Скриншот SSCCE

public class ValueChangerSSCCE extends Activity implements OnTouchListener {

Button plusButton;
TextView valueView;
Button minusButton;
int value;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    LinearLayout layout = new LinearLayout(this);
    layout.setOrientation(LinearLayout.VERTICAL);

    plusButton = new Button(this);
    plusButton.setText("+");
    plusButton.setTextSize(120f);
    plusButton.setOnTouchListener(this);
    layout.addView(plusButton);

    valueView = new TextView(this);
    valueView.setGravity(Gravity.CENTER_HORIZONTAL);
    valueView.setTextColor(Color.WHITE);
    valueView.setText(value + "");
    valueView.setTextSize(120f);
    layout.addView(valueView);

    minusButton = new Button(this);
    minusButton.setText("-");
    minusButton.setTextSize(120f);
    minusButton.setOnTouchListener(this);
    layout.addView(minusButton);

    setContentView(layout);
}

/* 
 * Called when a button is pressed
 */
@Override
public boolean onTouch(View v, MotionEvent event) {

    if (v == plusButton) {
        value++;
    } else if (v == minusButton) {
        value--;
    }
    valueView.setText(value + "");

    return false;
}
}

Для устройств с низким разрешением может потребоваться уменьшить размер текста.

Заранее спасибо!


person Omphaloskopie    schedule 23.11.2011    source источник


Ответы (3)


Просмотрите исходный код NumberPicker. Это виджет из SDK, который делает именно то, что вы описываете, только без ускорения. Использование почтовых вызовов Handler, как это сделано здесь, является лучшим способом обработки событий синхронизации. Единственное дополнение, которое вам нужно будет внести в этот класс, — это изменить значение mSpeed в обратных вызовах post (и, возможно, приращение) в зависимости от времени простоя.

ХТН.

person devunwired    schedule 23.11.2011
comment
+1 Спасибо .. Я проверял, ускоряется ли TimePicker из моего будильника, но это не так, поэтому я пропустил ту часть, которая думала, что я могу его изменить. Если я не смогу выполнить ни одно из предложений Teds и C0deAttacks, я попробую это... - person Omphaloskopie; 23.11.2011
comment
Хотя мне действительно нравились все предложения, это помогло мне больше всего, потому что я застрял в том, как правильно использовать Threading. Источник раскрыл мне свою тайну. Пожалуйста, извините меня за позднее принятие, я был занят личными делами. - person Omphaloskopie; 15.12.2011

Я мог бы попытаться решить эту проблему следующим образом:

Нажатие + или - запустит поток. Поток обновляет число с заданным интервалом на значение смещения, если число изменилось более 20 раз, уменьшите интервал, чтобы число обновлялось быстрее, если число все еще сильно меняется, тогда значение смещения будет увеличено до пропускать номера. Помните, что все это происходит в потоке.

Когда пользователь поднимает палец, поток уничтожается, а интервал смещения сбрасывается.

person C0deAttack    schedule 23.11.2011
comment
+1 Спасибо за быстрый ответ... Завтра попробую. (уже пора спать :D) - person Omphaloskopie; 23.11.2011
comment
Просто следите за тем, чтобы вы не пытались обновить представление из потока, отличного от пользовательского интерфейса. Вероятно, лучше всего прочитать о многопоточности в Android, если вы хотите попробовать мою идею. - person C0deAttack; 23.11.2011
comment
Спасибо за подсказку. Мой пример кода - это всего лишь пример... фактический код использует шаблон наблюдателя, так что представление уведомляется об изменении модели. - person Omphaloskopie; 23.11.2011

Используйте значение getDownTime(), чтобы вычислить, насколько большим должно быть приращение счетчика.

Во-первых, спроектируйте кривую отклика, которую вы хотите. (То есть определите функцию, которая определяет, как значение должно изменяться в зависимости от времени касания и, возможно, начального значения. Это не должно быть, судя по тому, как вы описываете, это функция прямой линии.)

Затем просто сделайте так, чтобы ваш прирост следовал за кривой. Вероятно, это поможет сохранить значение кнопки и время простоя на последнем событии.

person Ted Hopp    schedule 23.11.2011
comment
+1 О.. какая красивая ‹3... завтра попробую... до сих пор я только пытался пропускать циклы на какой-то странной функции, когда getDownTime < 10000 / cycles но это, похоже, ничего не делало в все... - person Omphaloskopie; 23.11.2011