做安卓开发的朋友们,不知道你们会不会经常用遇到这样的情景,某个做所畏的产品设计的sb,拿着iphone来看给你看,说看苹果的这个效果多好,看那个效果多好。苹果也比安卓清晰多了,你能不能也把咱们的安卓应用也做成这种效果的。那样的用户体验更好,更cool一些。不知你们有没有遇到过这样半吊子的sb设计,反正我是遇到了。所以本文由此而生。

  进入正题:首先你要实现弹性效果的view要能确定什么时候应该出现下拉的效果,什么时候出现下推的效果。在代码里的体现就是你要实现IScrollOverable接口。本文中的例子就拿GridView来做个例子。

  无图无真相:

  

  实现了IScrollOverable接口的GridView:

  

 1 public class BshSOGridView extends GridView implements
 2         IScrollOverable
 3 {
 4     public BshSOGridView(Context context, AttributeSet attrs,
 5             int defStyle)
 6     {
 7         super( context, attrs, defStyle );
 8     }
 9
10     public BshSOGridView(Context context, AttributeSet attrs)
11     {
12         super( context, attrs );
13     }
14
15     public BshSOGridView(Context context)
16     {
17         super( context );
18     }
19
20     @Override
21     public boolean isScrollOnTop()
22     {
23         return 0 == getFirstVisiblePosition() ? true : false;
24     }
25
26     @Override
27     public boolean isScrollOnBtm()
28     {
29         return (getCount() - 1) == getLastVisiblePosition() ? true : false;
30     }
31 }

  

  处理弹性效果的view.实际上是把想要有弹性效果的view加到这个view里来。

