343 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			343 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package androidx.recyclerview.widget;
 | |
| 
 | |
| import android.view.View;
 | |
| import android.view.ViewGroup;
 | |
| import androidx.recyclerview.widget.RecyclerView;
 | |
| import java.util.ArrayList;
 | |
| import java.util.List;
 | |
| 
 | |
| /* loaded from: classes.dex */
 | |
| class ChildHelper {
 | |
|     private static final boolean DEBUG = false;
 | |
|     private static final String TAG = "ChildrenHelper";
 | |
|     final Callback mCallback;
 | |
|     final Bucket mBucket = new Bucket();
 | |
|     final List<View> mHiddenViews = new ArrayList();
 | |
| 
 | |
|     interface Callback {
 | |
|         void addView(View view, int i);
 | |
| 
 | |
|         void attachViewToParent(View view, int i, ViewGroup.LayoutParams layoutParams);
 | |
| 
 | |
|         void detachViewFromParent(int i);
 | |
| 
 | |
|         View getChildAt(int i);
 | |
| 
 | |
|         int getChildCount();
 | |
| 
 | |
|         RecyclerView.ViewHolder getChildViewHolder(View view);
 | |
| 
 | |
|         int indexOfChild(View view);
 | |
| 
 | |
|         void onEnteredHiddenState(View view);
 | |
| 
 | |
|         void onLeftHiddenState(View view);
 | |
| 
 | |
|         void removeAllViews();
 | |
| 
 | |
|         void removeViewAt(int i);
 | |
|     }
 | |
| 
 | |
|     ChildHelper(Callback callback) {
 | |
|         this.mCallback = callback;
 | |
|     }
 | |
| 
 | |
|     private void hideViewInternal(View view) {
 | |
|         this.mHiddenViews.add(view);
 | |
|         this.mCallback.onEnteredHiddenState(view);
 | |
|     }
 | |
| 
 | |
|     private boolean unhideViewInternal(View view) {
 | |
|         if (!this.mHiddenViews.remove(view)) {
 | |
|             return false;
 | |
|         }
 | |
|         this.mCallback.onLeftHiddenState(view);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     void addView(View view, boolean z) {
 | |
|         addView(view, -1, z);
 | |
|     }
 | |
| 
 | |
|     void addView(View view, int i, boolean z) {
 | |
|         int offset;
 | |
|         if (i < 0) {
 | |
|             offset = this.mCallback.getChildCount();
 | |
|         } else {
 | |
|             offset = getOffset(i);
 | |
|         }
 | |
|         this.mBucket.insert(offset, z);
 | |
|         if (z) {
 | |
|             hideViewInternal(view);
 | |
|         }
 | |
|         this.mCallback.addView(view, offset);
 | |
|     }
 | |
| 
 | |
|     private int getOffset(int i) {
 | |
|         if (i < 0) {
 | |
|             return -1;
 | |
|         }
 | |
|         int childCount = this.mCallback.getChildCount();
 | |
|         int i2 = i;
 | |
|         while (i2 < childCount) {
 | |
|             int countOnesBefore = i - (i2 - this.mBucket.countOnesBefore(i2));
 | |
|             if (countOnesBefore == 0) {
 | |
|                 while (this.mBucket.get(i2)) {
 | |
|                     i2++;
 | |
|                 }
 | |
|                 return i2;
 | |
|             }
 | |
|             i2 += countOnesBefore;
 | |
|         }
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     void removeView(View view) {
 | |
|         int indexOfChild = this.mCallback.indexOfChild(view);
 | |
|         if (indexOfChild < 0) {
 | |
|             return;
 | |
|         }
 | |
|         if (this.mBucket.remove(indexOfChild)) {
 | |
|             unhideViewInternal(view);
 | |
|         }
 | |
|         this.mCallback.removeViewAt(indexOfChild);
 | |
|     }
 | |
| 
 | |
|     void removeViewAt(int i) {
 | |
|         int offset = getOffset(i);
 | |
|         View childAt = this.mCallback.getChildAt(offset);
 | |
|         if (childAt == null) {
 | |
|             return;
 | |
|         }
 | |
|         if (this.mBucket.remove(offset)) {
 | |
|             unhideViewInternal(childAt);
 | |
|         }
 | |
|         this.mCallback.removeViewAt(offset);
 | |
|     }
 | |
| 
 | |
|     View getChildAt(int i) {
 | |
|         return this.mCallback.getChildAt(getOffset(i));
 | |
|     }
 | |
| 
 | |
|     void removeAllViewsUnfiltered() {
 | |
|         this.mBucket.reset();
 | |
|         for (int size = this.mHiddenViews.size() - 1; size >= 0; size--) {
 | |
|             this.mCallback.onLeftHiddenState(this.mHiddenViews.get(size));
 | |
|             this.mHiddenViews.remove(size);
 | |
|         }
 | |
|         this.mCallback.removeAllViews();
 | |
|     }
 | |
| 
 | |
|     View findHiddenNonRemovedView(int i) {
 | |
|         int size = this.mHiddenViews.size();
 | |
|         for (int i2 = 0; i2 < size; i2++) {
 | |
|             View view = this.mHiddenViews.get(i2);
 | |
|             RecyclerView.ViewHolder childViewHolder = this.mCallback.getChildViewHolder(view);
 | |
|             if (childViewHolder.getLayoutPosition() == i && !childViewHolder.isInvalid() && !childViewHolder.isRemoved()) {
 | |
|                 return view;
 | |
|             }
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     void attachViewToParent(View view, int i, ViewGroup.LayoutParams layoutParams, boolean z) {
 | |
|         int offset;
 | |
|         if (i < 0) {
 | |
|             offset = this.mCallback.getChildCount();
 | |
|         } else {
 | |
|             offset = getOffset(i);
 | |
|         }
 | |
|         this.mBucket.insert(offset, z);
 | |
|         if (z) {
 | |
|             hideViewInternal(view);
 | |
|         }
 | |
|         this.mCallback.attachViewToParent(view, offset, layoutParams);
 | |
|     }
 | |
| 
 | |
|     int getChildCount() {
 | |
|         return this.mCallback.getChildCount() - this.mHiddenViews.size();
 | |
|     }
 | |
| 
 | |
|     int getUnfilteredChildCount() {
 | |
|         return this.mCallback.getChildCount();
 | |
|     }
 | |
| 
 | |
|     View getUnfilteredChildAt(int i) {
 | |
|         return this.mCallback.getChildAt(i);
 | |
|     }
 | |
| 
 | |
|     void detachViewFromParent(int i) {
 | |
|         int offset = getOffset(i);
 | |
|         this.mBucket.remove(offset);
 | |
|         this.mCallback.detachViewFromParent(offset);
 | |
|     }
 | |
| 
 | |
|     int indexOfChild(View view) {
 | |
|         int indexOfChild = this.mCallback.indexOfChild(view);
 | |
|         if (indexOfChild == -1 || this.mBucket.get(indexOfChild)) {
 | |
|             return -1;
 | |
|         }
 | |
|         return indexOfChild - this.mBucket.countOnesBefore(indexOfChild);
 | |
|     }
 | |
| 
 | |
|     boolean isHidden(View view) {
 | |
|         return this.mHiddenViews.contains(view);
 | |
|     }
 | |
| 
 | |
|     void hide(View view) {
 | |
|         int indexOfChild = this.mCallback.indexOfChild(view);
 | |
|         if (indexOfChild < 0) {
 | |
|             throw new IllegalArgumentException("view is not a child, cannot hide " + view);
 | |
|         }
 | |
|         this.mBucket.set(indexOfChild);
 | |
|         hideViewInternal(view);
 | |
|     }
 | |
| 
 | |
|     void unhide(View view) {
 | |
|         int indexOfChild = this.mCallback.indexOfChild(view);
 | |
|         if (indexOfChild < 0) {
 | |
|             throw new IllegalArgumentException("view is not a child, cannot hide " + view);
 | |
|         }
 | |
|         if (!this.mBucket.get(indexOfChild)) {
 | |
|             throw new RuntimeException("trying to unhide a view that was not hidden" + view);
 | |
|         }
 | |
|         this.mBucket.clear(indexOfChild);
 | |
|         unhideViewInternal(view);
 | |
|     }
 | |
| 
 | |
|     public String toString() {
 | |
|         return this.mBucket.toString() + ", hidden list:" + this.mHiddenViews.size();
 | |
|     }
 | |
| 
 | |
|     boolean removeViewIfHidden(View view) {
 | |
|         int indexOfChild = this.mCallback.indexOfChild(view);
 | |
|         if (indexOfChild == -1) {
 | |
|             unhideViewInternal(view);
 | |
|             return true;
 | |
|         }
 | |
|         if (!this.mBucket.get(indexOfChild)) {
 | |
|             return false;
 | |
|         }
 | |
|         this.mBucket.remove(indexOfChild);
 | |
|         unhideViewInternal(view);
 | |
|         this.mCallback.removeViewAt(indexOfChild);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     static class Bucket {
 | |
|         static final int BITS_PER_WORD = 64;
 | |
|         static final long LAST_BIT = Long.MIN_VALUE;
 | |
|         long mData = 0;
 | |
|         Bucket mNext;
 | |
| 
 | |
|         Bucket() {
 | |
|         }
 | |
| 
 | |
|         void set(int i) {
 | |
|             if (i < 64) {
 | |
|                 this.mData |= 1 << i;
 | |
|             } else {
 | |
|                 ensureNext();
 | |
|                 this.mNext.set(i - 64);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private void ensureNext() {
 | |
|             if (this.mNext == null) {
 | |
|                 this.mNext = new Bucket();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void clear(int i) {
 | |
|             if (i < 64) {
 | |
|                 this.mData &= ~(1 << i);
 | |
|                 return;
 | |
|             }
 | |
|             Bucket bucket = this.mNext;
 | |
|             if (bucket != null) {
 | |
|                 bucket.clear(i - 64);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         boolean get(int i) {
 | |
|             if (i < 64) {
 | |
|                 return (this.mData & (1 << i)) != 0;
 | |
|             }
 | |
|             ensureNext();
 | |
|             return this.mNext.get(i - 64);
 | |
|         }
 | |
| 
 | |
|         void reset() {
 | |
|             this.mData = 0L;
 | |
|             Bucket bucket = this.mNext;
 | |
|             if (bucket != null) {
 | |
|                 bucket.reset();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void insert(int i, boolean z) {
 | |
|             if (i >= 64) {
 | |
|                 ensureNext();
 | |
|                 this.mNext.insert(i - 64, z);
 | |
|                 return;
 | |
|             }
 | |
|             long j = this.mData;
 | |
|             boolean z2 = (Long.MIN_VALUE & j) != 0;
 | |
|             long j2 = (1 << i) - 1;
 | |
|             this.mData = ((j & (~j2)) << 1) | (j & j2);
 | |
|             if (z) {
 | |
|                 set(i);
 | |
|             } else {
 | |
|                 clear(i);
 | |
|             }
 | |
|             if (z2 || this.mNext != null) {
 | |
|                 ensureNext();
 | |
|                 this.mNext.insert(0, z2);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         boolean remove(int i) {
 | |
|             if (i >= 64) {
 | |
|                 ensureNext();
 | |
|                 return this.mNext.remove(i - 64);
 | |
|             }
 | |
|             long j = 1 << i;
 | |
|             long j2 = this.mData;
 | |
|             boolean z = (j2 & j) != 0;
 | |
|             long j3 = j2 & (~j);
 | |
|             this.mData = j3;
 | |
|             long j4 = j - 1;
 | |
|             this.mData = (j3 & j4) | Long.rotateRight((~j4) & j3, 1);
 | |
|             Bucket bucket = this.mNext;
 | |
|             if (bucket != null) {
 | |
|                 if (bucket.get(0)) {
 | |
|                     set(63);
 | |
|                 }
 | |
|                 this.mNext.remove(0);
 | |
|             }
 | |
|             return z;
 | |
|         }
 | |
| 
 | |
|         int countOnesBefore(int i) {
 | |
|             Bucket bucket = this.mNext;
 | |
|             if (bucket == null) {
 | |
|                 if (i >= 64) {
 | |
|                     return Long.bitCount(this.mData);
 | |
|                 }
 | |
|                 return Long.bitCount(this.mData & ((1 << i) - 1));
 | |
|             }
 | |
|             if (i < 64) {
 | |
|                 return Long.bitCount(this.mData & ((1 << i) - 1));
 | |
|             }
 | |
|             return bucket.countOnesBefore(i - 64) + Long.bitCount(this.mData);
 | |
|         }
 | |
| 
 | |
|         public String toString() {
 | |
|             if (this.mNext == null) {
 | |
|                 return Long.toBinaryString(this.mData);
 | |
|             }
 | |
|             return this.mNext.toString() + "xx" + Long.toBinaryString(this.mData);
 | |
|         }
 | |
|     }
 | |
| }
 |