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

Android ListView zur Implementierung des Effekts der Bildvergrößerung beim Ziehen nach oben

Dieser Artikel teilt den spezifischen Code für die Erweiterung des oberen Bildes der Android ListView, den ich geteilt habe, zur Referenz, der Inhalt ist wie folgt

Bei der Überprüfung des Codes von Profis auf GitHub fand ich heraus, dass es sich um Decompilation fremder Codes handelt, die noch keine Kommentare hinzugefügt haben und der Code ist nicht vollständig kompiliert. Daher habe ich hier einfache Kommentare hinzugefügt, die nur zur Lernzweck dienen.

Variablenbeschreibung

Hier enthalten sind: benutzerdefinierte Rückwärtsbeschleunigung der Animation, benutzerdefinierte Animationsthread, Header-Bild-View, letze Y-Koordinate, erstellte Proportion, vergrößerte Proportion usw.

private static final String TAG = "PullToZoomListView";
 private static final int INVALID_VALUE = -1;//Wiederherstellungswert
 //benutzerdefinierte Beschleunigungsanimation
 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;//Aktuelle Finger-ID
 private FrameLayout mHeaderContainer;//Kopfzeile
 private int mHeaderHeight;//Höhe des Kopf-Bildes
 private ImageView mHeaderImage;//Kopfbild
 float mLastMotionY = INVALID_VALUE;//letzte y-Koordinate
 float mLastScale = INVALID_VALUE;//letzte Verhältnis
 float mMaxScale = INVALID_VALUE;//größte Verhältnis
 private OnScrollListener mOnScrollListener;//Scrollen-Abhörer
 private ScalingRunnalable mScalingRunnalable;//Animationsthread
 private int mScreenHeight;//Bildschirmhöhe
 private ImageView mShadow;//Schattenmaske

Initialisierung der benutzerdefinierten View: Der Kopf und die Schattenmaske wurden gesetzt und der Listener wurde eingerichtet.

/**
  * Initialisierung
  * @param paramContext
  */
 private void init(Context paramContext) {
  DisplayMetrics metrics = new DisplayMetrics();
  ((Activity) paramContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
  this.mScreenHeight = metrics.heightPixels;//Ziehen Sie die Bildschirmhöhe zu
  this.mHeaderContainer = new FrameLayout(paramContext);//Kopfzeile
  this.mHeaderImage = new ImageView(paramContext);//Kopfbild
  int screenWidth = metrics.widthPixels;//Bildschirmbreite
  //Stellen Sie den Stil des Kopf-Views ein: Setzen Sie die Bildschirmbreite, die maximale Stilhöhe ist die Höhe des Bildschirms9/16
  setHeaderViewSize(screenWidth, (int) (9.0F * (screenWidth / 16.0F)));
  this.mShadow = new ImageView(paramContext);//Überlagerung
  FrameLayout.LayoutParams layoutParams =
    new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
      ViewGroup.LayoutParams.MATCH_PARENT);
  layoutParams.gravity = Gravity.CENTER;
  this.mShadow.setLayoutParams(layoutParams);//Setzen Sie den Stil der Überlagerung
  //Fügen Sie View zur Kopfzeile hinzu
  this.mHeaderContainer.addView(this.mHeaderImage);
  this.mHeaderContainer.addView(this.mShadow);
  //Fügen Sie die Kopfzeile hinzu
  addHeaderView(this.mHeaderContainer);
  //Initialisieren Sie die Rückwärts-Animation
  this.mScalingRunnalable = new ScalingRunnalable();
  //Setzen Sie den Listener
  super.setOnScrollListener(this);
 }

Animation starten: Prüfen Sie die Position der unteren Kante der aktuellen Kopfleiste – ob sie größer als die initiale Höhe des Bildes ist.

/**
  * Animation starten
  */
 private void endScraling() {
  if (this.mHeaderContainer.getBottom() >= this.mHeaderHeight) {
   Log.d(TAG, "dieses.mScalingRunnalable.startAnimation("200L)");
   this.mScalingRunnalable.startAnimation(200L);
  }
 }

Beim mehrfachen Berühren wird der 0. Finger zugewiesen.

