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

android仿QQ个人主页下拉回d效果,第1张

概述先看效果:效果不错吧!进入主题之前,先了解ImageView的scaleType的center_crop,网络上说的已经很清楚了:以下抄自网络:

先看效果:

效果不错吧!

进入主题之前,先了解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)时让其回到初始位置,并伴着回d过程,这里通过自定义动画让其具备回d效果
(2)dy<0,则是上拉,上推的过程,由于topVIEw和ImagevIEw不具备滚动的效果,所以上推也是通过控制topVIEw和ImageVIEw的高度,并且当topVIEw和ImageVIEw滑出屏幕时就不在更改高度防止不断的绘制,提高性能。
ok,大体思路就这样。具体分析代码如下:

实现:

activity的xml
stretch_act.xml:

<linearLayout xmlns:androID="http://schemas.androID.com/apk/res/androID"    androID:layout_wIDth="match_parent"    androID:layout_height="match_parent"    androID:orIEntation="vertical"> <!--这是topVIEw--> <relativeLayout  androID:ID="@+ID/rl_top"  androID:layout_wIDth="match_parent"  androID:layout_height="wrap_content"  >  <!--这是imageVIEw,一定要设置scaleType为centerCrop-->  <ImageVIEw   androID:ID="@+ID/iv_stretch_pic"   androID:layout_wIDth="match_parent"   androID:layout_height="wrap_content"   androID:scaleType="centerCrop"   androID:src="@drawable/stretch_s"   />  <TextVIEw   androID:layout_wIDth="wrap_content"   androID:layout_height="wrap_content"   androID:layout_alignBottom="@ID/iv_stretch_pic"   androID:text="你最美,你最酷…………^^"   androID:textSize="16sp"/> </relativeLayout><!--这是自定义的ListvIEw--> <com.example.zwr.myapplication.Widget.StretchListVIEw  androID:ID="@+ID/ListvIEw"  androID:layout_wIDth="match_parent"  androID:layout_height="match_parent"  androID:cachecolorHint="@null"  androID:divIDer="@null"  androID:ListSelector="#00000000"/></linearLayout>

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

 float translationY = getNegativeMaxValue(tempDy,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发生改变,并且是下拉时,这是松开手或者手指移出屏幕,则让其回d到初始位置;这里是通过自定义动画来改变其变化的高度,达到回d效果 代码如下

 /**  * 自定义回d动画,使imageVIEw和topVIEw过渡回d到初始位置  */ 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系统是开源的导致有些系统是无法回调这个方法的,以至于无法实现回d效果(比如:vivoX5)等等。所以在ontouchEvent()搞事情才是王道
ok!,以上有什么问题,请不吝指正!!!

Demo:android个人主页下拉回d

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

总结

以上是内存溢出为你收集整理的android仿QQ个人主页下拉回d效果全部内容,希望文章能够帮你解决android仿QQ个人主页下拉回d效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/web/1146783.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存