最近做项目,想要这么一个效果,就是ScrollVIEw 滑动到顶部,当不能在滑动的时候,图片可以下拉放大,松开又恢复。滑到底部没有内容的时候,也有伸缩效果,先看看效果图吧。
就是如上图这么个效果。系统提供的ScrollVIEw 是不能做到这个效果的,所以需要自己自定义,网上找了一些资料。也参考了下其他人的做法。自己也整合了一下。希望对大家有所帮助。
核心的控件就是下面的这段代码:
package com.kokjuis.travel.customVIEw; import androID.animation.ObjectAnimator; import androID.animation.ValueAnimator; import androID.content.Context; import androID.graphics.Rect; import androID.util.AttributeSet; import androID.vIEw.MotionEvent; import androID.vIEw.VIEw; import androID.vIEw.VIEwGroup; import androID.vIEw.animation.TranslateAnimation; import androID.Widget.ScrollVIEw; /** * 注意使用的时候需要放大的vIEw,一般是第一个relativeLayout或者linearLayout。要加上 androID:layout_gravity="center_horizontal" * <p> * Created by kokJuis on 2017/3/14. 189155278@qq.com */ public class BounceZoomScrollVIEw extends ScrollVIEw { private static final String TAG = "BounceScrollVIEw"; //----头部收缩属性-------- // 记录首次按下位置 private float mFirstposition = 0; // 头部图片是否正在放大 private Boolean mScaling = false; private VIEw dropZoomVIEw;//需要被放大的vIEw private int dropZoomVIEwWIDth; private int dropZoomVIEwHeight; //----头部收缩属性end-------- //------尾部收缩属性-------- private VIEw inner;// 子VIEw private float y;// 点击时y坐标 private Rect normal = new Rect();// 矩形(这里只是个形式,只是用于判断是否需要动画.) private boolean isCount = false;// 是否开始计算 //最后的坐标 private float lastX = 0; private float lastY = 0; //当前坐标 private float currentX = 0; private float currentY = 0; //移动的坐标量 private float distanceX = 0; private float distanceY = 0; private boolean updownSlIDe = false; //判断上下滑动的flag //------尾部收缩属性end-------- public BounceScrollVIEw(Context context,AttributeSet attrs) { super(context,attrs); } //初始化 private voID init() { setoverScrollMode(OVER_SCRolL_NEVER); if (getChildAt(0) != null) { inner = getChildAt(0);//这个是底部收缩的vIEw //头部收缩的 VIEwGroup vg = (VIEwGroup) getChildAt(0); if (vg.getChildAt(0) != null) { dropZoomVIEw = vg.getChildAt(0); } } } /*** * 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. 即使子类覆盖了 onFinishInflate * 方法,也应该调用父类的方法,使该方法得以执行. */ @OverrIDe protected voID onFinishInflate() { //初始化 init(); super.onFinishInflate(); } @OverrIDe public boolean dispatchtouchEvent(MotionEvent ev) { //这里只是计算尾部坐标 currentX = ev.getX(); currentY = ev.getY(); switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: distanceX = currentX - lastX; distanceY = currentY - lastY; if (Math.abs(distanceX) < Math.abs(distanceY) && Math.abs(distanceY) > 12) { updownSlIDe = true; } break; } lastX = currentX; lastY = currentY; if (updownSlIDe && inner != null) commOntouchEvent(ev); return super.dispatchtouchEvent(ev); } /*** * 触摸事件 * * @param ev */ public voID commOntouchEvent(MotionEvent ev) { //头部缩放计算 if (dropZoomVIEwWIDth <= 0 || dropZoomVIEwHeight <= 0) { dropZoomVIEwWIDth = dropZoomVIEw.getMeasureDWIDth(); dropZoomVIEwHeight = dropZoomVIEw.getMeasuredHeight(); } switch (ev.getAction()) { case MotionEvent.ACTION_UP: //手指离开后头部恢复图片 mScaling = false; replyImage(); // 手指松开尾部恢复 if (isNeedAnimation()) { animation(); isCount = false; } clear0(); break; //这里头尾分开处理,互不干扰 case MotionEvent.ACTION_MOVE: //尾部处理 final float preY = y;// 按下时的y坐标 float NowY = ev.getY();// 时时y坐标 int deltaY = (int) (preY - NowY);// 滑动距离 if (!isCount) { deltaY = 0; // 在这里要归0. } y = NowY; // 当滚动到最上或者最下时就不会再滚动,这时移动布局 if (isNeedMove()) { // 初始化头部矩形 if (normal.isEmpty()) { // 保存正常的布局位置 normal.set(inner.getleft(),inner.gettop(),inner.getRight(),inner.getBottom()); } // 移动布局 inner.layout(inner.getleft(),inner.gettop() - deltaY / 2,inner.getBottom() - deltaY / 2); } isCount = true; //尾部处理end //头部处理 if (!mScaling) { if (getScrollY() == 0) { mFirstposition = ev.getY();// 滚动到顶部时记录位置,否则正常返回 } else { break; } } int distance = (int) ((ev.getY() - mFirstposition) * 0.6); // 滚动距离乘以一个系数 if (distance < 0) { // 当前位置比记录位置要小,正常返回 break; } // 处理放大 mScaling = true; setZoom(1 + distance); //头部处理end break; } } /*** * 回缩动画,尾部往下缩动画 */ public voID animation() { // 开启移动动画 TranslateAnimation ta = new TranslateAnimation(0,normal.top); ta.setDuration(200); inner.startAnimation(ta); // 设置回到正常的布局位置 inner.layout(normal.left,normal.top,normal.right,normal.bottom); normal.setEmpty(); } // 是否需要开启动画 public boolean isNeedAnimation() { return !normal.isEmpty(); } // 回d动画,header往上缩动画 (使用了属性动画) public voID replyImage() { final float distance = dropZoomVIEw.getMeasureDWIDth() - dropZoomVIEwWIDth; // 设置动画 ValueAnimator anim = ObjectAnimator.offloat(0.0F,1.0F).setDuration((long) (distance * 0.7)); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @OverrIDe public voID onAnimationUpdate(ValueAnimator animation) { float cVal = (float) animation.getAnimatedValue(); setZoom(distance - ((distance) * cVal)); } }); anim.start(); } //头部缩放 public voID setZoom(float s) { if (dropZoomVIEwHeight <= 0 || dropZoomVIEwWIDth <= 0) { return; } VIEwGroup.LayoutParams lp = dropZoomVIEw.getLayoutParams(); lp.wIDth = (int) (dropZoomVIEwWIDth + s); lp.height = (int) (dropZoomVIEwHeight * ((dropZoomVIEwWIDth + s) / dropZoomVIEwWIDth)); dropZoomVIEw.setLayoutParams(lp); } /*** * 是否需要移动布局 inner.getMeasuredHeight():获取的是控件的总高度 * * getHeight():获取的是屏幕的高度 * * @return */ public boolean isNeedMove() { int offset = inner.getMeasuredHeight() - getHeight(); int scrollY = getScrollY(); // 0是顶部,后面那个是底部 if (scrollY == 0 || scrollY == offset) { return true; } return false; } //清理尾部属性值 private voID clear0() { lastX = 0; lastY = 0; distanceX = 0; distanceY = 0; updownSlIDe = false; } }
下面是我自己使用的一个layout例子:
<?xml version="1.0" enCoding="utf-8"?> <com.kokjuis.travel.customVIEw.BounceZoomScrollVIEw xmlns:androID="http://schemas.androID.com/apk/res/androID" xmlns:imagecontrol="http://schemas.androID.com/apk/res-auto" androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:scrollbars="none"> <!-- <linearLayout androID:ID="@+ID/ui_allchatList_header_relativelayout" androID:layout_wIDth="match_parent" androID:layout_height="45dp" androID:background="@drawable/bar_bg" androID:orIEntation="horizontal" androID:paddingBottom="5dp" androID:paddingtop="5dp"> <button androID:ID="@+ID/ui_allchatList_backbtn" androID:layout_wIDth="wrap_content" androID:layout_height="match_parent" androID:layout_marginBottom="3dp" androID:layout_marginleft="5dp" androID:layout_margintop="3dp" androID:background="@null" androID:gravity="center" androID:text="我" androID:textcolor="@color/white" androID:textSize="18sp" /> </linearLayout> --> <linearLayout androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:orIEntation="vertical"> <relativeLayout androID:layout_wIDth="match_parent" androID:layout_height="250dp" androID:layout_gravity="center_horizontal"> <ImageVIEw androID:layout_wIDth="match_parent" androID:layout_height="match_parent" androID:layout_marginBottom="40dp" androID:background="@drawable/personinfo_bg" /> <com.kokjuis.travel.customVIEw.RoundImageVIEw androID:ID="@+ID/headImage" androID:layout_wIDth="80dp" androID:layout_height="80dp" androID:layout_alignParentBottom="true" androID:layout_centerHorizontal="true" androID:src="@drawable/headimg" imagecontrol:border_insIDe_color="#fff7f2e9" imagecontrol:border_outsIDe_color="#ffd5d1c8" imagecontrol:border_thickness="2dp" /> </relativeLayout> <linearLayout androID:layout_wIDth="match_parent" androID:layout_height="wrap_content" androID:orIEntation="vertical"> <TextVIEw androID:ID="@+ID/name_tv" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_gravity="center_horizontal" androID:layout_margintop="6dp" androID:gravity="center_vertical" androID:text="昵称:" androID:textSize="20sp" /> <TextVIEw androID:ID="@+ID/motto_tv" androID:layout_wIDth="wrap_content" androID:layout_height="40dp" androID:layout_gravity="center_horizontal" androID:gravity="center_vertical" androID:text="座右铭:" androID:textSize="11sp" /> <linearLayout androID:layout_wIDth="150dp" androID:layout_height="wrap_content" androID:layout_gravity="center_horizontal" androID:orIEntation="vertical"> <TextVIEw androID:ID="@+ID/accounts_tv" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_margintop="8dp" androID:gravity="center_vertical" androID:text="帐号:" androID:textSize="12sp" /> <TextVIEw androID:ID="@+ID/gender_tv" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_margintop="2dp" androID:gravity="center_vertical" androID:text="性别:" androID:textSize="12sp" /> </linearLayout> <button androID:ID="@+ID/logout_btn" androID:layout_wIDth="wrap_content" androID:layout_height="wrap_content" androID:layout_gravity="center_horizontal" androID:layout_margintop="20dp" androID:text="注销" /> </linearLayout> </linearLayout> </com.kokjuis.travel.customVIEw.BounceZoomScrollVIEw>
以上所述是小编给大家介绍的AndroID ScrollVIEw 滑到头部或尾部可伸缩放大效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!
总结以上是内存溢出为你收集整理的Android中ScrollView 滑到头部或尾部可伸缩放大效果全部内容,希望文章能够帮你解决Android中ScrollView 滑到头部或尾部可伸缩放大效果所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)