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

Implementación de ScrollView en Android para hacer que la imagen superior se agrande al deslizar hacia abajo

preface

When I was working on a project before, I needed to implement a ScrollView effect similar to that of a Weibo personal homepage, where when you pull down at the top, the top picture will zoom in. Then I found a related implementation on the internet, which was very good in terms of effect and the code was also concise and easy to understand. (Link: Custom scrollView to implement top picture zooming when pulling down at the top), so here I just made a few modifications to it, such as controlling the image to be centered in the code, adding dynamic setting of the zoomed control, using a custom maximum zoom factor, etc., which are all very simple modifications, and also added the sliding listener callback (required by the project).

The effect is as follows:

idea

As usual, let's talk about the idea first, because the idea is the most important compared to the code. The specific steps are as follows:
1. Get the control to be zoomed and obtain its width and height;
2. Continue to pull down at the top, and change the width and height of the control through LayoutParams;
3. Initialize all parameters when the finger is lifted, and bounce the control through property animation.

implementation

take a look at the code directly

public class HeadZoomScrollView extends ScrollView {
 public HeadZoomScrollView(Context context) {
  super(context);
 }
 public HeadZoomScrollView(Context context, AttributeSet attrs) {
  super(context, attrs);
 }
 public HeadZoomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
 }
 // used to record the pull-down position
 private float y = 0f;
 // zoomView original width and height
 private int zoomViewWidth = 0;
 private int zoomViewHeight = 0;
 // ¿está en proceso de ampliación?
 private boolean mScaling = false;
 // view de ampliación, por defecto la primera subview
 private View zoomView;
 public void setZoomView(View zoomView) {
  this.zoomView = zoomView;
 }
 // Coeficiente de desplazamiento de desplazamiento, cuanto mayor sea el coeficiente, mayor será el grado de ampliación durante el desplazamiento
 private float mScaleRatio = 0.4f;
 public void setmScaleRatio(float mScaleRatio) {
  this.mScaleRatio = mScaleRatio;
 }
 // el mayor factor de ampliación
 private float mScaleTimes = 2f;
 public void setmScaleTimes(int mScaleTimes) {
  this.mScaleTimes = mScaleTimes;
 }
 // Coeficiente de tiempo de rebote, cuanto menor sea el coeficiente, más rápido será el rebote
 private float mReplyRatio = 0.5f;
 public void setmReplyRatio(float mReplyRatio) {
  this.mReplyRatio = mReplyRatio;
 }
 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
//  No se permite desplazamiento excesivo, de lo contrario, después de desplazarse hacia arriba y luego hacia abajo, aparecerá un área en blanco
  setOverScrollMode(OVER_SCROLL_NEVER);
//  obtener la primera view por defecto
  if (getChildAt(0) != null && getChildAt(0) instanceof ViewGroup && zoomView == null) {
   ViewGroup vg = (ViewGroup) getChildAt(0);
   if (vg.getChildCount() > 0) {
    zoomView = vg.getChildAt(0);
   }
  }
 }
 @Override
 public boolean onTouchEvent(MotionEvent ev) {
  if (zoomViewWidth <= 0 || zoomViewHeight <= 0) {
   zoomViewWidth = zoomView.getMeasuredWidth();
   zoomViewHeight = zoomView.getMeasuredHeight();
  }
  if (zoomView == null || zoomViewWidth <= 0 || zoomViewHeight <= 0) {
   return super.onTouchEvent(ev);
  }
  switch (ev.getAction()) {
   case MotionEvent.ACTION_MOVE:
    if (!mScaling) {
     if (getScrollY() == 0) {
      y = ev.getY();//al deslizar a la parte superior, registrar la posición
     } else {
      break;
     }
    }
    int distance = (int) ((ev.getY() - y)*mScaleRatio);
    if (distance < 0) break;//si se desliza hacia abajo
    mScaling = true;
    setZoom(distance);
    return true;
   case MotionEvent.ACTION_UP:
    mScaling = false;
    replyView();
    break;
  }
  return super.onTouchEvent(ev);
 }
 /**ampliar la vista*/
 private void setZoom(float s) {
  float scaleTimes = (float) ((zoomViewWidth+s)/(zoomViewWidth*1).0));
