Android PullToZoomListView實現放大回彈效果

來源:互聯網
上載者:User

標籤:prot   nbsp   group   com   ini   src   pack   min   .net   

版本號碼:1.0 日期:2014.8.4著作權:? 2014 kince 轉載註明出處
  之前看過一篇文章,連結是:能夠下拉縮放HeaderView的ListView:PullToZoomInListView。

說的就是PullToZoomListView。只是這篇文章有個地方須要勘誤,就是PullToZoomListView這個控制項儘管是github上一個開源項目。只是最美應用並非使用這個開源項目,而是這個開源項目反編譯了最美應用的代碼。

  可是,它這個代碼是有問題的,當手指在螢幕上滑動的時候會引發onItemClick事件。

看了一下它的代碼。發現是由於在onTouchEvent()方法中的MotionEvent.ACTION_MOVE中return true了,這樣就會消費這個事件。所以導致了onItemClick事件。

之後我也反編譯了一下最美應用,看了一下這個控制項的實現,發現還有其它問題,比方少了一些變數,沒有重寫onInterceptTouchEvent()方法等。因此我又自己動手把這個控制項豐富了一下。使其能夠最大限度的接近原始代碼。並且可正常使用。改動後代碼例如以下:

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 implementsAbsListView.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();}@Overridepublic 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);}}}
  關於這個控制項的實現原理能夠自行參考上面連結的文章,裡面已經有較為仔細的解說,此處不再贅述。

實現的效果就是以下這樣:

  github連結:https://github.com/wangjinyu501/PullToZoomListView/,假設您發現了不論什麼問題。能夠在文章以下留言,我會第一時間處理。歡迎交流。

Android PullToZoomListView實現放大回彈效果

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.