Sunday, 21 September 2014

Android: a ListView for which scrolling can be disabled

Given a parent View which contains other child Views, the way touch generally works in Android is that the parent View will only see a touch event if it's not consumed by one of its child Views, i.e. the child Views have first say on whether they want to act on a touch event. This is true in most circumstances but there are some exceptions. Notably, it is possible for a parent View to intercept touch events so that it processes them instead of the child Views. An example of this is the ListView class: when the user moves his/her finger up or down in the ListView, the touch events are intercepted by the ListView so that it scrolls vertically and the child Views do not see the touch events. If you'd like to stop the ListView stealing the touch events, here's how: instantiate the custom ListView class below and set scrollEnabled to false:

public class DisableScrollListView extends ListView {

  /**
   * Flag which determines whether vertical scrolling is enabled in this {@link ListView}.
   */
  private boolean scrollEnabled = true;

  public DisableScrollListView(Context context) {
    super(context);
  }

  public DisableScrollListView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public DisableScrollListView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (!scrollEnabled) {
      return false;
    } else {
      return super.onInterceptTouchEvent(ev);
    }
  }

  /**
   * Sets the value of {@link #scrollEnabled}.
   * 
   * @param scrollEnabled
   */
  public void setScrollEnabled(boolean scrollEnabled) {
    this.scrollEnabled = scrollEnabled;
  }
}

Android: methods for converting pixels to scaled pixels, and vice versa

Here's a couple of methods for converting from pixels to scaled pixels (for use in TextViews to set the size of text), and vice versa.

If you need to convert between pixels and density-independent pixels, then you need these methods instead:
http://adilatwork.blogspot.co.uk/2011/09/android-methods-for-converting-density.html
/**  
  * @param scaledPixels  
  * @return the number of pixels which scaledPixels corresponds to  
  * on the device.  
  */  
 private float convertSpToPx(float scaledPixels) {  
  DisplayMetrics dm = getContext().getResources().getDisplayMetrics();  
  return scaledPixels * dm.scaledDensity;  
 }  
   
 /**  
  * @param pixels  
  * @return the number of scaled pixels which pixels corresponds to  
  * on the device.  
  */  
 private float convertPxToSp(float pixels) {  
  DisplayMetrics dm = getContext().getResources().getDisplayMetrics();  
  return pixels / dm.scaledDensity;  
 }