/**
  * Bei mehrfachen Berührungen wird gedrückt, wenn der 0. Finger aufhebt und erneut ein Finger gedrückt wird, wird der aufhebe-Event-Fingerzeiger als aktueller Fingerzeiger gesetzt
  *
  * @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);
 }

Alle Daten zurücksetzen

/**
 * Alle Daten zurücksetzen
*/
 private void reset() {
  this.mActivePointerId = INVALID_VALUE;
  this.mLastMotionY = INVALID_VALUE;
  this.mMaxScale = INVALID_VALUE;
  this.mLastScale = INVALID_VALUE;
 }

BeimScrollen nach oben das Layout-Design ändern

@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)) {//Wenn nach oben gescrollt wird
   int toUpScroll = (int) (0.65D * bottomSpacing);
   this.mHeaderImage.scrollTo(0, -toUpScroll);
   Log.d(TAG, "onScroll nach oben scrollen 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);
  }
 }

Behandlung verschiedener Ereignisse, Änderung des Layout-Stils

@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();
    //Erhalten Sie die ID des ersten Fingerzeigers
    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)) {
       //Wenn das letzte Verhältnis kleiner als das Standardverhältnis ist und das aktuelle Verhältnis kleiner als das letzte Verhältnis ist, ändern Sie die Höhe des Kopfes
       headerParams.height = this.mHeaderHeight;
       this.mHeaderContainer.setLayoutParams(headerParams);
       return super.onTouchEvent(motionEvent);
      } else {
       //sonst, weisen Sie das aktuelle Verhältnis dem letzten Verhältnis zu
       this.mLastScale = Math.min(Math.max(currentScale, 1.0F), this.mMaxScale);
       headerParams.height = ((int) (this.mHeaderHeight * this.mLastScale));
       //Überprüfen Sie, ob die geänderte Höhe kleiner als die Bildschirmhöhe ist
       if (headerParams.height < this.mScreenHeight) {
        this.mHeaderContainer.setLayoutParams(headerParams);
       }
       //Notieren Sie die letzte y-Koordinate
       this.mLastMotionY = motionEvent.getY(pointer);
       return true;
      }
     }
     this.mLastMotionY = motionEvent.getY(pointer);
    }
    break;
   case MotionEvent.ACTION_UP:
    Log.d(TAG, "onTouchEvent ACTION_UP Zurücksetzen");
    //Zurücksetzen
    reset();
    //Wenn der Finger hochgenommen wird, werden die Dehnungen berechnet und überprüft, ob die Animation aktiviert ist
    endScraling();
    break;
   case MotionEvent.ACTION_CANCEL:
    int actionIndex = motionEvent.getActionIndex();//Erhalten Sie den aktuellen obersten Zeiger
    this.mLastMotionY = motionEvent.getY(actionIndex);//Erhalten Sie die letzte y-Koordinate
    this.mActivePointerId = motionEvent.getPointerId(actionIndex);//Erhalten Sie den Finger der obersten Zeiger
    Log.d(TAG, "onTouchEvent ACTION_CANCEL actionIndex = ") + actionIndex + " mLastMotionY = " + mLastMotionY + " mActivePointerId = " + mActivePointerId);
    break;
   case MotionEvent.ACTION_POINTER_DOWN:
    //Wenn der zweite Finger gedrückt oder gelöst wird, wird dieses Ereignis ausgelöst
    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:
    //Wenn der zweite Finger gedrückt oder gelöst wird
    Log.d(TAG, "onTouchEvent_Po ACTION_POINTER_UP ");
    break;
  }
  return super.onTouchEvent(motionEvent);
 }

Animation beim Zurück nach oben

/**
  * Animation zurück nach oben
  */
 class ScalingRunnalable implements Runnable {
  long mDuration;//Dauer
  boolean mIsFinished = true;//Ob beendet
  float mScale;//Verhältnis
  long mStartTime;//Startzeit
  ScalingRunnalable() {
  }
  /**
   * Animation abbrechen
   */
  public void abortAnimation() {
   this.mIsFinished = true;
  }
  /**
   * Abbruchbedingung
   *
   * @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;//Header-Stil
   //Überprüfen Sie, ob die Abbruchbedingung erfüllt ist und ob es über die Standardgröße hinaus gescrollt wurde
   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);
  }
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

声明:本文内容来自网络,版权属于原作者。内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未进行人工编辑处理,也不承担相关法律责任。如果您发现涉嫌版权的内容,请发送邮件至:notice#oldtoolbag.com(在发送邮件时,请将#替换为@进行举报,并提供相关证据。一经查实,本站将立即删除涉嫌侵权的内容。)

Vermutlich gefällt Ihnen auch