首页 > 学院 > 开发设计 > 正文

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

2019-11-07 22:53:19
字体:
来源:转载
供稿:网友

最近有研究了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

(欢迎关注学习和交流)


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表