This plugin was just what I needed. Although I needed it for paging.

Here is my modified version.



Usage:

Code:
plugins: [new mobile.plugins.ListPullPager({
		previousFn: function(cb,scope){
		    mobile.commissions.store.previousPage();
		    cb.call(this);
		},
		nextFn: function(cb,scope){
		    mobile.commissions.store.nextPage(); 
		    cb.call(this);
		}
	    })]
Plugin:

Code:
Ext.apply(Ext.anims, {
    rotate: new Ext.Anim({
        autoClear: false,
        out: false,
        before: function(el) {
            var d = '';
            if (this.dir == 'ccw'){
              d = '-';
            }

            this.from = {
                '-webkit-transform': 'rotate('+d+''+this.fromAngle+'deg)'
            };

            this.to = {
                '-webkit-transform': 'rotate('+d+''+this.toAngle+'deg)'
            };
                        
        }
    })
});  

Ext.ns('mobile.plugins');

mobile.plugins.ListPullPager = Ext.extend(Ext.util.Observable, {
  langPullPrevious: 'Pull down to load previous...',
  langReleasePrevious: 'Release to load previous...',
  langPullNext: 'Pull up to load next...',
  langReleaseNext: 'Release to load next...',
  langLoading: 'Loading...',
 
  loading: false,
  //define the functions to call for loading.
  previousFn: undefined,
  nextFn: undefined,
  // private
  init: function(cmp){
    this.cmp = cmp;
    this.lastUpdate = new Date();
    cmp.loadingText = undefined;
    cmp.on('render', this.initPullHandler, this);
    if (!this.previousFn || !this.nextFn){
      cmp.getStore().on('load', this.reloadComplete, this);
    }
  },
  // private
  initPullHandler: function(){
    //Previous
    this.previousTpl = new Ext.XTemplate(
      '<div class="pullprevious" style="height: {h}; text-align: bottom;">'+
        '<div class="msgwrap" style="height: 75px; bottom: 0px; position: relative;">'+
          '<span class="arrow {s}"></span>'+
          '<span class="msg">{m}</span>'+
        '</div>'+
      '</div>');
    this.previousEl = this.previousTpl.insertBefore(this.cmp.scroller.el, {h:0,m:this.langPullPrevious,l:this.lastUpdate}, true);
    this.previousEl.hide();
    Ext.Element.cssTranslate(this.previousEl, {x:0, y:+75});
    //this.cmp.scroller.on('offsetchange', this.handlePrevious, this);
    
    //Next
    this.nextTpl = new Ext.XTemplate(
      '<div class="pullnext" style="height: {h}; text-align: bottom;">'+
        '<div class="msgwrap" style="height: 75px; bottom: 0px; position: relative;">'+
          '<span class="arrow {s}"></span>'+
          '<span class="msg">{m}</span>'+
        '</div>'+
      '</div>');
    this.nextEl = this.nextTpl.insertAfter(this.cmp.scroller.el, {h:0,m:this.langPullNext,l:this.lastUpdate}, true);
    this.nextEl.hide();
    Ext.Element.cssTranslate(this.nextEl, {x:0, y:-75});
    
    
    this.cmp.scroller.on('offsetchange', this.handleOffsettChange, this);
  },
  
  handleOffsettChange: function(scroller, offset) {
    if (scroller.direction === 'vertical' && !this.loading){
      
      var heightOfList = scroller.size.height - scroller.containerBox.height;
      
      if (offset.y > 0){
        //console.log('up');
        this.handlePrevious(scroller, offset, heightOfList);
      }
      
      if (offset.y < (heightOfList * -1)) {
        //console.log('down');
        this.handleNext(scroller, offset, heightOfList);
      }
    }
  },
  
  //private
  handlePrevious: function(scroller, offset, heightOfList){
    if (scroller.direction === 'vertical' && !this.loading){
      if (offset){
        Ext.Element.cssTranslate(this.previousEl, {x:0, y:offset.y-75});
        if (offset.y > 75){
          // state 1
          if (this.state !== 1){
            this.prevState = this.state;
            this.state = 1;
            this.previousTpl.overwrite(this.previousEl, {h:offset.y,m:this.langReleasePrevious,l:this.lastUpdate});
            Ext.Anim.run(this.previousEl.select('.arrow').first(),'rotate',{dir:'ccw',fromAngle:0,toAngle:180});
          }
        }else if (!scroller.isDragging()){
          // state 3
          if (this.state !== 3){
            this.prevState = this.state;
            this.state = 3;
            if (this.prevState == 1){
              this.loading = true;
              this.lastUpdate = new Date();
              this.previousEl.hide();
              if (this.previousFn){
                this.previousFn.call(this,this.previousComplete,this);
              }else{
                this.cmp.getStore().load();
              }
            }
          }
        }else{
          // state 2
          if (this.state !== 2){
            this.prevState = this.state;
            this.state = 2;
            this.previousTpl.overwrite(this.previousEl, {h:offset.y,m:this.langPullPrevious,l:this.lastUpdate});
            this.previousEl.show();
            if (this.prevState == 1){
              Ext.Anim.run(this.previousEl.select('.arrow').first(),'rotate',{dir:'cw',fromAngle:180,toAngle:0});
            }
          }
        }
      }
    }
  },
  handleNext: function(scroller, offset, heightOfList){
    if (scroller.direction === 'vertical' && !this.loading){
      if (offset){
        Ext.Element.cssTranslate(this.nextEl, {x:0, y:offset.y});
        if (offset.y < ((heightOfList + 75)*-1)){
          // state 1
          if (this.state !== 1){
            this.prevState = this.state;
            this.state = 1;
            this.nextTpl.overwrite(this.nextEl, {h:offset.y,m:this.langReleaseNext,l:this.lastUpdate});
            Ext.Anim.run(this.nextEl.select('.arrow').first(),'rotate',{dir:'ccw',fromAngle:180,toAngle:0});
          }
        }else if (!scroller.isDragging()){
          // state 3
          if (this.state !== 3){
            this.prevState = this.state;
            this.state = 3;
            if (this.prevState == 1){
              this.loading = true;
              this.lastUpdate = new Date();
              this.nextEl.hide();
              if (this.nextFn){
                this.nextFn.call(this,this.nextComplete,this);
              }else{
                this.cmp.getStore().load();
              }
            }
          }
        }else{
          // state 2
          if (this.state !== 2){
            this.prevState = this.state;
            this.state = 2;
            this.nextTpl.overwrite(this.nextEl, {h:offset.y,m:this.langPullNext,l:this.lastUpdate});
            this.nextEl.show();
            if (this.prevState == 1){
              Ext.Anim.run(this.nextEl.select('.arrow').first(),'rotate',{dir:'cw',fromAngle:180,toAngle:0});
            }
          }
        }
      }
    }
  },
  //private
  previousComplete: function(){
    this.loading = false;
    this.lastUpdate = new Date();
    this.previousTpl.overwrite(this.previousEl, {h:0,m:this.langPullPrevious,l:this.lastUpdate});
  },
  nextComplete: function(){
    this.loading = false;
    this.lastUpdate = new Date();
    this.nextTpl.overwrite(this.nextEl, {h:0,m:this.langPullNext,l:this.lastUpdate});
  }
});