//  si supera el factor de amplificación máximo, regrese directamente
  if (scaleTimes > mScaleTimes) return;
  ViewGroup.LayoutParams layoutParams = zoomView.getLayoutParams();
  layoutParams.width = (int) (zoomViewWidth + s);
  layoutParams.height = (int)(zoomViewHeight*((zoomViewWidth+s)/);
//  ajustar el control al centro horizontalmente
  ((MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width)} - zoomViewWidth) / 2, 0, 0, 0);
  zoomView.setLayoutParams(layoutParams);
 }
 /**resbalón*/
 private void replyView() {
  final float distance = zoomView.getMeasuredWidth() - zoomViewWidth;
  // establecer animación
  ValueAnimator anim = ObjectAnimator.ofFloat(distance, 0.0F).setDuration((long) (distance * mReplyRatio));
  anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   @Override
   public void onAnimationUpdate(ValueAnimator animation) {
    setZoom((Float) animation.getAnimatedValue());
   }
  });
  anim.start();
 }
 @Override
 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  super.onScrollChanged(l, t, oldl, oldt);
  if (onScrollListener!=null) onScrollListener.onScroll(l, t, oldl, oldt);
 }
 private OnScrollListener onScrollListener;
 public void setOnScrollListener(OnScrollListener onScrollListener) {
  this.onScrollListener = onScrollListener;
 }
 /**desplazamiento de escucha*/
 public interface OnScrollListener{
  void onScroll(int scrollX, int scrollY, int oldScrollX, int oldScrollY);
 }
}

Se puede ver que en el método onTouchEvent, primero se�断a si está en estado de ampliación, si no lo está, se graba la posición del evento de toque en la parte superior, por supuesto, también se puede escribir en el evento ACTION_DOWN, si no está en la parte superior, no se procesa.

Luego se calcula la distancia deslizante, si se desliza hacia abajo, no se procesa, lo que hay que tener en cuenta es que esta distancia es la distancia entre la posición actual y el ACTION_DOWN de la acción inicial, por lo que cuando esta distancia es menor que 0, es "no ampliar && deslizar hacia abajo", en este momento, debe deslizar el ScrollView, bueno, no hay problema. Cuando la distancia no es menor o igual a 0, comienza a ampliar el controlador, se puede ver que se llama al método setZoom, note que aquí se hacen también el deslizamiento hacia abajo del controlador y el retorno hacia arriba, en realidad también se llama a este método.

Retornar cuando levanta la mano, esto no necesita decirse.

El código en general es bastante simple, si necesita otra implementación, también puede agregarla fácilmente, por ejemplo, cuando queremos ampliar la imagen como Weibo, rotar la flor exterior cuando soltamos, ¿qué hacer cuando actualizamos los datos? Puede hacerlo en
Añada una interfaz de llamada de retorno en onTouchEvent y luego realice la lógica específica en el exterior.

Uso

Puede usarlo directamente como un ScollView común, no es necesario hacer mucho ruido.

Código fuente:Dirección de descarga

Esto es todo el contenido de este artículo, espero que ayude en su aprendizaje y también espero que todos den más apoyo al tutorial de clamor.

Declaración: el contenido de este artículo se ha obtenido de la red, y los derechos de autor pertenecen a los propietarios originales. El contenido ha sido subido por usuarios de Internet de manera voluntaria y no ha sido editado por humanos, ni este sitio asume ninguna responsabilidad legal relacionada. Si encuentra contenido sospechoso de infracción de derechos de autor, por favor envíe un correo electrónico a: notice#w3Dirección de descarga: al enviar un correo electrónico, por favor reemplace # con @ para denunciar, y proporcione evidencia relevante. Una vez verificada, este sitio eliminará inmediatamente el contenido sospechoso de infracción.

Te gustaría que te gustara