gpt4 book ai didi

java - 如何知道在不加载数据的情况下在 RecyclerView 中可以看到的最大 ItemView 数量?

转载 作者:太空狗 更新时间:2023-10-29 13:03:01 27 4
gpt4 key购买 nike

我有一个用于 RecyclerView 的分页算法,如果完成 Scroll,滚动监听器将触发并加载更多元素。最初,我为我的 RecyclerView 分配了一些元素以加载到服务器的请求中默认情况下为 20,它具有固定大小(不是 wrap_content)。

我需要知道在加载数据之前在定义的 RecyclerView 的宽度/高度中可以看到的项目数量,以确定在初始加载时要请求的项目数量, 鉴于某些设备上有 20 个项目不足以激活滚动的监听器并加载更多元素

这还没有考虑 View 的额外属性,例如 padding、margin 等 ...

解决方案可以使用 Java Android 或 Xamarin Android(不是 Forms)C#。

更新:

为了给你一个线索,我已经尝试过这个并且它对我有用,只有当我在 RecyclerView 的大小被分配时调用它,在 OnLayoutChange:

public int GetMaxVisibleItemCountFromRecyclerView(RecyclerView recyclerView)
{
if (recyclerView == null) return 0;

int Width = recyclerView.Width;
int Height = recyclerView.Height;

if (Width == 0 || Height == 0)
return 0;

var layoutManager = recyclerView.GetLayoutManager() as GridLayoutManager;

if (layoutManager == null) return 0;

int widthRatio = Width / layoutManager.SpanCount;
int quantity = (Height / widthRatio) * layoutManager.SpanCount;

return quantity;

}

此解决方案仅适用于使用 GridLayoutManagerRecyclerViews。我还有其他具有定义大小的 RecyclerViews,它们也使用带有 LinearLayoutManager 的分页算法。

我需要一个类似的解决方案,它适用于 RecyclerView 的任何 LayoutManager,并且不必在 OnLayoutChange 内部调用,这可能吗?

最佳答案

与其尝试复制 RecyclerView 为计算布局所做的计算,不如让系统为您完成工作。以下示例让 RecyclerView 布置一个项目并从中获取测量值。虚拟项目不显示,仅用于测量。

这种方法的优点是我们不必复制 RecyclerView 测量项目的方法。所有关键测量都被考虑在内,包括填充、边距和装饰。

以下示例显示了如何为 GridLayoutManagerLinearLayoutManager 完成此操作。 StaggeredGridLayoutManagerFlexboxLayoutManager 是特例,此处不予考虑。

这是一个简短的视频,展示了这个演示应用程序的结果,显示仅加载了一页项目。

enter image description here

MainActivity.java

public class MainActivity extends AppCompatActivity {
private List<String> mItems = new ArrayList<>();
private RecyclerView mRecycler;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecycler = findViewById(R.id.recyclerView);

// Sample for vertical LinearLayoutManager.
LinearLayoutManager layoutManager = new LinearLayoutManager(this);

// Sample for GridLayoutManager with 4 spans. Each item comsumes 2 spans.
// GridLayoutManager layoutManager = new GridLayoutManager(this, 4);
// layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
// @Override
// public int getSpanSize(int position) {
// return 2;
// }
// });

// Add single dummy item that will be measured but not be displayed.
mItems.add("Dummy item");
RecyclerViewAdapter mAdapter = new RecyclerViewAdapter(mItems);
mRecycler.setLayoutManager(layoutManager);
mRecycler.setAdapter(mAdapter);

// Take measurements in OnPreDraawListener(). This could also be accomplished with
// mRecyclerView.post(new Runnable()...)
mRecycler.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mRecycler.getViewTreeObserver().removeOnPreDrawListener(this);

// RecyclerView is laid out with single dummy entry. Get how many of this type
// of item can fit into the visible portion of the RecyclerView.
final int nItems = getInitialLoadCount(mRecycler);
Log.d(TAG, "<<<<Items per page=" + nItems);

// Don't need the dummy entry any more.
mItems.clear();
mRecycler.getAdapter().notifyDataSetChanged();
mItems = new ArrayList<>();

// Fake load...
loadInitialItems(nItems);
return false;
}
});
}

// Determine how many items will fill one screen of the RecyclerView. Call with the
// RecyclerView loaded with at least one item for measurement.
private int getInitialLoadCount(RecyclerView recyclerView) {
int itemsToLoad = 0;
RecyclerView.LayoutManager lm = recyclerView.getLayoutManager();
View firstChild = recyclerView.getChildAt(0);

if (lm instanceof LinearLayoutManager) {
Rect bounds = new Rect();
recyclerView.getDecoratedBoundsWithMargins(firstChild, bounds);
if (lm.canScrollVertically()) {
int recyclerHeightForItems = recyclerView.getHeight() - recyclerView.getPaddingTop()
- recyclerView.getPaddingBottom();
itemsToLoad = (recyclerHeightForItems + bounds.height() - 1) / bounds.height();
} else if (lm.canScrollHorizontally()) {
int recyclerWidthForItems = recyclerView.getWidth() - recyclerView.getPaddingLeft()
- recyclerView.getPaddingRight();
itemsToLoad = (recyclerWidthForItems + bounds.width() - 1) / bounds.width();
}
if (lm instanceof GridLayoutManager) {
// Adjust for GridLayoutManager. All items should to be the same number of spans.
GridLayoutManager glm = (GridLayoutManager) lm;
itemsToLoad *= glm.getSpanCount() / glm.getSpanSizeLookup().getSpanSize(0);
}
}
return itemsToLoad;
}

private void loadInitialItems(final int itemCount) {
// Simulate load of nItems...should be on non-UI thread.
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 1; i <= itemCount; i++) {
sleep(250);
mItems.add("Item #" + i);
}
runOnUiThread(new Runnable() {
@Override
public void run() {
mRecycler.swapAdapter(new RecyclerViewAdapter(mItems), true);
}
});
}
}).start();
}

private static final String TAG = "MainActivity";
}

关于java - 如何知道在不加载数据的情况下在 RecyclerView 中可以看到的最大 ItemView 数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52910380/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com