热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

android仿QQ个人主页下拉回弹效果

这篇文章主要为大家详细介绍了android仿QQ个人主页下拉回弹效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

先看效果:

效果不错吧!

进入主题之前,先了解ImageView的scaleType的center_crop,网络上说的已经很清楚了 : 以下抄自网络:

1.Android:scaleType=”centerCrop”
以填满整个ImageView为目的,将原图的中心对准ImageView的中心,等比例放大原图,直到填满ImageView为止(指的是ImageView的宽和高都要填满),原图超过ImageView的部分作裁剪处理。

均衡的缩放图像(保持图像原始比例),使图片的两个坐标(宽、高)都大于等于 相应的视图坐标(负的内边距)。图像则位于视图的中央。 在XML 中可以使用的语法:android:scaleType=”centerCrop”。

不说废话,直接进入主题!!

思路

1.先将topView的布局和listview平级,然后将topview以及topview包裹的imageView中传listview,即一般是activity的layout
2.重写listView的ontoucEvent()方法,但不做任何拦截,只在action时,控制imageView以及topView的高度,使其重新layout然后重新布局就可以了。
3.以上是大概思路,这里具体分析:当action_down时记录其初始位置,action_move时得到dy,通过dy来判断是上啦还是下拉:
(1)dy>0,则是下拉,不断重新设置topView和imageView的高度,又因为imageView的scaleType=center_crop,所以图片会按照这个规则进行等比拉伸,当到达图片最大时就会有不断放大的过程
当松开手或者手指移出屏幕外时(action_up|action_outside|action_cancel)时让其回到初始位置,并伴着回弹过程,这里通过自定义动画让其具备回弹效果
(2)dy<0,则是上拉,上推的过程,由于topView和Imageview不具备滚动的效果,所以上推也是通过控制topView和ImageView的高度,并且当TopVIew和ImageView滑出屏幕时就不在更改高度防止不断的绘制,提高性能。
ok,大体思路就这样。具体分析代码如下:

实现:

activity的xml
stretch_act.xml:



 
 

  
  

  

 

 




看看StretchListView:

/***
  * @param topView
  * @param imgResId 图片id
  */
 public void setTopView(View topView, int imgResId) {
  if (null != topView) {
   this.topView = topView;
   imageView = (ImageView) topView.findViewById(imgResId);
  }
 }

通过这个对外的方法,将topView以及ImageView的id传进来

分析:重新ListView的onTouchEvent():

ACTION_DOWN:
  case MotionEvent.ACTION_DOWN:
    startY = ev.getRawY();
    if (!hadInit) {//初始化,只要初始化一次就够了
     childAt0Top = getChildAt(0).getTop();
     ivInitHeight = imageView.getHeight();
     hadInit = true;
    }
    break;

只是进行一些初始化操作:

 1. startY:相对于屏幕顶部的高度
 2. childAt0Top,获取listview的第一个view的top距离、
 3. ivInitHeight:获取ImageView的初始高度,即刚进来时的高度
ACTION_MOVE:

case MotionEvent.ACTION_MOVE:
    Log.d(TAG, "dy = " + dy);
    dy = ev.getRawY() - startY;
    if (dy > 0 && 0 == getFirstVisiblePosition() && 
    childAt0Top == getChildAt(0).getTop()) {//(1)手指从上往下拉:下拉
     int tempDy = (int) (dy + 0.5);
     //一定也要给topView增加一定的高度,否则从上啦到下拉就不会显示
     imageView.getLayoutParams().height = imageView.getHeight() + tempDy;
     topView.getLayoutParams().height = topView.getHeight() + tempDy;
     topView.requestLayout();
     isChangedHeight = true;

    } else {//(2)手指从下往上拉:上拉
     int tempDy = (int) (dy - 0.5);
     int currHeight = imageView.getHeight();
     float translatiOnY= getNegativeMaxValue(tempDy, -currHeight, 0);
     if (translationY <= 0 && currHeight > 0) {
      LinearLayout.LayoutParams lp = 
      (LinearLayout.LayoutParams) topView.getLayoutParams();
      //一定要减去titleBar,如果没有去掉Winow.xxx.Title,还要减去这个高度,否则会显示不全
      lp.height = topView.getHeight() + (int) translationY;
      topView.requestLayout();//
      isChangedHeight = true;
     }
    }
    //用这个getRawY而不是用getY,是因为listview也会随着改变,
    //而getY获取的就是listview本身的Y,所以基本是变化不大的,
    // 而使用getRawY相对于屏幕的距离,保证滑动了多大的距离就改变多大的距离
    startY = ev.getRawY();
    break;

当下拉时:主要条件如下:

