Question

I have been steaming over this one a few days now. I try to have a selector for a big range of numbers... within int-limits. You ought to hold down a button and the value should change slow and the longer you press the more rapid it changes. You all know that kind of button, don't you?! :D It has to be precise, yet fast to enter the number. I use a OnTouchListener. The event allows to .getDownTime().

I tried a lot, but always only got it to skip numbers (not really but too fast to use) or not repeatingly increase the value while holding down the button. If run without changes it is pretty fast, but it would be nice, if it starts to make 10 100 or 1000-jumps if it is held down long enough.

I prepared a little SSCCE looking like this:

Screenshot of 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;
}
}

For devices with low resolution one might have to decrease the text-sizes.

Thanks in advance!

Was it helpful?

Solution

Have a look at the NumberPicker source code. This is a widget from the SDK that does exactly what you are describing, except without the acceleration. Using post calls to a Handler as is done here is the best way to handle the timing events. The only addition you would need to make to this class is to vary the mSpeed value in the post callbacks (and perhaps the increment) based on the down time.

HTH.

OTHER TIPS

The way I might try and tackle this is as follows:

Pressing + or - will start a Thread. The thread updates the number at a set interval by an offset value, if the number has changed more than 20 times then decrease the interval so the number updates faster, if the number is still changing a lot then the offset value would be made larger to skip numbers. Remember all this is happening in a thread.

When the user lifts their finger the thread is killed and the offset, interval is reset.

Use the value of getDownTime() to compute how big the counter increment should be.

First, design the response curve you would like. (That is, determine a function that defines how the value should change as a function of touch time and, perhaps, starting value. It does not — should not, from the way you describe it — be a straight line function.)

Then just make your increment follow the curve. It will probably help to store the button value and down time at the last event.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top