English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
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(在发送邮件时,请将#替换为@进行举报,并提供相关证据。一经查实,本站将立即删除涉嫌侵权的内容。)