Friday, May 28, 2010

Wheel UI contol: Scrolling

The main feature of the Wheel control is a scrolling (rotation). And I'd like to describe a simple wheel scrolling, without animation.

The wheel control should be scrolled on touch motion event. So, it needs to override onTouchEvent() method to rotate the wheel. Each time it needs to update the wheel according to motion distance that can be calculated as the difference between the last and current Y motion position.
In our case we will update the wheel control by setting the current number. If motion distance is less than zero (the movement from bottom to top) we have to increment it, and decrement otherwise. Note that we have to skip that if the movement is so small (is less than one item height).
@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        lastYTouch = event.getY();
        break;

    case MotionEvent.ACTION_MOVE:
        float delta = event.getY() - lastYTouch;
        int count = (int) (visibleItems * delta / getHeight());
        int pos = currentValue - count;
        pos = Math.max(pos, minValue);
        pos = Math.min(pos, maxValue);
        if (pos != currentValue) {
            lastYTouch = event.getY();
            setValue(pos);
        }
        break;
    case MotionEvent.ACTION_UP:
        break;
    }
    return true;
}

/**
 * Sets current value
 * 
 * @param value the value to set
 */
public void setValue(int value) {
    if (value != currentValue && value >= minValue && value <= maxValue) {
        itemsLayout = null;
        valueLayout = null;
        currentValue = value;
        invalidate();
    }
}

Note that it is just a simple scrolling implementation, and it is not as good as expected. But there is nothing impossible, and I think it can be extended to have the behavior like original iPhone widget.

See also
    Introduction to the Wheel control
    The Wheel control layouts
    The Wheel control backgrounds
    Ideas for the future

5 comments:

  1. This is great. I added an isTouchEnabled property to WheelScroller so I can ignore touch events. This is for apps that want to scroll only from external events (button press, accelerometer "shake", etc). To expose this to the containing Activity, I added setTouchEnabled methods to WheelView and WheelScroller. Activity calls WheelView.setTouchEnabled(false) which passes this value to WheelScroller's method which sets isTouchEnabled. onTouchEvent simply ignores the touch events (early return) if this is false. Default to true, of course.

    ReplyDelete
  2. Hi Rich,

    You can use also View.isEnabled()/View.setEnabled() for wheel view and ignore touch events if view is disabled.

    ReplyDelete
  3. Maidul said...

    Hi kankan How can i increase the size of month value.Suppose You set month view 15 dip.I want increase 25 dip.Can you please help me

    ReplyDelete
  4. Hi
    At first thanks for your valuable code.I use your code.But I have use year month and date in a same wheel .I set a image for a date .when change date the image will change.show image from database for the date .when date change the image also change.How can is this possible.Can you give some example or Hint.

    Thanks and Regards,
    Md Maidul Islam

    ReplyDelete