仿QQ空间打造可拉伸头部组件

仿QQ空间打造可拉伸头部组件

本章没有什么难点和技术点,主要是大晚上的没啥事写着玩 -.-
首先先上一个效果图
这里写图片描述

全代码文件不超过150行 所以说超简单~ ~(当然前提是布局简单 只写了一个类似的效果而已)

进入正题
下面是布局文件得xml

<?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:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.administrator.qqzone.MainActivity">
    <com.example.administrator.qqzone.MyPullList
        android:id="@+id/main_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></com.example.administrator.qqzone.MyPullList>
</RelativeLayout>

这里的MyPullList是自定义的listView
下面是头部的xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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/head_img"
        android:layout_width="match_parent"
        android:layout_height="@dimen/head_img_defualt_size_dp"
        android:scaleType="centerCrop"
        android:src="@mipmap/dog" />

    <ImageView
        android:id="@+id/head_leftimg"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="30dp"
        android:layout_marginLeft="30dp"
        android:scaleType="centerCrop"
        android:src="@mipmap/tz" />
</RelativeLayout>

布局文件已经写完 在适配数据源之前我们先把这个自定义ListView写出来

public class MyPullList extends ListView {
    public MyPullList(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        mImageViewHeigth = context.getResources().getDimensionPixelOffset(R.dimen.head_img_defualt_size_dp);
    }

适配数据源不在做过多解释 贴代码看就行

public class MainActivity extends AppCompatActivity {

    private MyPullList mainlist;
    private View headView;
    private ImageView iv;
    private ImageView leftIv;
    private List<String> list;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.mainlist = (MyPullList) findViewById(R.id.main_list);
        headView = View.inflate(this, R.layout.listview_head, null);
        iv = (ImageView) headView.findViewById(R.id.head_img);
        leftIv = (ImageView) headView.findViewById(R.id.head_leftimg);
        //消除阴影
        mainlist.setOverScrollMode(View.OVER_SCROLL_NEVER);
        initData();
        mainlist.setImageBig(iv);

    }

    private void initData() {
        list = new ArrayList<>();
        for (int i = 0; i < 26; i++) {
            list.add("嗯哼嗯哼蹦擦擦~" + (i + 1));
        }
        initAdapter();
    }

    private void initAdapter() {
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
        mainlist.addHeaderView(headView);
        mainlist.setAdapter(adapter);
    }
}

14行的head是我们要添加的头部 接下来的效果也只要是针对头部的
我们在initAdapter()方法中将头部添加进去 然后setAdapter
接下来主要在自定义的listView中做操作
首先我们需要重写overScrollBy方法监听滑动的事件

@Override
    protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY, int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY, boolean isTouchEvent) {
    //这里的deltaY代表的是Y偏移量
        if (deltaY < 0) {
        //这里将图片的高度变大  为什么deltaY要除2呢? 是因为防止用户从头拉到底部 图片高度过大不好看
            mIv.getLayoutParams().height = mIv.getHeight() - deltaY / 2;
            mIv.requestLayout();
        } else {
            //这里的代码是当你上滑的时候缩放图片的
            if (mIv.getHeight() > mImageViewHeigth) {
                mIv.getLayoutParams().height = mIv.getHeight() + deltaY / 2;
                mIv.requestLayout();
            }
        }
        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);
    }

接着要重写onScrollChanged方法

 @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        //让Imageview上滑时放大监听
        View head = (View) mIv.getParent();
        //拿到父容器与顶部的高度
        if (head.getTop() < 0 && mIv.getHeight() > mImageViewHeigth) {
            mIv.getLayoutParams().height = mIv.getHeight() + head.getTop();
            head.layout(head.getLeft(), 0, head.getRight(), head.getHeight());
            mIv.requestLayout();
        }
        super.onScrollChanged(l, t, oldl, oldt);
    }

主要的作用与父容器与顶部的距离 这里有一个mImageViewHeigth的变量是什么意思呢? 他代表的是图片的初始高度 我定义在了成员变量内
最后需要重写的是onTouchEvent方法

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
    //注意  这里只监听了ACTION_UP方法  是因为只有当用户抬起手指的时候才会让顶部回弹
        switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
            //自定义了一个动画  下面直接贴代码
                ResetAnimation animation = new ResetAnimation(mIv, mImageViewHeigth);
                animation.setDuration(300);
                mIv.startAnimation(animation);
                break;
        }
        return super.onTouchEvent(ev);
    }

动画代码————>

class ResetAnimation extends Animation {

        private ImageView iv;
        private int targetHeigth; //最终恢复的高度
        private final int height;
        private final int endHeigth;
        //这个iv的参数也许用不到  可加可不加
        public ResetAnimation(ImageView iv, int targetHeigth) {
            this.iv = iv;
            this.targetHeigth = targetHeigth;
            this.height = mIv.getHeight();
            this.endHeigth = height - targetHeigth;
        }
 @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            //不断调用  这个的代码比较关键  当手指抬起回调动画方法的时候这个方法是会被一直调用的
            mIv.getLayoutParams().height = (int) (height - endHeigth * interpolatedTime);
            mIv.requestLayout();
            super.applyTransformation(interpolatedTime, t);
        }

基本代码就只有这一些
github地址

https://github.com/Huazhiling/DivQQZone

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值