NekoX/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastLinearLayoutManager...

183 lines
6.4 KiB
Java

package org.telegram.ui.Components;
import android.content.Context;
import android.util.SparseArray;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class FillLastLinearLayoutManager extends LinearLayoutManager {
private SparseArray<RecyclerView.ViewHolder> heights = new SparseArray<>();
private int lastItemHeight = -1;
private int listHeight;
private int listWidth;
private int additionalHeight;
private RecyclerView listView;
private boolean skipFirstItem;
private boolean bind = true;
private boolean canScrollVertically = true;
boolean fixedLastItemHeight;
private int minimumHeight;
public FillLastLinearLayoutManager(Context context, int h, RecyclerView recyclerView) {
super(context);
listView = recyclerView;
additionalHeight = h;
}
public FillLastLinearLayoutManager(Context context, int orientation, boolean reverseLayout, int h, RecyclerView recyclerView) {
super(context, orientation, reverseLayout);
listView = recyclerView;
additionalHeight = h;
}
public void setAdditionalHeight(int value) {
additionalHeight = value;
calcLastItemHeight();
}
public void setSkipFirstItem() {
skipFirstItem = true;
}
public void setBind(boolean value) {
bind = value;
}
public void setCanScrollVertically(boolean value) {
canScrollVertically = value;
}
@Override
public boolean canScrollVertically() {
return canScrollVertically;
}
@SuppressWarnings("unchecked")
private void calcLastItemHeight() {
if (listHeight <= 0) {
return;
}
RecyclerView.Adapter adapter = listView.getAdapter();
if (adapter == null) {
return;
}
int count = adapter.getItemCount() - 1;
int allHeight = 0;
int firstItemHeight = 0;
for (int a = skipFirstItem ? 1 : 0; a < count; a++) {
int type = adapter.getItemViewType(a);
RecyclerView.ViewHolder holder = heights.get(type, null);
if (holder == null) {
holder = adapter.createViewHolder(listView, type);
heights.put(type, holder);
if (holder.itemView.getLayoutParams() == null) {
holder.itemView.setLayoutParams(generateDefaultLayoutParams());
}
}
if (bind) {
adapter.onBindViewHolder(holder, a);
}
final RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) holder.itemView.getLayoutParams();
final int widthSpec = getChildMeasureSpec(listWidth, getWidthMode(), getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, lp.width, canScrollHorizontally());
final int heightSpec = getChildMeasureSpec(listHeight, getHeightMode(), getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, lp.height, canScrollVertically());
holder.itemView.measure(widthSpec, heightSpec);
allHeight += holder.itemView.getMeasuredHeight();
if (a == 0) {
firstItemHeight = holder.itemView.getMeasuredHeight();
}
if (fixedLastItemHeight) {
if (allHeight >= listHeight + firstItemHeight) {
break;
}
} else {
if (allHeight >= listHeight) {
break;
}
}
}
if (fixedLastItemHeight) {
lastItemHeight = Math.max(minimumHeight, firstItemHeight + (listHeight - allHeight - additionalHeight - listView.getPaddingBottom()));
} else {
lastItemHeight = Math.max(minimumHeight, listHeight - allHeight - additionalHeight - listView.getPaddingBottom());
}
}
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
int lastHeight = listHeight;
listWidth = View.MeasureSpec.getSize(widthSpec);
listHeight = View.MeasureSpec.getSize(heightSpec);
if (lastHeight != listHeight) {
calcLastItemHeight();
}
super.onMeasure(recycler, state, widthSpec, heightSpec);
}
@Override
public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter) {
heights.clear();
calcLastItemHeight();
super.onAdapterChanged(oldAdapter, newAdapter);
}
@Override
public void onItemsChanged(RecyclerView recyclerView) {
heights.clear();
calcLastItemHeight();
super.onItemsChanged(recyclerView);
}
@Override
public void onItemsAdded(RecyclerView recyclerView, int positionStart, int itemCount) {
super.onItemsAdded(recyclerView, positionStart, itemCount);
calcLastItemHeight();
}
@Override
public void onItemsRemoved(RecyclerView recyclerView, int positionStart, int itemCount) {
super.onItemsRemoved(recyclerView, positionStart, itemCount);
calcLastItemHeight();
}
@Override
public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCount) {
super.onItemsMoved(recyclerView, from, to, itemCount);
calcLastItemHeight();
}
@Override
public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) {
super.onItemsUpdated(recyclerView, positionStart, itemCount);
calcLastItemHeight();
}
@Override
public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount, Object payload) {
super.onItemsUpdated(recyclerView, positionStart, itemCount, payload);
calcLastItemHeight();
}
@Override
public void measureChildWithMargins(View child, int widthUsed, int heightUsed) {
RecyclerView.ViewHolder holder = listView.findContainingViewHolder(child);
int pos = holder.getAdapterPosition();
if (pos == getItemCount() - 1) {
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
layoutParams.height = Math.max(lastItemHeight, 0);
}
super.measureChildWithMargins(child, 0, 0);
}
public void setFixedLastItemHeight() {
fixedLastItemHeight = true;
}
public void setMinimumLastViewHeight(int height) {
minimumHeight = height;
}
}