LiatView下拉图片放大

public class PullZoomListView extends ListView {
/头部View 的容器/
privateFrameLayout mHeaderContainer;
/头部View 的图片/
privateImageView mHeaderImg;
/屏幕的高度/
privateintmScreenHeight;
/屏幕的宽度/
privateintmScreenWidth;

 privateintmHeaderHeight;

 /*无效的点*/
 privatestaticfinalintINVALID_POINTER = -1;
 /*滑动动画执行的时间*/
 privatestaticfinalintMIN_SETTLE_DURATION = 200; // ms
 /*定义了一个时间插值器,根据ViewPage控件来定义的*/
 privatestaticfinalInterpolator sInterpolator = newInterpolator() {
      publicfloatgetInterpolation(floatt) {
           t -= 1.0f;
           returnt * t * t * t * t + 1.0f;
      }
 };

 /*记录上一次手指触摸的点*/
 privatefloatmLastMotionX;
 privatefloatmLastMotionY;

 /*当前活动的点Id,有效的点的Id*/
 protectedintmActivePointerId = INVALID_POINTER;
 /*开始滑动的标志距离*/
 privateintmTouchSlop;

 /*放大的倍数*/
 privatefloatmScale;
 /*上一次放大的倍数*/
 privatefloatmLastScale;

 /*最大放大的倍数*/
 privatefinalfloatmMaxScale = 2.0f;
 /*是否需要禁止ListView 的事件响应*/
 privatebooleanisNeedCancelParent;

 /*这个不解释*/
 privateOnScrollListener mScrollListener ;

 /*下拉刷新的阈值*/
 privatefinalfloatREFRESH_SCALE = 1.20F;

 /*下拉刷新监听*/
 privateOnRefreshListener mRefreshListener ;

 publicPullZoomListView(Context context) {
      super(context);
      init(context);
 }

 publicPullZoomListView(Context context, AttributeSet attrs) {
      super(context, attrs);
      init(context);
 }

 publicPullZoomListView(Context context, AttributeSet attrs, intdefStyleAttr) {
      super(context, attrs, defStyleAttr);
      init(context);
 }

 privatevoid init(Context context) {

       /*这里获取的是一个无用值,可忽略*/
       finalViewConfiguration configuration = ViewConfiguration.get(context);
       mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration);

       /*创建头部View 的容器*/
       mHeaderContainer = newFrameLayout(context);
       /*获取屏幕的像素值*/
       DisplayMetrics metrics = newDisplayMetrics();
       ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(metrics);
       mScreenHeight = metrics.heightPixels;
       mScreenWidth = metrics.widthPixels;
       /*设置头部View 的初始大小*/
       mHeaderHeight = (int) ((9* 1.0f / 16) * mScreenWidth);
       LayoutParams absLayoutParams = newLayoutParams(mScreenWidth, mHeaderHeight);
       mHeaderContainer.setLayoutParams(absLayoutParams);
       /*创建图片显示的View*/
       mHeaderImg = newImageView(context);
       FrameLayout.LayoutParams imgLayoutParams = newFrameLayout.LayoutParams
                      (ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
       mHeaderImg.setScaleType(ImageView.ScaleType.CENTER_CROP);
       mHeaderImg.setLayoutParams(imgLayoutParams);
       mHeaderContainer.addView(mHeaderImg);

       /*增加头部View*/
       addHeaderView(mHeaderContainer);
       /*设置监听事件*/
       super.setOnScrollListener(newInternalScrollerListener() );

 }
 /*处理事件用*/

