最近有研究了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
微信公众号:终端研发部
(欢迎关注学习和交流)