仿QQ空间之打造个性化可拉伸头部控件

来源:互联网 发布:淘宝老爷爷模特卖裙子 编辑:程序博客网 时间:2024/06/06 12:46

最近有研究了QQ空间可拉伸头部控件的listView。如何去做呢?这里使用了自定义listView的方法。先看效果图吧:

Markdown

究竟如何去做呢?
可以用的方法有:
* 1.继承 extends ViewGrop
* 2.RecycleView +Behavior+CoordinateLayout
* 3.ViewGroup 组合控件
* 4.ListView + headView

这次我们主要用原生的自定义listView去做。
- 1.extends 继承 ListView
- 2.监听过度监听,在缩放头部图片重写overScrollBy方法
- 重写onScrollChanged方法监听度放大时,执行缩小图片
- 重写onTouchEvent方法,执行触摸时释放事件的处理

/** * 类功能描述:</br> *  仿QQ空间之打造个性化可拉伸头部控件</br> * @author yuyahao * @version 1.0 </p> 修改时间:</br> 修改备注:</br> */public class CustomerScrollZoomListView extends ListView{    private ImageView imageView;    private int mMeasureWeight;    public CustomerScrollZoomListView(Context context, AttributeSet attrs) {        super(context, attrs);         mMeasureWeight = context.getResources().getDimensionPixelSize(R.dimen.dp200);    }    public CustomerScrollZoomListView(Context context) {        super(context);    }    public void setZoomImageView(ImageView iView ){         imageView = iView;    }    @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){//下拉过度  对图片进行放大            imageView.getLayoutParams().height = imageView.getHeight() - deltaY;            imageView.requestLayout();        }else{//上拉过度时            imageView.getLayoutParams().height = imageView.getHeight() - deltaY;            imageView.requestLayout();        }        LogUtil.i("yuyahao","deltaY:  "+deltaY);        return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY, maxOverScrollX, maxOverScrollY, isTouchEvent);    }    @Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        //只有当imageView过度放大时,这里才会去执行缩小        View view = (View) imageView.getParent();        int detalY = view.getTop();//此时 detay 为负值       if(imageView.getHeight() > mMeasureWeight){//如果当前图片的高度 > 初始高度            imageView.getLayoutParams().height = imageView.getHeight() + detalY;            imageView.requestLayout();        }        LogUtil.i("yuyahao","----   deltaY:  "+detalY);        super.onScrollChanged(l, t, oldl, oldt);    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()){            case MotionEvent.ACTION_UP://松手释放时                MyCustomserAnimation myCustomserAnimation = new MyCustomserAnimation(mMeasureWeight);                myCustomserAnimation.setDuration(300);                myCustomserAnimation.setInterpolator(new BounceInterpolator());                imageView.startAnimation(myCustomserAnimation);                break;        }        return super.onTouchEvent(ev);    }    public class MyCustomserAnimation extends Animation{        private int delay ;//高度差        private int currentHeight ; //当前的高度        public MyCustomserAnimation( int targetHeight){            //this.delay = delay;            delay = imageView.getHeight()  - targetHeight;            currentHeight =  imageView.getHeight();        }        @Override        protected void applyTransformation(float interpolatedTime, Transformation t) {            imageView.getLayoutParams().height = (int) (currentHeight  - delay * interpolatedTime);            imageView.requestLayout();            super.applyTransformation(interpolatedTime, t);        }    }}

这里重写了overScrollBy方法
这里源码是怎么说的呢?

  /**     * This is called in response to an internal scroll in this view (i.e., the     * view scrolled its own contents). This is typically as a result of     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been     * called.     *     * @param l Current horizontal scroll origin.     * @param t Current vertical scroll origin.     * @param oldl Previous horizontal scroll origin.     * @param oldt Previous vertical scroll origin.     */    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        notifySubtreeAccessibilityStateChangedIfNeeded();        if (AccessibilityManager.getInstance(mContext).isEnabled()) {            postSendViewScrolledAccessibilityEventCallback();        }        mBackgroundSizeChanged = true;        if (mForegroundInfo != null) {            mForegroundInfo.mBoundsChanged = true;        }        final AttachInfo ai = mAttachInfo;        if (ai != null) {            ai.mViewScrollChanged = true;        }        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);        }    }

大致意思我们都可以看得出来.大致意思是响应于该视图中的内部滚动而调用的(即视图滚动其自己的内容)比如:eltaY < 0的时候下拉过度 对图片进行放大。 小于0时,上拉过度。

日前google上搜索“android overscroll”,对此效果的介绍很多,但关于其具体使用方式和实现,则很少涉及,偶有提及,也经常答非所问或似是而非,反而误导了别人。于是我查阅了android相关源码,并做了一些测试,在此讲讲我的理解。

