English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Android仿QQ好友详情页下拉顶部图片缩放效果

This article shares the specific code for displaying the Android pull-down top image zoom effect with everyone for reference, the specific content is as follows

Effect Diagram

Effect Analysis

1 Slide down, the top image keeps getting larger as the finger slides

2 Slide up continuously, moving the image upwards until the image is not visible

3 When the top image is not visible, slide up, sliding ListView

Implementation Ideas

1 As this View is divided into two parts, upper and lower, vertically aligned, it can be implemented by inheriting LinearLayout: Define a custom DragImageView, which inherits LinearLayout

public DragImageView(Context context, AttributeSet attrs) {
  super(context, attrs);
  // Default the View to be vertically arranged
  setOrientation(LinearLayout.VERTICAL);
  // Used to cooperate with handling the inertia sliding of this View
  mScroller = new OverScroller(context);
  mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
  mMaximumVelocity = ViewConfiguration.get(context)
        .getScaledMaximumFlingVelocity();
  mMinimumVelocity = ViewConfiguration.get(context)
        .getScaledMinimumFlingVelocity();
  }

2 Set the height of the content view in onMeasure

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  LayoutParams params = (LayoutParams) getChildAt(1).getLayoutParams();
  // The header can be completely hidden, so the height of the content view is the height of the control
  params.height = getMeasuredHeight();
}

3 Set the ScaleType attribute of ImageView

@Override
protected void onFinishInflate() {
  super.onFinishInflate();
  imageView = (ImageView) getChildAt(0);
  // As the finger slides, the picture keeps zooming in (both width and height are greater than or equal to the size of ImageView), and it is displayed in the center:
  // According to the analysis above, CENTER_CROP: It can use an even zoom image (keep the original image ratio), so that the two coordinates (width, height) of the image are greater than or equal to the corresponding view coordinates (negative inner padding), and the image is centered in the view
  imageView.setScaleType(ScaleType.CENTER_CROP);
  listView = (ListView) getChildAt(1);
}

4 Event Interception

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
  if (ev.getAction() == MotionEvent.ACTION_DOWN) {
    downX = (int) ev.getX();
    downY = (int) ev.getY();
  }
  if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    int currentX = (int) ev.getX();
    int currentY = (int) ev.getY();
    // Ensure it is a vertical swipe
    if (Math.abs(currentY - downY) > Math.abs(currentX - downX)) {
      View childView = listView.getChildAt(listView
          .getFirstVisiblePosition());
      // There are two cases that need to be intercepted:
      // 1 The image is not completely hidden
      // 2 The image is completely hidden, but scrolled down and the ListView is scrolled to the top
      if (getScrollY() != imageHeight
          || (getScrollY() == imageHeight && currentY - downY > 0
              && childView != null && childView.getTop() == 0)) {
        initVelocityTrackerIfNotExists();
        mVelocityTracker.addMovement(ev);
        return true;
      }
    }
  }
  if (ev.getAction() == MotionEvent.ACTION_UP) {
    recycleVelocityTracker();
  }
  return super.onInterceptTouchEvent(ev);
}

5 onTouchEvent's ACTION_MOVE handling

if (ev.getAction() == MotionEvent.ACTION_MOVE) {
    int currentX = (int) ev.getX();
    int currentY = (int) ev.getY();
    int deltyX = currentX - downX;
    int deltyY = currentY - downY;
    if (Math.abs(deltyY) > Math.abs(deltyX)) {
      if (deltyY > 0) {
        if (getScrollY() > 0) {
          if (getScrollY() - deltyY < 0) {
            scrollBy(0, -getScrollY());
            return true;
          }
          // When the image is not fully displayed and scrolled down, continue the entire view to make the image visible
          scrollBy(0, -deltyY);
        }
        // When the image is fully displayed and scrolled down, the image is continuously zoomed in by changing the height of the ImageView
          LayoutParams layoutParams = (LayoutParams) getChildAt(0)
              .getLayoutParams();
          layoutParams.height = layoutParams.height + deltyY / 2;
          getChildAt(0).setLayoutParams(layoutParams);
        }
      }
      // When the image is still in the zoomed state and sliding up, continue to gradually reduce the height of the image to make the image smaller
        if (getChildAt(1).getTop() > imageHeight) {
          LayoutParams layoutParams = (LayoutParams) getChildAt(0)
              .getLayoutParams();
          layoutParams.height = layoutParams.height + deltyY / 2;
          getChildAt(0).setLayoutParams(layoutParams);
        }
        // When the image is in the normal state and sliding up, move the entire View to reduce the visible range of the image
          if (getScrollY() - deltyY > imageHeight) {
            scrollBy(0, imageHeight - getScrollY());
            return true;
          }
          scrollBy(0, -deltyY);
        }
      }
      downY = currentY;
      downX = currentX;
      return true;
    }
  }

6 ACTION_UP handling of onTouchEvent

if (ev.getAction() == MotionEvent.ACTION_UP) {
  // When the image is in the zoomed state, release it to slowly return the image to its original state
  if (getChildAt(1).getTop() > imageHeight) {
    isAnimating = true;
    ValueAnimator valueAnimator = ValueAnimator.ofInt(getChildAt(1)
        .getTop(), imageHeight);
    valueAnimator.setDuration(300);
    valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
        int value = (Integer) animation.getAnimatedValue();
        LayoutParams layoutParams = (LayoutParams) getChildAt(0)
            .getLayoutParams();
        layoutParams.height = value;
        getChildAt(0).setLayoutParams(layoutParams);
      }
    });
    valueAnimator.addListener(new AnimatorListenerAdapter() {
      @Override
      public void onAnimationEnd(Animator animation) {}}
        super.onAnimationEnd(animation);
        isAnimating = false;
      }
    });
    valueAnimator.start();
  }
  // When the current image is in a normal state, and the image is not completely hidden, and the sliding speed is greater than the minimum inertia sliding value when the hand is released, let the View produce an inertia sliding effect
  if (getChildAt(1).getTop() == imageHeight
      && getScrollY() != imageHeight) {
    mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
    int velocityY = (int) mVelocityTracker.getYVelocity();
    if (Math.abs(velocityY) > mMinimumVelocity) {
      fling(-velocityY);
    }
    recycleVelocityTracker();
  }

Summary

There are mainly two learning points here

1 Handling of image zoom, event interception

2 Inertia sliding of View: mainly combined with the use of OverScroller

That's all for this article. I hope it will be helpful to everyone's learning, and I also hope everyone will support the Yelling Tutorial more.

Declaration: The content of this article is from the Internet, the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, does not edit the content manually, and does not assume any relevant legal responsibility. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting. Provide relevant evidence, and once verified, this site will immediately delete the infringing content.)

You May Also Like