首页 > 系统 > Android > 正文

Android ListView实现下拉顶部图片变大效果

2019-10-22 18:19:00
字体:
来源:转载
供稿:网友

本文实例为大家分享了Android ListView下拉顶部图片变大的具体代码,供大家参考,具体内容如下

在git上查看牛人的代码,发现是反编译别人的代码,还没加注释,代码也没有完全编译完整,所以这里我做的简单的注释,仅供学习。

变量说明

这里变量包含了:自定义返回动画加速度、自定义动画线程、头部图片view,最后的y坐标,做好的比例,做大的比例等。

private static final String TAG = "PullToZoomListView"; private static final int INVALID_VALUE = -1;//重置值 //自定义加速度动画 private static final Interpolator sInterpolator = new Interpolator() {  public float getInterpolation(float interpolator) {   float f = interpolator - 1.0F;   return 1.0F + f * (f * (f * (f * f)));  } }; private int mActivePointerId = INVALID_VALUE;//当前手指的Id private FrameLayout mHeaderContainer;//头部 private int mHeaderHeight;//头部图片的高度 private ImageView mHeaderImage;//头部图片 float mLastMotionY = INVALID_VALUE;//最后y坐标 float mLastScale = INVALID_VALUE;//最后的比例 float mMaxScale = INVALID_VALUE;//最大的比例 private OnScrollListener mOnScrollListener;//滑动监听 private ScalingRunnalable mScalingRunnalable;//动画线程 private int mScreenHeight;//屏幕高度 private ImageView mShadow;//阴影遮罩

自定义View初始化:设置了头部的头部和遮罩并且设置了监听。

/**  * 初始化  * @param paramContext  */ private void init(Context paramContext) {  DisplayMetrics metrics = new DisplayMetrics();  ((Activity) paramContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);  this.mScreenHeight = metrics.heightPixels;//屏幕高度赋值  this.mHeaderContainer = new FrameLayout(paramContext);//头部  this.mHeaderImage = new ImageView(paramContext);//头部图片  int screenWidth = metrics.widthPixels;//屏幕宽度  //设置头部View的样式 设置屏幕宽度,最大样式高度为屏幕高度的9/16  setHeaderViewSize(screenWidth, (int) (9.0F * (screenWidth / 16.0F)));  this.mShadow = new ImageView(paramContext);//遮罩  FrameLayout.LayoutParams layoutParams =    new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,      ViewGroup.LayoutParams.MATCH_PARENT);  layoutParams.gravity = Gravity.CENTER;  this.mShadow.setLayoutParams(layoutParams);//设置遮罩样式  //头部添加View  this.mHeaderContainer.addView(this.mHeaderImage);  this.mHeaderContainer.addView(this.mShadow);  //添加头部  addHeaderView(this.mHeaderContainer);  //初始化返回动画  this.mScalingRunnalable = new ScalingRunnalable();  //设置监听  super.setOnScrollListener(this); }

开启动画:判断当前的头部布局底部的位置–是否大于图片的初始化高度。

/**  * 开启动画  */ private void endScraling() {  if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight) {   Log.d(TAG, "this.mScalingRunnalable.startAnimation(200L)");   this.mScalingRunnalable.startAnimation(200L);  } }

多指触碰时将第0个手指赋值。

/**  * 多点触碰的时候按下,当第0个有手指抬起,再次有手指按下后,将按下的事件的手指指针作为当前手指指针  *  * @param motionEvent  */ private void onSecondaryPointerUp(MotionEvent motionEvent) {  Log.d(TAG, "onSecondaryPointerUp motionEvent.getPointerId(0) = " + motionEvent.getPointerId(0));  Log.d(TAG, "onSecondaryPointerUp this.mActivePointerId = " + this.mActivePointerId);  if (motionEvent.getPointerId(0) == this.mActivePointerId) {   this.mLastMotionY = motionEvent.getY(0);   this.mActivePointerId = motionEvent.getPointerId(0);  }  Log.d(TAG, "onSecondaryPointerUp mLastMotionY = " + mLastMotionY);  Log.d(TAG, "onSecondaryPointerUp mActivePointerId = " + mActivePointerId); }

重置所有的数据