1.dy > 0 && 0 == getFirstVisiblePosition() && childAt0Top ==
getChildAt(0).getTop()
意思是当下拉时,并且listview的第一个位置显示全了,才能下拉放大图片,这是避免,listview已经发生滚动了,需要回到初始位置才能下拉放大,否则会出现,立即下拉放大,体验不好
2.当上拉时 主要条件
if (translationY <= 0 && currHeight > 0)
currHeight>0:当前ImageView的高度,如果已经滚动到顶部或者超出,则不再进行滚动,防止已经滚出屏幕不可视了,还在进行滚动。
translationY<=0: 这个值是滚动的距离,这个距离不能超过ImageView的高度,由于上拉时dy是负值,所以要判断是否小于0;其主要方法如下:

 float translatiOnY= getNegativeMaxValue(tempDy, -currHeight, 0);
 /***
  * 手指上移过程dy是负数
  * 返回负数最大值:0是最大值,不可以超过
  *
  * @param value   移动的最终距离:上次的位置+当次移动的偏移量之和,就是本次要移动的最终的偏移量
  * @param canMoveMaxValue 可移动的最大值
  * @param maxValue
  * @return
  */
 public static float getNegativeMaxValue(float value,float canMoveMaxValue, float maxValue) {
  return Math.min(maxValue, Math.max(canMoveMaxValue, value));
 }

ACTION_UP:

case MotionEvent.ACTION_OUTSIDE:
   case MotionEvent.ACTION_CANCEL:
   case MotionEvent.ACTION_UP:
    if (isChangedHeight) {
     if (imageView.getHeight() > ivInitHeight) {// (1)手指从上往下拉:下拉
      ResetAnimation resetAnimation = 
      new ResetAnimation(ivInitHeight, imageView, topView);
      resetAnimation.setDuration(200);
      imageView.startAnimation(resetAnimation);
     } else {//(2)手指从下往上拉:上拉。。。这个不用处理。。。因为上拉后松开让其topview固定

     }
     isChangedHeight = false;
    }
    break;

isChangedHeight:当发生ImageView发生改变,并且是下拉时,这是松开手或者手指移出屏幕,则让其回弹到初始位置;这里是通过自定义动画来改变其变化的高度,达到回弹效果 代码如下

 /**
  * 自定义回弹动画,使imageView和topView过渡回弹到初始位置
  */
 static class ResetAnimation extends Animation {
  private View topView;
  private int topCurrHeight;

  private ImageView ivStretch;
  private int ivInitHeight;
  private int ivCurrHeight;

  public ResetAnimation(int ivInitHeiht, ImageView ivStretch, View topView) {

   this.ivInitHeight = ivInitHeiht;
   this.ivCurrHeight = ivStretch.getHeight();
   this.topCurrHeight = topView.getHeight();
   this.ivStretch = ivStretch;
   this.topView = topView;
  }

  @Override
  protected void applyTransformation(float interpolatedTime, Transformation t) {
   int dy = (int) ((ivCurrHeight - ivInitHeight) * interpolatedTime);
   Log.d(TAG, "anim dy = " + dy);
   ivStretch.getLayoutParams().height = ivCurrHeight - dy;
   topView.getLayoutParams().height = topCurrHeight - dy;
   topView.requestLayout();
  }
 }

其实主要是applyTransformation(float interpolatedTime, Transformation t) 这个方法

主要是通过这个渐变因子interpolatedTime来控制,其值范围是(0~1) 所以计算渐变的高度如下
int dy = (int) ((ivCurrHeight - ivInitHeight) * interpolatedTime);
然后一定要记得调用topView.requestLayout(),让其重新布局绘制。这样就完成了,所有代码,也就一百行代码左右,是不是很简单。而且通过这个demo,可以很好的拓展到scrollview中。

注意:
网上有些demo是通过overScrollBy()这个方法中搞事情,因为

/***
  * 这个方法是在滑出屏幕时回调,但是由于android系统国内厂商修改的面目全非,有些机型是不会回调的,比如vivo
  * 所以不要使用这个方法搞事情
  *
  * @param scrollX
  * @param scrollY
  */
 @Override
 protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, 
 int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, 
 boolean isTouchEvent) {
  Log.d(TAG, "deltax = " + deltaX + " deltaY = " + deltaY);
  return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX,
   scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
 }


其自带dy,还有一些其它的参数,应有尽有。但是由于android系统是开源的导致有些系统是无法回调这个方法的,以至于无法实现回弹效果(比如:vivoX5)等等。所以在onTouchEvent()搞事情才是王道
ok!,以上有什么问题,请不吝指正!!!

