轮子怎么造---可以下拉缩放HeaderView的ListView:PullToZoomInListView
来源:互联网 发布:网络发展阶段 编辑:程序博客网 时间:2024/05/22 05:31
github地址如下:https://github.com/matrixxun/PullToZoomInListView
原理:
PullToZoomListView的实现原理主要是自定义ListView,在ListView中对监听手势,当MotionEvent为MotionEvent.ACTION_MOVE的时候,去判断向下滑动的偏移量,根据这个来改变headerView内容区域的高度,并且在手指放开的那一刻,停止缩放,启用一个动画来使HeaderView平滑的恢复到放大之前的状态。
先来理清Android坐标和偏移量
http://blog.csdn.net/lvxiangan/article/details/19971509
http://www.jb51.net/article/77546.htm这两篇文章都写的不错的。
//获取屏幕区域的宽高等尺寸获取DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);int widthPixels = metrics.widthPixels;int heightPixels = metrics.heightPixels;//应用程序App区域宽高等尺寸获取Rect rect = new Rect();getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);//获取状态栏高度Rect rect= new Rect();getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);int statusBarHeight = rectangle.top;//View布局区域宽高等尺寸获取Rect rect = new Rect();getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);
自定义listView的代码:
public class MyListView extends ListView implements AbsListView.OnScrollListener { private static final Interpolator sInterpolator = new Interpolator() { public float getInterpolation(float paramAnonymousFloat) { float f = paramAnonymousFloat - 1.0F; return 1.0F + f * (f * (f * (f * f))); } }; int mActivePointerId = -1; private FrameLayout mHeaderContainer; private int mHeaderHeight; private ImageView mHeaderImage; float mLastMotionY = -1.0F; float mLastScale = -1.0F; float mMaxScale = -1.0F; private AbsListView.OnScrollListener mOnScrollListener; private ScalingRunnalable mScalingRunnalable; private int mScreenHeight; public MyListView(Context context) { super(context); init(context); } public MyListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public MyListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); } @Override public void onScroll(AbsListView paramAbsListView, int paramInt1, int paramInt2, int paramInt3) { // Log.d("mmm", "onScroll"); float f = mHeaderHeight - mHeaderContainer.getBottom();// Log.d("mmm", "f|" + f); if ((f > 0.0F) && (f < mHeaderHeight)) {// Log.d("mmm", "1"); int i = (int) (0.65D * f); mHeaderImage.scrollTo(0, -i); } else if (mHeaderImage.getScrollY() != 0) {// Log.d("mmm", "2"); mHeaderImage.scrollTo(0, 0); } if (mOnScrollListener != null) { mOnScrollListener.onScroll(paramAbsListView, paramInt1, paramInt2, paramInt3); } } public void onScrollStateChanged(AbsListView paramAbsListView, int paramInt) { if (mOnScrollListener != null) mOnScrollListener.onScrollStateChanged(paramAbsListView, paramInt); } private void init(Context context){ DisplayMetrics localDisplayMetrics = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay() .getMetrics(localDisplayMetrics); mScreenHeight = localDisplayMetrics.heightPixels; mHeaderContainer = new FrameLayout(context); mHeaderImage = new ImageView(context); int i = localDisplayMetrics.widthPixels; setHeaderViewSize(i, (int) (5.0F * (i / 10.0F))); mHeaderContainer.addView(mHeaderImage); addHeaderView(mHeaderContainer); mScalingRunnalable = new ScalingRunnalable(); } public ImageView getHeaderView() { return mHeaderImage; } /** * 设置header的高度 * @param paramInt1 * @param paramInt2 */ public void setHeaderViewSize(int paramInt1, int paramInt2) { Object localObject = mHeaderContainer.getLayoutParams(); if (localObject == null) localObject = new AbsListView.LayoutParams(paramInt1, paramInt2); ((ViewGroup.LayoutParams) localObject).width = paramInt1; ((ViewGroup.LayoutParams) localObject).height = paramInt2; mHeaderContainer .setLayoutParams((ViewGroup.LayoutParams) localObject); mHeaderHeight = paramInt2; } /** * 停止滑动 */ private void endScraling() { if (mHeaderContainer.getBottom() >= mHeaderHeight) mScalingRunnalable.startAnimation(200L); } private void reset() { mActivePointerId = -1; mLastMotionY = -1.0F; mMaxScale = -1.0F; mLastScale = -1.0F; }public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction() & MotionEvent.ACTION_MASK) {//每个手指第一次按下的时候,都被分配了一个独立的ID,一个ID在最终手指离开触摸屏之前或者手势失效之前,会一直有效。//PointerIndex和PointerId是什么。PointerId会被放入一个数组,PointerIndex就是Pointer在数组内的下标,//PointerIndex值从0到getPointerCount()-1,getPointerCount会得到The number of pointers of data contained in this event case MotionEvent.ACTION_DOWN://用户开始触摸. if (!mScalingRunnalable.mIsFinished) { mScalingRunnalable.abortAnimation(); } mLastMotionY = ev.getY();//触摸点相对当前控件的y轴 mActivePointerId = ev.getPointerId(0); mMaxScale = (mScreenHeight / mHeaderHeight); mLastScale = (mHeaderContainer.getBottom() / mHeaderHeight); break; case MotionEvent.ACTION_MOVE://用户在移动(手指或者其他) Log.d("mmm", "mActivePointerId" + mActivePointerId); int j = ev.findPointerIndex(mActivePointerId); if (j == -1) { Log.e("PullToZoomListView", "Invalid pointerId=" + mActivePointerId + " in onTouchEvent"); } else { if (mLastMotionY == -1.0F) mLastMotionY = ev.getY(j); if (mHeaderContainer.getBottom() >= mHeaderHeight) { ViewGroup.LayoutParams localLayoutParams = mHeaderContainer.getLayoutParams(); float f = ((ev.getY(j) - mLastMotionY + mHeaderContainer.getBottom()) / mHeaderHeight - mLastScale) / 2.0F + mLastScale; if ((mLastScale <= 1.0D) && (f < mLastScale)) { localLayoutParams.height = mHeaderHeight; mHeaderContainer.setLayoutParams(localLayoutParams); return super.onTouchEvent(ev); } mLastScale = Math.min(Math.max(f, 1.0F), mMaxScale); localLayoutParams.height = ((int) (mHeaderHeight * mLastScale)); if (localLayoutParams.height < mScreenHeight) mHeaderContainer.setLayoutParams(localLayoutParams); mLastMotionY = ev.getY(j); return true; } mLastMotionY = ev.getY(j); } break; case MotionEvent.ACTION_UP://用户抬起了手指 reset(); endScraling(); break; } return super.onTouchEvent(ev); } class ScalingRunnalable implements Runnable { long mDuration; boolean mIsFinished = true; float mScale; long mStartTime; ScalingRunnalable() { } public void abortAnimation() { mIsFinished = true; } public boolean isFinished() { return mIsFinished; } public void run() { float f2; ViewGroup.LayoutParams localLayoutParams; if ((!mIsFinished) && (mScale > 1.0D)) { float f1 = ((float) SystemClock.currentThreadTimeMillis() - (float) mStartTime) / (float) mDuration; f2 = mScale - (mScale - 1.0F) * sInterpolator.getInterpolation(f1); localLayoutParams = mHeaderContainer.getLayoutParams(); if (f2 > 1.0F) { Log.d("mmm", "f2>1.0"); localLayoutParams.height = mHeaderHeight; localLayoutParams.height = ((int) (f2 * mHeaderHeight)); mHeaderContainer.setLayoutParams(localLayoutParams); post(this); return; } mIsFinished = true; } } /** * 手指下拉停止释放后的动画 * * @param paramLong */ public void startAnimation(long paramLong) { mStartTime = SystemClock.currentThreadTimeMillis(); mDuration = paramLong; //缩小比例 mScale = ((float) (mHeaderContainer.getBottom()) / mHeaderHeight); mIsFinished = false; post(this); } }}
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0627/1625.html这篇文章对
PullToZoomInListView有很好的分析
我觉得,难点在于:改变headerView的高度的时候,下面的listview的item也会跟着移动,我尝试用缩放的动画,属性动画也没有解决,缩放headerview的时候,它是独立的,不能跟listview一起走,源码作者是ScalingRunnalable在startAnimation中调用了PullToZoomListView.this.post(this);post调用ScalingRunnalable的run方法,而ScalingRunnalable run方法中再次调用了post,就这样不断的更新UI,直到达到一定的条件退出这个循环。
不断更新UI是通过重新设置headerView的宽高来实现:
localLayoutParams.height = mHeaderHeight;localLayoutParams.height = ((int) (f2 * mHeaderHeight));mHeaderContainer.setLayoutParams(localLayoutParams);
- 轮子怎么造---可以下拉缩放HeaderView的ListView:PullToZoomInListView
- 可以下拉缩放HeaderView的ListView:PullToZoomInListView
- ListView的headerView下拉刷新PullToZoomInListView分析
- tableView 的headerView下拉缩放
- 不要重复造轮子,但必须知道轮子怎么造的 -----listview实现下拉刷新滚动加载
- 针对ListView item的侧滑删除和支持下拉时HeaderView缩放的ListView、ScrollView
- 关于ListView的HeaderView
- ListView的HeaderView
- [Android]LIstView的HeaderView
- LIstView的HeaderView, FooterView
- Listview的HeaderView
- ListView的HeaderView
- ListView的HeaderView
- ListView的HeaderView
- ListView的HeaderView
- 5.3 ListView的HeaderView
- 关于ListView的HeaderView
- ListView的HeaderView
- org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException 解决办法
- android之适配器使用
- 贝赛尔曲线简介
- AXIS2 参数说明
- poj 3070 Fibonacci(矩阵快速幂模板题)
- 轮子怎么造---可以下拉缩放HeaderView的ListView:PullToZoomInListView
- centos tomcat 搭建https 服务器
- 使用Python
- UITextField 密码明文及密文切换问题
- Layout组件综合训练
- swift调用OC代码和第三方库
- ssm项目中动态Quartz定时任务的实现(定时任务存在表中,而不是在.xml中)
- 动态规划-最优解
- 弧线运动