Ext.preg('listpullpager', mobile.plugins.ListPullPager);
CSS

Code:
div.pullprevious, div.pullprevious div.msgwrap {
  background-color: #e1e1e1 !important;
}

div.pullprevious span.arrow {
  width: 32px;
  height: 60px;
  position: absolute;
  top: 0;
  left: 10px;
  background-image: url('../images/blackArrow.png');
  background-repeat: no-repeat;
  margin: 10px 0 0 25px;
}

div.loadingspacer span.loading {
  width: 32px;
  height: 60px;
  position: absolute;
  top: 0;
  left: 10px;
  background-image: url('../images/loader.gif');
  background-repeat: no-repeat;
  background-position: 0 7px;
}

div.pullprevious span.msg, div.loadingspacer span.msg {
  width: 80%;
  text-align: center;
  font-size: 0.9em;
  position: absolute;
  top: 12px;
  left: 40px;
  margin: 5px 0 5px 40px; 
  font-weight: bold;
}

div.pullprevious span.lastupdate {
  width: 80%;
  text-align: center;
  font-size: 0.7em;
  position: absolute;
  top: 25px;
  left: 40px;
  margin: 15px 0 5px 40px;
}

div.pullnext, div.pullnext div.msgwrap {
  background-color: #e1e1e1 !important;
}

div.pullnext span.arrow {
  width: 32px;
  height: 60px;
  position: absolute;
  top: 0;
  left: 10px;
  background-image: url('../images/blackArrow.png');
  background-repeat: no-repeat;
  margin: 10px 0 0 25px;
  -webkit-transform: rotate(180deg);
}

div.pullnext span.msg, div.loadingspacer span.msg {
  width: 80%;
  text-align: center;
  font-size: 0.9em;
  position: absolute;
  top: 12px;
  left: 40px;
  margin: 5px 0 5px 40px; 
  font-weight: bold;
}

div.pullnext span.lastupdate {
  width: 80%;
  text-align: center;
  font-size: 0.7em;
  position: absolute;
  top: 25px;
  left: 40px;
  margin: 15px 0 5px 40px;
}
Figured I'd post it here just incase its of value to somebody.