首先是overscroll功能本身。
- 在最顶层的View类提供了支持,可通过setOverScrollMode函数控制其出现条件。但其实View中并没有实现overscroll功能,
- 提供了一个辅助函数overScrollBy,该函数根据overScrollMode和内容是否需要滚动控制最大滚动范围。
- 最后将计算结果传给onOverScrolled实现具体的overscroll功能
- 但此函数在View类中是全空的
overscroll功能真正的实现分别在ScrollView、AbsListView、HorizontalScrollView和WebView中各有一份,代码基本一样。
- 以ScrollView为例,它在处理笔点移动消息时调用overScrollBy来滚动视图,然后重载了overScrollBy函数来实现具体功能,其位置计算通过OverScroller类实现。
- OverScroller作为一个计算引擎,应该是一个独立的模块,具体滚动效果和范围都不可能通过它来设置,我觉得没有必要细看。但滚动位置最终是它给出的,那相关数据肯定要传递给它。
- 回头看overScrollBy函数,它有两个控制overScroll出界范围的参数,几个实现里面都是取自ViewConfiguration.getScaledOverscrollDistance,而这个参数的值在我的源码中都是0,而且我没找到任何可以影响其结果的设置。

Activity中的代码:

/** * 类功能描述:</br> *  仿QQ空间之打造个性化可拉伸头部控件</br> * @author yuyahao * @version 1.0 </p> 修改时间:</br> 修改备注:</br> */public class CustomerScrollZoomListViewActivity extends BaseActivity{    @Bind(R.id.lv_customser_zoomscroll)    CustomerScrollZoomListView lv_customser_zoomscroll;    private List<Student> list = new ArrayList<>();    private ZoomScrollListViewAdapter zoomScrollListViewAdapter;    private View headView;    @Override    protected void initData() {        setContentView(R.layout.activity_customerscrollzoomlistview);        ButterKnife.bind(this);        list.addAll(ServiceData.getStudentList());        zoomScrollListViewAdapter = new ZoomScrollListViewAdapter(CustomerScrollZoomListViewActivity.this,list,R.layout.item_xzoomscrollview);        headView = LayoutInflater.from(CustomerScrollZoomListViewActivity.this).inflate(R.layout.zoom_headview,null);        ImageView iamgeView = (ImageView) headView.findViewById(R.id.iv_zoom_head);        lv_customser_zoomscroll.setZoomImageView(iamgeView);        lv_customser_zoomscroll.addHeaderView(headView);        lv_customser_zoomscroll.setAdapter(zoomScrollListViewAdapter);    }}

xml布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical" android:layout_width="match_parent"    android:layout_height="match_parent">    <com.yolo.myapplication.activity.view.CustomerScrollZoomListView        android:layout_width="match_parent"        android:layout_height="match_parent"        android:id="@+id/lv_customser_zoomscroll"        /></LinearLayout>

adapter适配器

public class ZoomScrollListViewAdapter extends CommonAdapter<Student> {    private Context context;    public ZoomScrollListViewAdapter(Context context, List<Student> listDatas, int layoutId) {        super(context, listDatas, layoutId);        this.context = context;    }    @Override    protected void fillData(ViewHolder holder, int position) {        TextView actNum = holder.getView(R.id.team_item_active_num);        TextView time = holder.getView(R.id.team_item_time);        TextView title = holder.getView(R.id.team_item_title);        ImageView icon = holder.getView(R.id.team_item_icon);        Student item = listDatas.get(position);        actNum.setText(String.valueOf(item.getList().size()) + "");        time.setText(String.valueOf(item.getList().get(0).getPerListenceName()) + "");        title.setText(item.getName());    }}

adapter适配器请参考:
教你打造一个万能的适配器
item:布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal" android:layout_width="match_parent"    android:gravity="center_vertical"    android:layout_height="match_parent">    <ImageView        android:layout_width="@dimen/dp80"        android:layout_height="@dimen/dp80"        android:background="@drawable/img2"        android:scaleType="fitXY"        android:id="@+id/team_item_icon"/>    <LinearLayout        android:layout_width="match_parent"        android:layout_marginLeft="@dimen/dp10"        android:orientation="vertical"        android:layout_height="@dimen/dp80">        <TextView            android:layout_width="match_parent"            android:layout_height="match_parent"            android:id="@+id/team_item_title"            android:gravity="center_vertical"            android:layout_weight="1"            android:text="卡卡罗特"/>        <LinearLayout            android:layout_width="match_parent"            android:layout_weight="1"            android:layout_height="match_parent"            android:gravity="center_vertical">            <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="天不排名"                android:id="@+id/team_item_time"/>            <TextView                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginLeft="@dimen/dp20"                android:text="战斗值: "                android:id="@+id/team_item_active_num"/>        </LinearLayout>    </LinearLayout></LinearLayout>

项目源码地址:MyZoomListView.rar

如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
微信公众号:终端研发部
Markdown

(欢迎关注学习和交流)

2 0
原创粉丝点击