 @Override
 publicbooleanonTouchEvent(MotionEvent ev) {

      finalintaction = ev.getAction() & MotionEventCompat.ACTION_MASK;

      switch(action) {
      caseMotionEvent.ACTION_DOWN:

            /*计算 x,y 的距离*/
            intindex = MotionEventCompat.getActionIndex(ev);
            mActivePointerId = MotionEventCompat.getPointerId(ev, index);
            if(mActivePointerId == INVALID_POINTER)
                 break;
            mLastMotionX = MotionEventCompat.getX(ev, index);
            mLastMotionY = MotionEventCompat.getY(ev, index);
            // 结束动画,目前没做处理,可忽略
            abortAnimation();
            /*计算算一次放缩的比例*/
            mLastScale = (this.mHeaderContainer.getBottom() / this.mHeaderHeight);
            /*当按下的时候把这个标志为设为有效*/
            isNeedCancelParent = true;
            break;
    caseMotionEvent.ACTION_MOVE:
            intindexMove = MotionEventCompat.getActionIndex(ev);
            mActivePointerId = MotionEventCompat.getPointerId(ev, indexMove);

            if(mActivePointerId == INVALID_POINTER) {
                 /*这里相当于松手*/
                 finishPull();
                 isNeedCancelParent = true;
            } else{
                 /*这是一个关键值,通过这个值来判断是否需要放大图片*/
                 if(mHeaderContainer.getBottom() >= mHeaderHeight) {
                      ViewGroup.LayoutParams params = this.mHeaderContainer.getLayoutParams();
                 finalfloaty = MotionEventCompat.getY(ev, indexMove);
                 floatdy = y - mLastMotionY;
                 floatf = ((y - this.mLastMotionY + this.mHeaderContainer
                        .getBottom()) / this.mHeaderHeight - this.mLastScale)
                        / 2.0F + this.mLastScale;
                 if((this.mLastScale <= 1.0D) && (f <= this.mLastScale)) {
                       params.height = this.mHeaderHeight;
                       this.mHeaderContainer.setLayoutParams(params);
                       returnsuper.onTouchEvent(ev);
                 }
                 /*这里设置紧凑度*/
                 dy = dy * 0.5f * (mHeaderHeight * 1.0f / params.height);
                 mLastScale = (dy + params.height) * 1.0f / mHeaderHeight;
                 mScale = clamp(mLastScale, 1.0f, mMaxScale);

                 // Log.v(“zgy”, “=======mScale=====” + mLastScale+”,f = “+f);
                 params.height = (int) (mHeaderHeight * mScale);
                 mHeaderContainer.setLayoutParams(params);
                 mLastMotionY = y;
                 /*这里,如果图片有放大,则屏蔽ListView 的其他事件响应*/
                 if(isNeedCancelParent ){
                      isNeedCancelParent = false;
                      MotionEvent motionEvent = MotionEvent.obtain(ev);
                      motionEvent.setAction(MotionEvent.ACTION_CANCEL);
                      super.onTouchEvent(motionEvent);
                 }
                 returntrue;
            }
            mLastMotionY = MotionEventCompat.getY(ev, indexMove);

        }

        break;
    caseMotionEvent.ACTION_UP:
        /*结束事件响应,做相应的操作*/
        finishPull();

        break;
    caseMotionEvent.ACTION_POINTER_UP:
        /*这里需要注意,多点处理,这里的处理方式是:如果有两个手指按下,抬起的是后按下的手指,则不做处理
        * 如果抬起的是最先按下的手指,则复原图片效果。
        * */
        intpointUpIndex = MotionEventCompat.getActionIndex(ev);
        intpointId = MotionEventCompat.getPointerId(ev, pointUpIndex);
        if(pointId == mActivePointerId) {
            /*松手执行结束拖拽操作*/
            /*结束事件响应,做相应的操作*/
            finishPull();
        }

        break;

}

returnsuper.onTouchEvent(ev);

}

@Override
publicvoidsetOnScrollListener(OnScrollListener l) {
mScrollListener = l ;
}

privatevoidabortAnimation() {
/啥都没做,暂时没做而已/
}

privatevoidfinishPull() {
mActivePointerId = INVALID_POINTER;
/这是一个阈值,如果成立,则表示图片已经放大了,在手指抬起的时候需要复原图片/
if(mHeaderContainer.getBottom() > mHeaderHeight){

    // Log.v(“zgy”, “===super====onTouchEvent========”);
    /<em>这里是下拉刷新的阈值,当达到了,则表示需要刷新,可以添加刷新动画</em>/
    if(mScale > REFRESH_SCALE){
         if(mRefreshListener != null){
                mRefreshListener.onRefresh();
         }
    }
    //图片复原动画
    pullBackAnimation();

}
}
/**
* 这是属性动画的知识,不懂的可以去看看属性动画的知识
*/
privatevoidpullBackAnimation(){
ValueAnimator pullBack = ValueAnimator.ofFloat(mScale , 1.0f);
pullBack.setInterpolator(sInterpolator);
pullBack.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {
@Override
publicvoidonAnimationUpdate(ValueAnimator animation) {
floatvalue = (float) animation.getAnimatedValue();
LayoutParams params = (LayoutParams) mHeaderContainer.getLayoutParams();
params.height = (int) (mHeaderHeight * value);
mHeaderContainer.setLayoutParams(params);
}
});
pullBack.setDuration((long) (MIN_SETTLE_DURATION*mScale));
pullBack.start();

}

/**
* 通过事件和点的 id 来获取点的索引
*
* @param ev
* @param id
* @return
*/
privateintgetPointerIndex(MotionEvent ev, intid) {
intactivePointerIndex = MotionEventCompat.findPointerIndex(ev, id);
if(activePointerIndex == -1)
mActivePointerId = INVALID_POINTER;
returnactivePointerIndex;
}

publicvoidsetOnRefreshListener(OnRefreshListener l){
mRefreshListener = l ;
}

publicImageView getHeaderImageView() {
returnthis.mHeaderImg;
}

privatefloatclamp(floatvalue, floatmin, floatmax) {
returnMath.min(Math.max(value, min), max);
}

privateclassInternalScrollerListener implementsOnScrollListener{
@Override
publicvoidonScrollStateChanged(AbsListView view, intscrollState) {

    if(mScrollListener != null){
        mScrollListener.onScrollStateChanged(view,scrollState);
    }
}

@Override
publicvoidonScroll(AbsListView view, intfirstVisibleItem, intvisibleItemCount, inttotalItemCount) {
    floatdiff = mHeaderHeight - mHeaderContainer.getBottom();
    if((diff > 0.0F) && (diff < mHeaderHeight)) {
        inti = (int) (0.3D * diff);
        mHeaderImg.scrollTo(0, -i);
    } elseif(mHeaderImg.getScrollY() != 0) {
        mHeaderImg.scrollTo(0, 0);
    }

    Log.v("zgy","=========height==="+getScrolledY());

    if(mScrollListener != null){
        mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
    }
}

}

publicintgetScrolledY() {
View c = getChildAt(0);
if(c == null) {
return0;
}

intfirstVisiblePosition = getFirstVisiblePosition();
inttop = c.getTop();

intheaderHeight = 0;
if(firstVisiblePosition >= 1) {
    headerHeight = mHeaderHeight;
}

return-top + firstVisiblePosition * c.getHeight() + headerHeight;

}

publicinterfaceOnRefreshListener {
voidonRefresh() ;
}

publicvoidcomputeRefresh(){
if(mActivePointerId != INVALID_POINTER){

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值