Demo:android个人主页下拉回弹

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在探讨Hibernate框架的高级特性时,缓存机制和懒加载策略是提升数据操作效率的关键要素。缓存策略能够显著减少数据库访问次数,从而提高应用性能,特别是在处理频繁访问的数据时。Hibernate提供了多层次的缓存支持,包括一级缓存和二级缓存,以满足不同场景下的需求。懒加载策略则通过按需加载关联对象,进一步优化了资源利用和响应时间。本文将深入分析这些机制的实现原理及其最佳实践。 ... [详细]
  • 本文探讨了如何有效地构建和优化微信公众平台账号,涵盖了用户信息管理、内容创作与发布、互动策略及数据分析等方面。通过合理设置用户信息字段,如用户名、昵称、密码、真实姓名和性别等,确保账号的安全性和用户体验。同时,文章还介绍了如何利用微信公众平台的各项功能,提升用户参与度和品牌影响力。 ... [详细]
  • 本文探讨了资源访问的学习路径与方法,旨在帮助学习者更高效地获取和利用各类资源。通过分析不同资源的特点和应用场景,提出了多种实用的学习策略和技术手段,为学习者提供了系统的指导和建议。 ... [详细]
  • 在本文中,我们将为 HelloWorld 项目添加视图组件,以确保控制器返回的视图路径能够正确映射到指定页面。这一步骤将为后续的测试和开发奠定基础。首先,我们将介绍如何配置视图解析器,以便 SpringMVC 能够识别并渲染相应的视图文件。 ... [详细]
  • SSAS入门指南:基础知识与核心概念解析
    ### SSAS入门指南:基础知识与核心概念解析Analysis Services 是一种专为决策支持和商业智能(BI)解决方案设计的数据引擎。该引擎能够为报告和客户端应用提供高效的分析数据,并支持在多维数据模型中构建高性能的分析应用。通过其强大的数据处理能力和灵活的数据建模功能,Analysis Services 成为了现代 BI 系统的重要组成部分。 ... [详细]
  • 在使用SSH框架进行项目开发时,经常会遇到一些常见的问题。例如,在Spring配置文件中配置AOP事务声明后,进行单元测试时可能会出现“No Hibernate Session bound to thread”的错误。本文将详细探讨这一问题的原因,并提供有效的解决方案,帮助开发者顺利解决此类问题。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • Java解析YAML文件并转换为JSON格式(支持JSON与XML的结构化查询)
    本文探讨了如何利用Java解析YAML文件并将其转换为JSON格式,同时支持JSON和XML的结构化查询。YAML、JSON和XML这三种数据格式通过其名称作为文件扩展名,便于区分和使用。文章详细介绍了这些格式的层次结构和数据表示方法,并重点讨论了在数据传输过程中,XML的特性和优势。此外,还提供了具体的代码示例和实现步骤,帮助开发者高效地进行数据格式转换和查询操作。 ... [详细]
  • Spring框架的核心组件与架构解析 ... [详细]
  • 本文详细解析了微信服务端示例类的功能与应用。其中,`ClientResponseHandler` 类主要用于处理微信支付所需的响应数据,而 `TenpayHttpClient` 则是对 HTTP 请求(包括 GET 和 POST 方法)进行了封装,以便在内部调用时更加便捷和高效。这些工具类在实际开发中起到了关键作用,开发者无需深入了解其底层实现细节,即可轻松集成微信支付功能。 ... [详细]
  • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
  • 深入解析:React与Webpack配置进阶指南(第二部分)
    在本篇进阶指南的第二部分中,我们将继续探讨 React 与 Webpack 的高级配置技巧。通过实际案例,我们将展示如何使用 React 和 Webpack 构建一个简单的 Todo 应用程序,具体包括 `TodoApp.js` 文件中的代码实现,如导入 React 和自定义组件 `TodoList`。此外,我们还将深入讲解 Webpack 配置文件的优化方法,以提升开发效率和应用性能。 ... [详细]
  • 本文详细介绍了如何安全地手动卸载Exchange Server 2003,以确保系统的稳定性和数据的完整性。根据微软官方支持文档(https://support.microsoft.com/kb833396/zh-cn),在进行卸载操作前,需要特别注意备份重要数据,并遵循一系列严格的步骤,以避免对现有网络环境造成不利影响。此外,文章还提供了详细的故障排除指南,帮助管理员在遇到问题时能够迅速解决,确保整个卸载过程顺利进行。 ... [详细]
  • 从文本中全面提取所有URL链接
    本文探讨了一种高效的方法,用于从大量文本数据中全面提取所有URL链接。通过使用正则表达式和Python编程语言,该方法能够准确识别并提取出各种格式的URL,包括HTTP、HTTPS等常见协议。实验结果表明,该方法在处理大规模文本数据时具有较高的准确率和效率。 ... [详细]
  • 润乾报表JNDI配置异常分析与解决方法
    在使用润乾报表时,通过JNDI连接数据源是常见的配置方式。本文详细分析了JNDI配置异常的原因,并提供了具体的解决方法。重点讨论了JNDI名称在三个关键位置的配置:1. Tomcat或应用服务器的数据源配置(以Tomcat为例);2. 润乾报表中的数据源配置;3. 应用程序代码中的JNDI名称引用。通过这些步骤,可以有效解决JNDI配置异常问题,确保报表系统的稳定运行。 ... [详细]
author-avatar
桑语敬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有