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

Implementazione di ScrollView in Android per ingrandimento dell'immagine in alto quando trascinata

Introduzione

Quando stavo lavorando su un progetto, avevo bisogno di implementare un effetto ScrollView simile a quello della pagina personale di Weibo, ovvero quando si trascina verso il basso dalla parte superiore, l'immagine in alto si amplifica. Poi ho trovato un articolo correlato su Internet, l'effetto è molto buono e il codice è semplice e facile da capire. (Link: Implementazione personalizzata di ScrollView per l'immagine in alto che si amplifica quando si trascina verso il basso), quindi qui ho solo fatto alcune modifiche rispetto a quel codice, come controllare la posizione centrale dell'immagine nel codice, aggiungere la regolazione dinamica del componente da amplificare, utilizzare il fattore di amplificazione massimo personalizzato, ecc., sono modifiche molto semplici e ho anche aggiunto il callback dell'ascoltatore dello scorrimento (richiesto dal progetto).

L'effetto è il seguente:

Pensiero

Come sempre, prima di tutto, parliamo del pensiero, il pensiero è più importante del codice. I passaggi specifici sono i seguenti:
1. Ottenere il componente da amplificare e ottenere le sue dimensioni;
2. Continuare a trascinare verso il basso quando si è in alto, modificare le dimensioni del componente utilizzando LayoutParams;
3. Inizializzare i parametri vari quando il dito viene sollevato, ripristinare il componente utilizzando l'animazione delle proprietà.

Implementazione

Guardiamo direttamente il codice

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);
 }
 // Utilizzato per registrare la posizione di scorrimento
 private float y = 0f;
 // L'altezza e la larghezza originali di zoomView
 private int zoomViewWidth = 0;
 private int zoomViewHeight = 0;
 // Se sta amplificando
 private boolean mScaling = false;
 // Amplificato view, predefinito come primo sotto-view
 private View zoomView;
 public void setZoomView(View zoomView) {
  this.zoomView = zoomView;
 }
 // 滑动放大系数,系数越大,滑动时放大程度越大
 private float mScaleRatio = 0.4f;
 public void setmScaleRatio(float mScaleRatio) {
  this.mScaleRatio = mScaleRatio;
 }
 // 最大的放大倍数
 private float mScaleTimes = 2f;
 public void setmScaleTimes(int mScaleTimes) {
  this.mScaleTimes = mScaleTimes;
 }
 // 回弹时间系数,系数越小,回弹越快
 private float mReplyRatio = 0.5f;
 public void setmReplyRatio(float mReplyRatio) {
  this.mReplyRatio = mReplyRatio;
 }
 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();
//  不可过度滚动,否则上移后下拉会出现部分空白的情况
  setOverScrollMode(OVER_SCROLL_NEVER);
//  获得默认第一个view
  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();//Registrazione della posizione quando scorre alla cima
     }
      break;
     }
    }
    int distance = (int) ((ev.getY() - y)*mScaleRatio);
    if (distance < 0) break;//Se scorre verso il basso
    mScaling = true;
    setZoom(distance);
    return true;
   case MotionEvent.ACTION_UP:
    mScaling = false;
    replyView();
    break;
  }
  return super.onTouchEvent(ev);
 }
 /**Ingrandire la vista*/
 private void setZoom(float s) {
  float scaleTimes = (float) ((zoomViewWidth+s)/(zoomViewWidth*1.0));
//  Se supera il fattore di ingrandimento massimo, tornare direttamente
  if (scaleTimes > mScaleTimes) return;
  ViewGroup.LayoutParams layoutParams = zoomView.getLayoutParams();
  layoutParams.width = (int) (zoomViewWidth + s);
  layoutParams.height = (int)(zoomViewHeight*((zoomViewWidth+s)/zoomViewWidth));
//  Impostare il controllo centrato orizzontalmente
  ((MarginLayoutParams) layoutParams).setMargins(-(layoutParams.width - zoomViewWidth) / 2, 0, 0, 0);
  zoomView.setLayoutParams(layoutParams);
 }
 /**Ripristino*/
 private void replyView() {
  final float distance = zoomView.getMeasuredWidth() - zoomViewWidth;
  // Impostazione dell'animazione
  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;
 }
 /**Spostamento in ascolto*/
 public interface OnScrollListener{
  void onScroll(int scrollX, int scrollY, int oldScrollX, int oldScrollY);
 }
}

Puoi vedere che in onTouchEvent, prima si verifica se è lo stato di ingrandimento attuale, se non lo è, si registra la posizione dell'evento di tocco in alto quando è in alto, naturalmente questo può essere scritto anche nell'evento ACTION_DOWN, se non è in alto, non elaboriamo.

Calcola la distanza di scorrimento dopo, se scorri verso il basso, non elaboriamo, è necessario notare che questa distanza si riferisce alla distanza tra la posizione corrente e l'azione ACTION_DOWN iniziale, quindi quando questa distanza è minore di 0, è "non ingrandito && scorri verso il basso", a questo punto dovresti scorrere lo ScrollView, sì, non c'è nulla di male. Quando la distanza non è inferiore a 0, inizia a ingrandire l'elemento, puoi vedere che è stato chiamato il metodo setZoom, nota che qui viene fatto anche il ridimensionamento del controllo in basso e il recupero in alto, anche il ritorno è chiamato questo metodo.

Ritornare quando sollevi la mano, questo non ha bisogno di essere spiegato.

Il codice in generale è piuttosto semplice, se hai bisogno di altre implementazioni, puoi aggiungerle facilmente, ad esempio, quando dobbiamo ingrandire l'immagine come Weibo, ruotare il fiore esterno, come possiamo aggiornare i dati quando rilasciamo? Puoi farlo nel
Aggiungi un'interfaccia di callback in onTouchEvent, quindi puoi implementare la logica specifica esternamente.

Uso

Puoi usarlo direttamente come un normale ScollView, non c'è bisogno di spiegare ulteriormente.

Codice sorgente:Indirizzo di download

Questo è tutto il contenuto dell'articolo, speriamo che sia utile per la tua apprendimento e che tu sostenga fortemente la guida di urla.

Dichiarazione: il contenuto di questo articolo è stato tratto da Internet, il copyright è della proprietà del rispettivo proprietario, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non detiene il diritto di proprietà, non è stato elaborato manualmente e non assume alcuna responsabilità legale correlata. Se trovi contenuti sospetti di violazione del copyright, ti preghiamo di inviare una e-mail a notice#oldtoolbag.com (sostituisci # con @) per segnalare il problema e fornire prove pertinenti. Una volta verificata, questo sito eliminerà immediatamente il contenuto sospetto di violazione del copyright.

Ti potrebbe interessare