/*** 本类旨在实现通用的弹性刷新效果。只要实现了IScrollOverable的view都可以据有弹性效果。上弹下弹均可以哦!* * @author http://www.cnblogs.com/bausch/* */
public class BshElasticView extends LinearLayout
{final int RELEASE_H = 0;final int PULL = 1;final int REFRESHING_H = 2;final int PUSH = 3;final int RELEASE_F = 4;final int REFRESHING_F = 5;final int NORMAL = 6;int factor = 3;float maxElastic = 0.2f;int critical = 2;int maxElasticH, maxElasticF;boolean isTopRecored;boolean isBtmRecored = false;int startY;IRefresh irefresh;RotateAnimation animation;RotateAnimation reverseAnimation;int state = NORMAL;boolean isBack;View rv;RelativeLayout headerView, footerView, continer, main_continer;ProgressBar hPro, fPro;ImageView hArow, fArow;TextView tvTipH, tvTipF, tvLstH, tvLstF;Context ctx;private IScrollOverable overable;public int continerH, continerW, headerH, headerW, footerH, footerW, rvH,rvW;Handler handler = new Handler(){@Overridepublic void handleMessage(Message msg){switch ( msg.what ){case 0:Log.d( "bsh", "刷新完成,到normal状态" );state = NORMAL;changeFooterViewByState();break;}}};public BshElasticView(Context context, AttributeSet attrs, int defStyle){super( context, attrs );init( context );}public BshElasticView(Context context, AttributeSet attrs){super( context, attrs );init( context );}public BshElasticView(Context context){super( context );init( context );}public void setScrollOverable(IScrollOverable o){overable = o;addView( ( View ) o );}public void init(Context ctx){this.ctx = ctx;rv = View.inflate( ctx, R.layout.elastic_view, null );main_continer = ( RelativeLayout ) rv.findViewById( R.id.main_continer );headerView = ( RelativeLayout ) rv.findViewById( R.id.header );hPro = ( ProgressBar ) rv.findViewById( R.id.pro_h );hArow = ( ImageView ) rv.findViewById( R.id.iv_harow );tvTipH = ( TextView ) rv.findViewById( R.id.tv_htip );tvLstH = ( TextView ) rv.findViewById( R.id.tv_lst );measureViewHeight( headerView );headerH = headerView.getMeasuredHeight();headerW = headerView.getMeasuredWidth();footerView = ( RelativeLayout ) rv.findViewById( R.id.footer );fPro = ( ProgressBar ) rv.findViewById( R.id.pro_f );fArow = ( ImageView ) rv.findViewById( R.id.iv_farow );tvTipF = ( TextView ) rv.findViewById( R.id.tv_ftip );tvLstF = ( TextView ) rv.findViewById( R.id.tv_lstf );footerH = headerH;footerW = headerW;continer = ( RelativeLayout ) rv.findViewById( R.id.continer );addView( rv, new ViewGroup.LayoutParams( LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT ) );main_continer.setPadding( 0, -1 * headerH, 0, 0 );rv.invalidate();rv.requestLayout();animation = new RotateAnimation( 0, -180,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f );animation.setDuration( 500 );animation.setFillAfter( true );reverseAnimation = new RotateAnimation( -180, 0,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f );reverseAnimation.setDuration( 500 );reverseAnimation.setFillAfter( true );state = NORMAL;}private void measureViewHeight(View child){ViewGroup.LayoutParams p = child.getLayoutParams();if ( null == p ){p = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.FILL_PARENT );}int childHeightSpec = ViewGroup.getChildMeasureSpec( 0, 0 + 0, p.height );int lpWidth = p.width;int childWidthSpec;if ( lpWidth > 0 ){childWidthSpec = MeasureSpec.makeMeasureSpec( lpWidth,MeasureSpec.EXACTLY );}else{childWidthSpec = MeasureSpec.makeMeasureSpec( 0,MeasureSpec.UNSPECIFIED );}child.measure( childWidthSpec, childHeightSpec );}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b){super.onLayout( changed, l, t, r, b );rvH = b;rvW = r;footerH = headerH;footerW = headerW;continerH = rvH;continerW = rvW;maxElasticH = ( int ) (headerH + continerH * maxElastic);maxElasticF = 0 - maxElasticH;RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams( rvW,rvH );rl.addRule( RelativeLayout.BELOW, R.id.header );continer.setLayoutParams( rl );continer.requestLayout();}public interface IScrollOverable{public boolean isScrollOnTop();public boolean isScrollOnBtm();}public void addView(View v){continer.addView( v, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,RelativeLayout.LayoutParams.FILL_PARENT ) );}public void changeHeaderViewByState(){switch ( state ){case RELEASE_H:hArow.setVisibility( View.VISIBLE );hPro.setVisibility( View.GONE );tvTipH.setVisibility( View.VISIBLE );tvLstH.setVisibility( View.VISIBLE );hArow.clearAnimation();hArow.startAnimation( animation );tvTipH.setText( "松开刷新" );Log.d( "bsh", "当前状态,松开刷新" );break;case PULL:hPro.setVisibility( View.GONE );tvTipH.setVisibility( View.VISIBLE );tvLstH.setVisibility( View.VISIBLE );hArow.clearAnimation();hArow.setVisibility( View.VISIBLE );if ( isBack ){isBack = false;hArow.clearAnimation();hArow.startAnimation( reverseAnimation );}tvTipH.setText( "下拉刷新" );Log.d( "bsh", "当前状态,上推刷新" );break;case REFRESHING_H:hPro.setVisibility( View.VISIBLE );hArow.clearAnimation();hArow.setVisibility( View.GONE );tvTipH.setText( "正在刷新..." );tvLstH.setVisibility( View.INVISIBLE );tvLstH.setText( "上次更新:"+ Calendar.getInstance().getTime().toLocaleString() );Log.d( "bsh", "当前状态,正在刷新..." );break;case NORMAL:setRvPadding( -1 * headerH );hPro.setVisibility( View.GONE );hArow.clearAnimation();hArow.setImageResource( R.drawable.arrow_down );tvTipH.setText( "下拉刷新" );tvLstH.setVisibility( View.VISIBLE );Log.d( "bsh", "当前状态,normalf" );break;}}public void changeFooterViewByState(){switch ( state ){case RELEASE_F:fArow.setVisibility( View.VISIBLE );fPro.setVisibility( View.GONE );tvTipF.setVisibility( View.VISIBLE );tvLstF.setVisibility( View.VISIBLE );fArow.clearAnimation();fArow.startAnimation( animation );tvTipF.setText( "松开刷新" );Log.d( "bsh", "当前状态,松开刷新" );break;case PUSH:fPro.setVisibility( View.GONE );tvTipF.setVisibility( View.VISIBLE );tvLstF.setVisibility( View.VISIBLE );fArow.clearAnimation();fArow.setVisibility( View.VISIBLE );if ( isBack ){isBack = false;fArow.clearAnimation();fArow.startAnimation( reverseAnimation );}tvTipF.setText( "上推刷新" );Log.d( "bsh", "当前状态,上推刷新" );break;case REFRESHING_F:fPro.setVisibility( View.VISIBLE );fArow.clearAnimation();fArow.setVisibility( View.GONE );tvTipF.setText( "正在刷新..." );tvLstF.setVisibility( View.INVISIBLE );tvLstF.setText( "上次更新:"+ Calendar.getInstance().getTime().toLocaleString() );Log.d( "bsh", "当前状态,正在刷新..." );break;case NORMAL:setRvPadding( -1 * headerH );fPro.setVisibility( View.GONE );fArow.clearAnimation();fArow.setImageResource( R.drawable.arrow_up );tvTipF.setText( "上推刷新" );tvLstF.setVisibility( View.VISIBLE );Log.d( "bsh", "当前状态,normalf" );break;}}public void setRvPadding(int padding){Log.d( "bsh", "padding:" + padding );if ( padding < maxElasticF ){return;}else if ( padding > maxElasticH ){return;}main_continer.setPadding( 0, padding, 0, 0 );rv.requestLayout();}@Overridepublic boolean dispatchTouchEvent(MotionEvent event){switch ( event.getAction() ){case MotionEvent.ACTION_DOWN:startRecord( event );break;case MotionEvent.ACTION_UP:handleUpF();handleUpH();break;case MotionEvent.ACTION_MOVE:handleMove( event );break;}if ( state == NORMAL || state == REFRESHING_H || state == REFRESHING_F ){return super.dispatchTouchEvent( event );}elsereturn true;}public void handleMove(MotionEvent event){int tempY = ( int ) event.getY();tempY = tempY < 0 ? 0 : tempY;Log.d( "bsh", "get temp:" + tempY );startRecord( event );if ( state != REFRESHING_F && isBtmRecored ){handleMoveF( tempY );}else if ( state != REFRESHING_H && isTopRecored ){handleMoveH( tempY );}}public void handleMoveH(int tempY){Log.d( "bsh", "release to refresh h" );if ( state == RELEASE_H ){Log.d( "bsh", "release to refresh h" );if ( ((tempY - startY) / factor < headerH * critical)&& (tempY - startY) > 0 ){state = PULL;changeHeaderViewByState();Log.d( "bsh", "由松开刷新状态转变到下拉刷新状态" );}else if ( startY - tempY > 0 ){state = NORMAL;changeHeaderViewByState();Log.d( "bsh", "由松开刷新状态转变到normal状态" );}}if ( state == PULL ){Log.d( "bsh", "push to refresh" );if ( (tempY - startY) / factor >= headerH * critical ){state = RELEASE_H;isBack = true;changeHeaderViewByState();Log.d( "bsh", "由normal或者下拉刷新状态转变到松开刷新" );}else if ( tempY - startY <= 0 ){state = NORMAL;changeHeaderViewByState();Log.d( "bsh", "由normal或者下拉刷新状态转变到normal状态" );}}if ( state == NORMAL ){if ( tempY - startY > 0 ){Log.d( "bsh", "normalf to push to refersh" );state = PULL;changeHeaderViewByState();}}// 这里就是处理弹性效果的地方if ( state == PULL || state == RELEASE_H ){setRvPadding( (tempY - startY) / factor - headerH );}}public void handleMoveF(int tempY){if ( state == RELEASE_F ){Log.d( "bsh", "release to refresh f" );if ( ((tempY - startY) / factor > 0 - headerH * critical)&& (tempY - startY) < 0 ){state = PUSH;changeFooterViewByState();Log.d( "bsh", "由松开刷新状态转变到上推刷新状态" );}else if ( tempY - startY >= 0 ){state = NORMAL;changeFooterViewByState();Log.d( "bsh", "由松开刷新状态转变到normal状态" );}}if ( state == PUSH ){Log.d( "bsh", "push to refresh" );if ( (tempY - startY) / factor <= (0 - headerH * critical) ){state = RELEASE_F;isBack = true;changeFooterViewByState();Log.d( "bsh", "由normal或者上推刷新状态转变到松开刷新" );}else if ( tempY - startY >= 0 ){state = NORMAL;changeFooterViewByState();Log.d( "bsh", "由normal或者上推刷新状态转变到normal状态" );}}if ( state == NORMAL ){if ( tempY - startY < 0 ){Log.d( "bsh", "normalf to push to refersh" );state = PUSH;changeFooterViewByState();}}// 这里就是处理弹性效果的地方。if ( state == PUSH || state == RELEASE_F ){setRvPadding( (tempY - startY) / factor - headerH * 2 );}}public void startRecord(MotionEvent event){if ( overable.isScrollOnTop() && !isTopRecored ){isTopRecored = true;startY = ( int ) event.getY();}if ( overable.isScrollOnBtm() && !isBtmRecored ){isBtmRecored = true;startY = ( int ) event.getY();}}public void handleUpF(){if ( state != REFRESHING_F ){if ( state == PUSH ){state = NORMAL;changeFooterViewByState();Log.d( "bsh", "由上推刷新状态,到normal状态" );}if ( state == RELEASE_F ){state = REFRESHING_F;changeFooterViewByState();setRvPadding( -1 * headerH - 1 );irefresh.refreshBtm();}}isBtmRecored = false;isBack = false;}public void handleUpH(){if ( state != REFRESHING_H ){if ( state == PULL ){state = NORMAL;changeHeaderViewByState();Log.d( "bsh", "由下拉状态,到normal状态" );}if ( state == RELEASE_H ){state = REFRESHING_H;changeHeaderViewByState();setRvPadding( 0 );irefresh.refreshTop();}}isTopRecored = false;isBack = false;}public void onRefreshComplete(){handler.sendEmptyMessage( 0 );}public interface IRefresh{public boolean refreshTop();public boolean refreshBtm();}/**** 设置拉动效果幅度建议值(1-5)* * @param factor*/public void setFactor(int factor){this.factor = factor;}/**** 设置最大拉动的位置,请在(0.0f-1.0f)之间取值* * @param maxElastic*/public void setMaxElastic(float maxElastic){this.maxElastic = maxElastic;}/**** 设置拉动和松开状态切换的临界值,1-5之间* * @param critical*/public void setCritical(int critical){this.critical = critical;}}

  调用Activity:

public class BshSOViewActivity extends Activity {BshElasticView ev;BshSOGridView gv;GridAdagper ga = new GridAdagper();@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate( savedInstanceState );setContentView( R.layout.elastic_grid );ev = ( BshElasticView ) findViewById( R.id.ev );//拉动幅度ev.setFactor( 2 );//拉动范围ev.setMaxElastic( 0.9f );gv = new BshSOGridView( this );gv.setBackgroundColor( Color.WHITE );gv.setNumColumns( 4 );gv.setAdapter( ga );ev.setScrollOverable( gv );ev.irefresh = new IRefresh(){@Overridepublic boolean refreshTop(){new Thread( new Runnable(){@Overridepublic void run(){try{Log.d( "bsh", "refreshing" );//在这里做刷新操作读数据神马的。这里用睡觉代替Thread.sleep( 3000 );} catch ( InterruptedException e ){e.printStackTrace();}ev.onRefreshComplete();}} ).start();return false;}@Overridepublic boolean refreshBtm(){new Thread( new Runnable(){@Overridepublic void run(){try{Log.d( "bsh", "refreshing" );Thread.sleep( 3000 );} catch ( InterruptedException e ){e.printStackTrace();}ev.onRefreshComplete();}} ).start();return false;}};}class GridAdagper extends BaseAdapter{@Overridepublic int getCount(){return 100;}@Overridepublic Object getItem(int arg0){return null;}@Overridepublic long getItemId(int arg0){return 0;}@Overridepublic View getView(int arg0, View arg1, ViewGroup arg2){if ( null == arg1 ){arg1 = new ImageView( BshSOViewActivity.this );arg1.setBackgroundResource( R.drawable.ic_launcher );}return arg1;}}
}

工程源码:点我

转载于:https://www.cnblogs.com/bausch/archive/2012/06/12/2546221.html

安卓弹性刷新通用版—支持任何view上下刷新均有弹性效果相关推荐

  1. 安卓仿苹果音量调节_android自定义view仿照MIUI中音量控制效果

    先看效果图: 这就是miui中的音量效果图,实现思路是自定义视图,绘制圆环,然后设置进度显示. 核心代码在onDraw中实现如下: @Override protected void onDraw(Ca ...

  2. Linux多定时器实现之三——Windows和Linux通用版

    Linux多定时器实现之三--Windows和Linux通用版 支持windows和linux. 支持秒以下定时器. /**************************************** ...

  3. AirServer电脑通用版下载及使用教程

    AirServer 是一款功能十分强大的投屏软件,支持并适用于 Windows和Mac.AirServer 是接收方,而不是发送方. AirServer 只允许您接收镜像或流媒体内容,反之则不行.Ai ...

  4. Android 怎么实现支持所有View的通用的下拉刷新控件

    转载请标明出处: http://blog.csdn.net/u010386612/article/details/51372696 本文出自:[AItsuki的博客] 下拉刷新对于一个app来说是必不 ...

  5. android opengl版本太低,安卓模拟器opengl_安卓模拟器无法安装“系统opengl版本过低”的通用解决方法_安卓模拟器通用版_通用安卓模拟器...

    安卓模拟器无法安装"系统opengl版本过低"的通用解决方法 在安装安卓模拟器时,出现"系统opengl版本过低",下图提示,说明你的显卡暂不支持模拟器: 遇到 ...

  6. xposed框架android9.0,安卓框架虚拟机VirtualXposed v0.17.1 清爽版 支持安卓9.0系统

    安卓框架虚拟机VirtualXposed v0.17.1 清爽版 支持安卓9.0系统 VirtualXposed 是基于VirtualApp 和 epic 在非ROOT环境下运行Xposed模块的实现 ...

  7. android 11 机型,安卓11支持机型介绍-安卓11正式版支持机型大全

    安卓11正式版系统已经于9月9日正式上线,这也意味着大部分的安卓手机将迎来一次系统的大规模更新升级,目前最新的消息显示称:谷歌旗下自己的手机品牌Pixel系列已经可以下载更新,国内的手机品牌之中哪些手 ...

  8. 从DDD到PaaS化再到一站式部署——通天塔后端通用版发展之路

    通用版的背景和目标 通天塔是一个面向京东运营和商家的活动搭建平台,提供了丰富和强大的模板,平台用户可基于模板自由搭建活动页面.通天塔支持无线和PC页面的搭建,提供的3种搭建方式:模块搭建.自定义开发( ...

  9. 民科微服务电脑版下载_天翼云桌面通用版电脑版下载|天翼云桌面通用版PC客户端 V1.23.0 官方最新版 下载_当下软件园...

    天翼云桌面通用版电脑版是一款由中国电信股份有限公司云计算分公司所推出的云终端桌面平台.该版本是通过在电脑上安装安卓模拟器来实现运行的,以此达到PC端的使用效果,基于特有的通信协议,通过云终端将桌面或应 ...

最新文章

  1. 整合vs2005sp1到vs2005安装文件中
  2. 微信小程序实例源码大全demo下载
  3. 比较全面的gdb调试命令
  4. Elasticsearch-02CentOS7安装elasticsearch-head插件
  5. V4L2 driver(一). 整体框架
  6. python注释以符号什么开始_python注释以什么符号开始
  7. 组件化与插件化的差别在哪里?内含福利
  8. scala语言示例_标有示例的Scala关键字
  9. LeetCode 717. 1-bit and 2-bit Characters
  10. java关闭按钮代码_Java高手看看如何实现关闭按钮
  11. Thinking in ++i and i++
  12. ERROR: Could not install packages due to an EnvironmentError: [Errno 13] 权限不够的解决办法
  13. 定制Eclipse IDE之功能篇(二)
  14. Windows操作系统发展简史
  15. nlohmann json使用
  16. AIBOX-32路智能园区安全视频流分析AI服务器
  17. 使用拦截器防止表单重复提交
  18. 国产28nm制程光刻机突破在即,助力国产芯片
  19. 抽象代数之第一群同构定理的证明
  20. 生产环境SLB-F5会话保持失效问题排查及总结

热门文章

  1. python gridsearch_Python超参数自动搜索模块GridSearchCV上手
  2. 查看数值类型python_Python数据科学实践 | 数据类型
  3. python常用_30个Python常用小技巧
  4. 多算法综合的文本挖掘系统
  5. vba替换字符串中的字符_R语言 | 字符串替换
  6. mysql 格式化 小数点后两位_MYSQL数据库mysql格式化小数保留小数点后两位(小数点格式化)...
  7. php7从基础到商业实战,TP5从基础到项目实战全套
  8. mysql 大文件导入工具_BigDump:导入超大mysql数据库文件工具
  9. poj 2870 Light Up(dfs+剪枝,写的稀烂)
  10. 程序员如何掌握计算机英语