/** * 重置所有数据*/ private void reset() {  this.mActivePointerId = INVALID_VALUE;  this.mLastMotionY = INVALID_VALUE;  this.mMaxScale = INVALID_VALUE;  this.mLastScale = INVALID_VALUE; }

向上滚动时修改布局样式

@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  Log.d(TAG, "onScroll");  float bottomSpacing = this.mHeaderHeight - this.mHeaderContainer.getBottom();  Log.d(TAG, "onScroll bottomSpacing = " + bottomSpacing);  if ((bottomSpacing > 0.0F) && (bottomSpacing < this.mHeaderHeight)) {//如果是向上滑动   int toUpScroll = (int) (0.65D * bottomSpacing);   this.mHeaderImage.scrollTo(0, -toUpScroll);   Log.d(TAG, "onScroll 向上滑动 toUpScroll = " + toUpScroll);  } else if (this.mHeaderImage.getScrollY() != 0) {   Log.d(TAG, "onScroll this.mHeaderImage.getScrollY() = " + this.mHeaderImage.getScrollY());   this.mHeaderImage.scrollTo(0, 0);  }  if (this.mOnScrollListener != null) {   this.mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);  } }

不同事件处理,修改布局样式

@Override public boolean onTouchEvent(MotionEvent motionEvent) {  switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {   case MotionEvent.ACTION_OUTSIDE:   case MotionEvent.ACTION_DOWN:    if (!this.mScalingRunnalable.mIsFinished) {     this.mScalingRunnalable.abortAnimation();    }    this.mLastMotionY = motionEvent.getY();    //获取第一个手指指针的ID    this.mActivePointerId = motionEvent.getPointerId(0);    this.mMaxScale = (this.mScreenHeight / this.mHeaderHeight);    this.mLastScale = (this.mHeaderContainer.getBottom() / this.mHeaderHeight);    Log.d(TAG, "onTouchEvent ACTION_DOWN mLastMotionY = " + mLastMotionY);    Log.d(TAG, "onTouchEvent ACTION_DOWN mActivePointerId = " + mActivePointerId);    Log.d(TAG, "onTouchEvent ACTION_DOWN mMaxScale = " + mMaxScale);    Log.d(TAG, "onTouchEvent ACTION_DOWN mLastScale = " + mLastScale);    break;   case MotionEvent.ACTION_MOVE:    Log.d(TAG, "onTouchEvent ACTION_MOVE mActivePointerId" + mActivePointerId);    //获取当前id的手机指针    int pointer = motionEvent.findPointerIndex(this.mActivePointerId);    //判断指针不为空    if (pointer == INVALID_VALUE) {     Log.e(TAG, "Invalid pointerId=" + this.mActivePointerId + " in onTouchEvent");    } else {     //如果开始没有赋值,则需要赋值     if (this.mLastMotionY == INVALID_VALUE) {      this.mLastMotionY = motionEvent.getY(pointer);     }     if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight) {      //获取头部样式      ViewGroup.LayoutParams headerParams = this.mHeaderContainer.getLayoutParams();      float currentScale = ((motionEvent.getY(pointer) - this.mLastMotionY + this.mHeaderContainer.getBottom())        / this.mHeaderHeight - this.mLastScale)        / 2.0F + this.mLastScale;      if ((this.mLastScale <= 1.0D) && (currentScale < this.mLastScale)) {       //最后比例小于默认并且当前的比例要小于上次的比例,则修改头部的高度       headerParams.height = this.mHeaderHeight;       this.mHeaderContainer.setLayoutParams(headerParams);       return super.onTouchEvent(motionEvent);      } else {       //否则,将当前的比例赋值为最后一次的比例       this.mLastScale = Math.min(Math.max(currentScale, 1.0F), this.mMaxScale);       headerParams.height = ((int) (this.mHeaderHeight * this.mLastScale));       //判断修改后的高度小于屏幕的高度       if (headerParams.height < this.mScreenHeight) {        this.mHeaderContainer.setLayoutParams(headerParams);       }       //记录最后的y坐标       this.mLastMotionY = motionEvent.getY(pointer);       return true;      }     }     this.mLastMotionY = motionEvent.getY(pointer);    }    break;   case MotionEvent.ACTION_UP:    Log.d(TAG, "onTouchEvent ACTION_UP 重置");    //重置    reset();    //当手指起来的时候,结算拉伸,判断是否开启动画    endScraling();    break;   case MotionEvent.ACTION_CANCEL:    int actionIndex = motionEvent.getActionIndex();//获取当前最上层的指针    this.mLastMotionY = motionEvent.getY(actionIndex);//获取最后的y坐标    this.mActivePointerId = motionEvent.getPointerId(actionIndex);//获取最上层指针的手指    Log.d(TAG, "onTouchEvent ACTION_CANCEL actionIndex = " + actionIndex + " mLastMotionY = " + mLastMotionY + " mActivePointerId = " + mActivePointerId);    break;   case MotionEvent.ACTION_POINTER_DOWN:    //当第二个手指按下或者放开触发这个事件    onSecondaryPointerUp(motionEvent);    this.mLastMotionY = motionEvent.getY(motionEvent.findPointerIndex(this.mActivePointerId));    Log.d(TAG, "onTouchEvent_Po ACTION_POINTER_DOWN mLastMotionY = " + mLastMotionY);    break;   case MotionEvent.ACTION_POINTER_UP:    //当第二个手指按下或者放开    Log.d(TAG, "onTouchEvent_Po ACTION_POINTER_UP ");    break;  }  return super.onTouchEvent(motionEvent); }

向上返回时的动画

/**  * 向上返回的动画  */ class ScalingRunnalable implements Runnable {  long mDuration;//持续时间  boolean mIsFinished = true;//是否结束  float mScale;//比例  long mStartTime;//开始时间  ScalingRunnalable() {  }  /**   * 中止动画   */  public void abortAnimation() {   this.mIsFinished = true;  }  /**   * 是否中止   *   * @return   */  public boolean isFinished() {   return this.mIsFinished;  }  public void run() {   Log.d(TAG, "ScalingRunnalable mIsFinished = " + this.mIsFinished + " this.mScale = " + this.mScale);   float currentScale;   ViewGroup.LayoutParams mHeaderContainerParams;//头部样式   //判断是否中止和已经滑动超过的默认大小   if ((!this.mIsFinished) && (this.mScale > 1.0D)) {    float currentTime = ((float) SystemClock.currentThreadTimeMillis() - (float) this.mStartTime) / (float) this.mDuration;    currentScale = this.mScale - (this.mScale - 1.0F) * PullToZoomListView.sInterpolator.getInterpolation(currentTime);    Log.d(TAG, "ScalingRunnalable currentTime = " + currentTime + " currentScale = " + currentScale);    mHeaderContainerParams = PullToZoomListView.this.mHeaderContainer.getLayoutParams();    if (currentScale > 1.0F) {     Log.d(TAG, "ScalingRunnalable currentScale > 1.0 -- 修改头部高度");     mHeaderContainerParams.height = PullToZoomListView.this.mHeaderHeight;     mHeaderContainerParams.height = ((int) (currentScale * PullToZoomListView.this.mHeaderHeight));     PullToZoomListView.this.mHeaderContainer.setLayoutParams(mHeaderContainerParams);     PullToZoomListView.this.post(this);//循环执行    } else {     Log.d(TAG, "ScalingRunnalable currentScale < 1.0 -- 中止");     this.mIsFinished = true;    }   }  }  public void startAnimation(long paramLong) {   Log.d(TAG, "ScalingRunnalable 开始执行动画");   this.mStartTime = SystemClock.currentThreadTimeMillis();   this.mDuration = paramLong;   this.mScale = ((float) (PullToZoomListView.this.mHeaderContainer.getBottom()) / PullToZoomListView.this.mHeaderHeight);   this.mIsFinished = false;   Log.d(TAG, "ScalingRunnalable this.mStartTime = " + this.mStartTime);   Log.d(TAG, "ScalingRunnalable this.mDuration = " + this.mDuration);   Log.d(TAG, "ScalingRunnalable this.mScale = " + this.mScale);   Log.d(TAG, "ScalingRunnalable this.mIsFinished = " + this.mIsFinished);   PullToZoomListView.this.post(this);  } }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表