下拉放大及回弹效果

下拉放大及回弹效果

   ONE Goal,ONE Passion !

我们更多地看到下拉放大,松手回弹的效果在个人中心头像布局页面使用.向下滑动的时候.头像照片会放大,松手时又会回弹回原来的大小.效果就如下:
这里写图片描述


第一:实现原理(以ListView为例)

1,当下拉时,重新设置顶部布局(一般背景为图片)的布局参数,我们只需要改变height就ok了.
2,当松开手指时,将布局参数重新设置为原来的默认值.

第二:自定义view实现
 public class SpringListView extends ListView {

    private ImageView mImageView;  // 头布局image
    int mOriginalHeight; //原始高度(圆图片的高度)
    int mSettingHeight;   //布局设置高度

    float MRATIO = 3f;   //手指滑动距离 X  让图像高度变大 (X / 3f).高度


    public SpringListView(Context context) {
        this(context, null);
    }

    public SpringListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SpringListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * 拿到header image的高度
     *
     * @param view
     */
    public void setHeardView(ImageView view) {
        this.mImageView = view;

        mSettingHeight = mImageView.getHeight();
        mOriginalHeight = mImageView.getDrawable().getIntrinsicHeight();

    }

    /**
     * @param deltaX         x方向瞬间变化量  顶部下拉为  -  .
     * @param deltaY
     * @param scrollX        x方向变化量
     * @param scrollY
     * @param scrollRangeX   x方向滑动范围
     * @param scrollRangeY
     * @param maxOverScrollX x方向最大滑动范围
     * @param maxOverScrollY
     * @param isTouchEvent   如果是手指滑动的话true,惯性滑动为false.
     * @return
     */
    @Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {


        if (deltaY < 0 && isTouchEvent) {


            if (mImageView.getHeight() <= mOriginalHeight) {   //头布局没有完全显示出来

                int cCurrentHeight = (int) (mImageView.getHeight() + Math.abs(deltaY / MRATIO));


                //改变头布局高度
                mImageView.getLayoutParams().height = cCurrentHeight;
                mImageView.requestLayout();
            }

        }


        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);

    }


    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:


                //抬起时 图片高度.
                int startHeight = mImageView.getHeight();

                int endHeight = mSettingHeight;


                startAnim(startHeight, endHeight);

                break;
        }

        //此次不能返回 true.  如果返回true的话,那么overScrollBy将不会执行了.因为overScrollBy
       // 的调用必须经过onTouchEvent中调用的.
        return super.onTouchEvent(ev);
    }

    /**
     * 执行回弹动画
     *
     * @param startHeight 动画的开始位置
     * @param endHeight   动画的结束位置
     */
    private void startAnim(final int startHeight, final int endHeight) {


        ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                // 动画执行的的比例进度
                float fraction = (float) animation.getAnimatedValue();

                // 瞬间应该回弹的距离
                float winkDis = (float) (fraction * (startHeight - endHeight));

                //设置mImageView的高度.
                mImageView.getLayoutParams().height = (int) (startHeight - winkDis);
                mImageView.requestLayout();

            }
        });

        animator.setDuration(1000);

        /**
         *   设置插值器
         *   之所以设置不同插值器后,会有不同效果.是因为
         *   插值器会改变fraction(估值器中的比例)的值.
         */

        animator.setInterpolator(new BounceInterpolator());
        animator.start();

    }


    }

第三:跑起来
 public class SpringActivity extends AppCompatActivity {

    private SpringListView lv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_spring);
        initView();
    }

    private void initView() {
        lv = (SpringListView) findViewById(R.id.lv);
    //    lv.setOverScrollMode(View.OVER_SCROLL_NEVER);
        // 加Header
        final View mHeaderView = View.inflate(this, R.layout.view_header, null);
        final ImageView mImage = (ImageView) mHeaderView.findViewById(R.id.iv);
        lv.addHeaderView(mHeaderView);


        // 填充数据
        lv.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, MyData.NAMES));



        mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

            @Override
            public void onGlobalLayout() {
                // 当布局填充结束之后, 此方法会被调用

                lv.setHeardView(mImage);

                mHeaderView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }

    }
第四:别担心,资源文件已经准备好了.

头部局 : R.layout.view_header

  <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:scaleType="centerCrop"
        android:src="@drawable/parallax_img" />

    </LinearLayout>

页面布局 : R.layout.activity_spring

 <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context="com.example.customview.activity.SpringActivity">

    <com.example.customview.view.SpringListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </com.example.customview.view.SpringListView>
    </RelativeLayout>

欢迎走进重温经典:

  public class MyData {
    public static final String[] NAMES = new String[]{"宋江", "卢俊义", "吴用",
            "公孙胜", "关胜", "林冲", "秦明", "呼延灼", "花荣", "柴进", "李应", "朱仝", "鲁智深",
            "武松", "董平", "张清", "杨志", "徐宁", "索超", "戴宗", "刘唐", "李逵", "史进", "穆弘",
            "雷横", "李俊", "阮小二", "张横", "阮小五", " 张顺", "阮小七", "杨雄", "石秀", "解珍",
            " 解宝", "燕青", "朱武", "黄信", "孙立", "宣赞", "郝思文", "韩滔", "彭玘", "单廷珪",
            "魏定国", "萧让", "裴宣", "欧鹏", "邓飞", " 燕顺", "杨林", "凌振", "蒋敬", "吕方",
            "郭 盛", "安道全", "皇甫端", "王英", "扈三娘", "鲍旭", "樊瑞", "孔明", "孔亮", "项充",
            "李衮", "金大坚", "马麟", "童威", "童猛", "孟康", "侯健", "陈达", "杨春", "郑天寿",
            "陶宗旺", "宋清", "乐和", "龚旺", "丁得孙", "穆春", "曹正", "宋万", "杜迁", "薛永", "施恩",
            "周通", "李忠", "杜兴", "汤隆", "邹渊", "邹润", "朱富", "朱贵", "蔡福", "蔡庆", "李立",
            "李云", "焦挺", "石勇", "孙新", "顾大嫂", "张青", "孙二娘", " 王定六", "郁保四", "白胜",
            "时迁", "段景柱"};
}

ok! 下来回弹效果已经完成了.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值