仿QQ空间之打造个性化可拉伸头部控件
来源:互联网 发布:淘宝老爷爷模特卖裙子 编辑:程序博客网 时间:2024/06/06 12:46
最近有研究了QQ空间可拉伸头部控件的listView。如何去做呢?这里使用了自定义listView的方法。先看效果图吧:
究竟如何去做呢?
可以用的方法有:
* 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
微信公众号:终端研发部
(欢迎关注学习和交流)
- 仿QQ空间之打造个性化可拉伸头部控件
- 仿QQ空间之打造个性化可拉伸头部控件
- 打造QQ个性化可拉伸头部控件
- android打造仿qq控件可拉伸头部控件
- 仿QQ空间打造可拉伸头部组件
- 可拉伸头部控件
- 仿QQ空间头部下拉放大控件
- QQ空间头部图片可拉伸的ListView效果
- 打造QQ空间头部视差ListView
- 打造QQ空间头部视差ListView
- 仿QQ空间下拉头部缩放
- 安卓开发之Kotlin和java双实现仿qq空间下拉图片拉伸
- 头部视觉视差(仿QQ控件下拉效果)
- iOS开发010 tableView头部拉伸效果(类似QQ空间)
- 彷QQ空间图片拉伸展示—头部视差效果Parallax
- JS选中样式,仿QQ空间自定义空间头部选择样式(9元包邮)
- 可拉伸的tabview头部视图
- 自定义控件之DragLayout仿QQ界面
- c++基础
- 我的第一次博客
- Maven管理SSM框架的pom.xml文件配置(自动下载所依赖的jar包)
- 任务控制块
- C++ FLAPPED BIRD
- 仿QQ空间之打造个性化可拉伸头部控件
- UVALive5461 UVA615 POJ1308 Is It A Tree?(解法二)
- No resource identifier found for attribute 'showAsAction' in package 'XXX'
- 使用 Vagrant 来管理 DigitalOcean 云主机
- Maven使用笔记(六)使用Maven进行多模块拆分
- SPOJ NETADMIN 最大流
- Okhttp获取中文网页乱码的解决方式
- Maven 学习(二)maven命令
- 5 个最常见的 Linux故障问题