Android PullToZoomListView实现放大回弹效果
另外一个相同项目的地址https://github.com/Frank-Zhu/PullZoomView
转自http://blog.csdn.net/wangjinyu501/article/details/38367669
- package com.kince.android.pulltozoomlistview;
- import android.app.Activity;
- import android.content.Context;
- import android.os.SystemClock;
- import android.util.AttributeSet;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.ViewGroup;
- import android.view.animation.Interpolator;
- import android.widget.AbsListView;
- import android.widget.FrameLayout;
- import android.widget.ImageView;
- import android.widget.ListView;
- public class PullToZoomListView extends ListView implements
- AbsListView.OnScrollListener {
- private static final int INVALID_VALUE = -1;
- private static final String TAG = "PullToZoomListView";
- 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;
- private ImageView mShadow;
- private boolean mScrollable = true;
- private boolean mShowHeaderImage = true;
- private boolean mZoomable = true;
- public PullToZoomListView(Context paramContext) {
- super(paramContext);
- init(paramContext);
- }
- public PullToZoomListView(Context paramContext,
- AttributeSet paramAttributeSet) {
- super(paramContext, paramAttributeSet);
- init(paramContext);
- }
- public PullToZoomListView(Context paramContext,
- AttributeSet paramAttributeSet, int paramInt) {
- super(paramContext, paramAttributeSet, paramInt);
- init(paramContext);
- }
- private void endScraling() {
- if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight)
- Log.d("mmm", "endScraling");
- this.mScalingRunnalable.startAnimation(200L);
- }
- private void init(Context paramContext) {
- DisplayMetrics localDisplayMetrics = new DisplayMetrics();
- ((Activity) paramContext).getWindowManager().getDefaultDisplay()
- .getMetrics(localDisplayMetrics);
- this.mScreenHeight = localDisplayMetrics.heightPixels;
- this.mHeaderContainer = new FrameLayout(paramContext);
- this.mHeaderImage = new ImageView(paramContext);
- int i = localDisplayMetrics.widthPixels;
- setHeaderViewSize(i, (int) (9.0F * (i / 16.0F)));
- this.mShadow = new ImageView(paramContext);
- FrameLayout.LayoutParams localLayoutParams = new FrameLayout.LayoutParams(
- -1, -2);
- localLayoutParams.gravity = 80;
- this.mShadow.setLayoutParams(localLayoutParams);
- this.mHeaderContainer.addView(this.mHeaderImage);
- this.mHeaderContainer.addView(this.mShadow);
- addHeaderView(this.mHeaderContainer);
- this.mScalingRunnalable = new ScalingRunnalable();
- super.setOnScrollListener(this);
- }
- private void onSecondaryPointerUp(MotionEvent paramMotionEvent) {
- int i = (paramMotionEvent.getAction()) >> 8;
- Log.d("onSecondaryPointerUp", i + "");
- if (paramMotionEvent.getPointerId(i) == this.mActivePointerId)
- if (i != 0) {
- this.mLastMotionY = paramMotionEvent.getY(1);
- this.mActivePointerId = paramMotionEvent.getPointerId(0);
- return;
- }
- }
- private void reset() {
- this.mActivePointerId = -1;
- this.mLastMotionY = -1.0F;
- this.mMaxScale = -1.0F;
- this.mLastScale = -1.0F;
- }
- public ImageView getHeaderView() {
- return this.mHeaderImage;
- }
- public void hideHeaderImage() {
- this.mShowHeaderImage = false;
- this.mZoomable = false;
- this.mScrollable = false;
- removeHeaderView(this.mHeaderContainer);
- }
- public boolean isScrollable() {
- return this.mScrollable;
- }
- public boolean isZoomable() {
- return this.mZoomable;
- }
- public boolean onInterceptTouchEvent(MotionEvent paramMotionEvent) {
- if (!this.mZoomable) {
- return super.onInterceptTouchEvent(paramMotionEvent);
- }
- switch (paramMotionEvent.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN:
- this.mActivePointerId = paramMotionEvent.getPointerId(0);
- this.mMaxScale = (this.mScreenHeight / this.mHeaderHeight);
- break;
- case MotionEvent.ACTION_UP:
- reset();
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- this.mActivePointerId = paramMotionEvent
- .getPointerId(paramMotionEvent.getActionIndex());
- break;
- case MotionEvent.ACTION_POINTER_UP:
- onSecondaryPointerUp(paramMotionEvent);
- break;
- }
- return super.onInterceptTouchEvent(paramMotionEvent);
- }
- protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2,
- int paramInt3, int paramInt4) {
- super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4);
- if (this.mHeaderHeight == 0)
- this.mHeaderHeight = this.mHeaderContainer.getHeight();
- }
- @Override
- public void onScroll(AbsListView paramAbsListView, int paramInt1,
- int paramInt2, int paramInt3) {
- if (this.mScrollable) {
- Log.d(TAG, "onScroll");
- float f = this.mHeaderHeight - this.mHeaderContainer.getBottom();
- Log.d("onScroll", "f|" + f);
- if ((f > 0.0F) && (f < this.mHeaderHeight)) {
- Log.d("onScroll", "1");
- int i = (int) (0.65D * f);
- this.mHeaderImage.scrollTo(0, -i);
- } else if (this.mHeaderImage.getScrollY() != 0) {
- Log.d("onScroll", "2");
- this.mHeaderImage.scrollTo(0, 0);
- }
- }
- if (this.mOnScrollListener != null) {
- this.mOnScrollListener.onScroll(paramAbsListView, paramInt1,
- paramInt2, paramInt3);
- }
- }
- public void onScrollStateChanged(AbsListView paramAbsListView, int paramInt) {
- if (this.mOnScrollListener != null)
- this.mOnScrollListener.onScrollStateChanged(paramAbsListView,
- paramInt);
- }
- public boolean onTouchEvent(MotionEvent ev) {
- Log.d(TAG, "" + (0xFF & ev.getAction()));
- if (!this.mZoomable) {
- Log.i("zoom", "zoom");
- return super.onTouchEvent(ev);
- }
- switch (ev.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_OUTSIDE:
- case MotionEvent.ACTION_DOWN:
- if (!this.mScalingRunnalable.mIsFinished) {
- this.mScalingRunnalable.abortAnimation();
- }
- this.mLastMotionY = ev.getY();
- this.mActivePointerId = ev.getPointerId(0);
- this.mMaxScale = (this.mScreenHeight / this.mHeaderHeight);
- this.mLastScale = (this.mHeaderContainer.getBottom() / this.mHeaderHeight);
- break;
- case MotionEvent.ACTION_MOVE:
- Log.d("onTouchEvent", "mActivePointerId" + mActivePointerId);
- int j = ev.findPointerIndex(this.mActivePointerId);
- if (j == -1) {
- Log.e("PullToZoomListView", "Invalid pointerId="
- + this.mActivePointerId + " in onTouchEvent");
- } else {
- if (this.mLastMotionY == -1.0F)
- this.mLastMotionY = ev.getY(j);
- if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight) {
- ViewGroup.LayoutParams localLayoutParams = this.mHeaderContainer
- .getLayoutParams();
- float f = ((ev.getY(j) - this.mLastMotionY + this.mHeaderContainer
- .getBottom()) / this.mHeaderHeight - this.mLastScale)
- / 2.0F + this.mLastScale;
- if ((this.mLastScale <= 1.0D) && (f < this.mLastScale)) {
- localLayoutParams.height = this.mHeaderHeight;
- this.mHeaderContainer
- .setLayoutParams(localLayoutParams);
- }
- this.mLastScale = Math.min(Math.max(f, 1.0F),
- this.mMaxScale);
- localLayoutParams.height = ((int) (this.mHeaderHeight * this.mLastScale));
- if (localLayoutParams.height < this.mScreenHeight)
- this.mHeaderContainer
- .setLayoutParams(localLayoutParams);
- this.mLastMotionY = ev.getY(j);
- }
- this.mLastMotionY = ev.getY(j);
- }
- break;
- case MotionEvent.ACTION_UP:
- reset();
- endScraling();
- break;
- case MotionEvent.ACTION_CANCEL:
- break;
- case MotionEvent.ACTION_POINTER_DOWN:
- int i = ev.getActionIndex();
- this.mLastMotionY = ev.getY(i);
- this.mActivePointerId = ev.getPointerId(i);
- break;
- case MotionEvent.ACTION_POINTER_UP:
- onSecondaryPointerUp(ev);
- this.mLastMotionY = ev.getY(ev
- .findPointerIndex(this.mActivePointerId));
- break;
- }
- return super.onTouchEvent(ev);
- }
- public void setHeaderViewSize(int paramInt1, int paramInt2) {
- if (!this.mShowHeaderImage) {
- return;
- }
- Object localObject = this.mHeaderContainer.getLayoutParams();
- if (localObject == null)
- localObject = new AbsListView.LayoutParams(paramInt1, paramInt2);
- ((ViewGroup.LayoutParams) localObject).width = paramInt1;
- ((ViewGroup.LayoutParams) localObject).height = paramInt2;
- this.mHeaderContainer
- .setLayoutParams((ViewGroup.LayoutParams) localObject);
- this.mHeaderHeight = paramInt2;
- }
- public void setOnScrollListener(
- AbsListView.OnScrollListener paramOnScrollListener) {
- this.mOnScrollListener = paramOnScrollListener;
- }
- public void setScrollable(boolean paramBoolean) {
- if (!this.mShowHeaderImage) {
- return;
- }
- this.mScrollable = paramBoolean;
- }
- public void setShadow(int paramInt) {
- if (!this.mShowHeaderImage) {
- return;
- }
- this.mShadow.setBackgroundResource(paramInt);
- }
- public void setZoomable(boolean paramBoolean) {
- if (!this.mShowHeaderImage) {
- return;
- }
- this.mZoomable = paramBoolean;
- }
- class ScalingRunnalable implements Runnable {
- long mDuration;
- boolean mIsFinished = true;
- float mScale;
- long mStartTime;
- ScalingRunnalable() {
- }
- public void abortAnimation() {
- this.mIsFinished = true;
- }
- public boolean isFinished() {
- return this.mIsFinished;
- }
- public void run() {
- float f2;
- ViewGroup.LayoutParams localLayoutParams;
- if ((!this.mIsFinished) && (this.mScale > 1.0D)) {
- float f1 = ((float) SystemClock.currentThreadTimeMillis() - (float) this.mStartTime)
- / (float) this.mDuration;
- f2 = this.mScale - (this.mScale - 1.0F)
- * PullToZoomListView.sInterpolator.getInterpolation(f1);
- localLayoutParams = PullToZoomListView.this.mHeaderContainer
- .getLayoutParams();
- if (f2 > 1.0F) {
- Log.d("mmm", "f2>1.0");
- localLayoutParams.height = PullToZoomListView.this.mHeaderHeight;
- localLayoutParams.height = ((int) (f2 * PullToZoomListView.this.mHeaderHeight));
- PullToZoomListView.this.mHeaderContainer
- .setLayoutParams(localLayoutParams);
- PullToZoomListView.this.post(this);
- return;
- }
- this.mIsFinished = true;
- }
- }
- public void startAnimation(long paramLong) {
- this.mStartTime = SystemClock.currentThreadTimeMillis();
- this.mDuration = paramLong;
- this.mScale = ((float) (PullToZoomListView.this.mHeaderContainer
- .getBottom()) / PullToZoomListView.this.mHeaderHeight);
- this.mIsFinished = false;
- PullToZoomListView.this.post(this);
- }
- }
- }
关于这个控件的实现原理可以自行参考上面链接的文章,里面已经有较为细致的讲解,此处不再赘述。实现的效果就是下面这样:
Android PullToZoomListView实现放大回弹效果的更多相关文章
- Android -- 自定义ScrollView实现放大回弹效果
1,刚刚在别人开源的项目中看到了一个挺不错的用户体验,效果图如下: 2,那下面我们就来实现一下,首先看一下布局,由于一般只是我们包含头像的那部分方法,所以这里我们要把布局分成两部分,对应的布局文件效果 ...
- 顶部图片放大回弹效果Scrollview ---- 各应用中常见的自定义View 解析
原理并不难. 代码量也不大. 非常简洁 . 先来个效果图 再上一波代码. public class SpecialScrollView extends ScrollView implements ...
- Android仿IOS回弹效果 ScrollView回弹 总结
Android仿IOS回弹效果 ScrollView回弹 总结 应项目中的需求 须要仿IOS 下拉回弹的效果 , 我在网上搜了非常多 大多数都是拿scrollview 改吧改吧 试了一些 发现总 ...
- Android 图片的放大缩小拖拉
package com.example.ImageView; import android.annotation.SuppressLint; import android.content.Contex ...
- ScrollView的阻尼回弹效果实现(仿qq空间)
玩过新浪微博,qq空间等手机客户端的童鞋,都应该清楚,在主界面向下滑动时,会有一个阻尼回弹效果,看起来挺不错,接下来我们就来实现一下这种效果,下拉后回弹刷新界面,先看效果图: 这个是编辑器里面的界面效 ...
- ScrollView的顶部下拉和底部上拉回弹效果
要实现ScrollView的回弹效果,需要对其进行触摸事件处理.先来看一下简单的效果: 根据Android的View事件分发处理机制,下面对dispatchTouchEvent进行详细分析: 在加载布 ...
- Android RecyclerView 实现支付宝首页效果
Android RecyclerView 实现支付宝首页效果 [TOC] 虽然我本人不喜欢支付宝的,但是这个网格本身其实还是不错的,项目更新中更改了一个布局为网格模式,类似支付宝.(估计是产品抄袭的= ...
- 移动端页面 弹出框滚动,底部body锁定,不滚动 / 微信网页禁止回弹效果
需求:页面有弹出层菜单,当弹出层菜单超出屏幕可视区域时,不能滚动.加上滚动后,底部body的滚动事件如何禁止,加上了overflow:hidden;还是不可用. 如下图:地区弹出框可以滚动,而底部的b ...
- 在android中用跑马灯的效果显示textview
大家好,在我们通常的android project中,通常需要用到textview这一个布局文件,并且对于这一个显示布局所需要的文本文字内容. 下面我们就来介绍一种方法来实现在android中用跑马灯 ...
随机推荐
- java io流之字符流
字符流 在程序中一个字符等于两个字节,那么java提供了Reader.Writer两个专门操作字符流的类. 字符输出流:Writer Writer本身是一个字符流的输出类,此类的定义如下: publi ...
- js Function.call
提到上述的概念之前,首先想说说javascript中函数的隐含参数:arguments Arguments 该对象代表正在执行的函数和调用它的函数的参数. [function.]arguments ...
- MSSQLSERVER服务无法启动的解决方案
MSSQLSERVER服务无法启动的解决方案 有时候sqlserver无法启动了,原因是mssqlserver服务没有启动,当你手动启动时,又出现服务无法响应的可恶错误提示... 笔者“有幸”遇到了, ...
- PHP移动文件指针ftell()、fseek()、rewind()总结
在对文件进行读写过程中,有时需要在文件中跳转.同不同位置读取,以及将数据写入到不同的位置.例如,使用文件模拟数据库保存数据,就需要移动文件指针.指针的位置是以从文件头开始的字节数度量的,默认以不同模式 ...
- Spring SpringMVC和Mybatis整合
1.引入所要的jar包 2.创建Mybatis的sqlMapConfig.xml配置文件,该文件中可以配置mybaits的相关参数,数据源不在这里配置. <?xml version=" ...
- Robot Framework入门学习2 创建第一个测试用例
本文章部分内容引自以下网址,感谢作者的辛苦分享 http://www.cnblogs.com/fnng/p/3871712.html http://blog.csdn.net/tulituqi/art ...
- 拓扑排序(topsort)
本文将从以下几个方面介绍拓扑排序: 拓扑排序的定义和前置条件 和离散数学中偏序/全序概念的联系 典型实现算法解的唯一性问题 Kahn算法 基于DFS的算法 实际例子 取材自以下材料: http://e ...
- Linux网络栈下两层实现
http://www.cnblogs.com/zmkeil/archive/2013/04/18/3029339.html 1.1简介 VLAN是网络栈的一个附加功能,且位于下两层.首先来学习Linu ...
- aa4
// 初始化地图 var BMapExt = new BMapExtension(domMain, BMap, require('echarts'), require('zrender')); var ...
- 《CODE》书摘
2016-11-08 14:59:16 可以说英语词汇就是一种编码. 2016-11-08 15:19:04 实际上任何两种不同的东西经过一定的组合都可以代表任何种类的信息. 2016-11-08 1 ...