📜  颤动的gridview垂直视口被赋予了无限的高度 (1)

📅  最后修改于: 2023-12-03 14:58:47.930000             🧑  作者: Mango

颤动的 GridView 垂直视口被赋予了无限的高度

当我们使用 GridView 来展示数据时,通常会设置一个固定的高度,以限制显示的行数。但如果我们将垂直视口(即 GridView 内容的容器)设置为无限高度,同时在 GridView 内部加入一个能够自适应高度的子控件,那么就可以达到颤动效果。

实现方法

首先,我们需要将 GridView 的垂直视口高度设置为无限。

<GridView
  android:id="@+id/gridView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:numColumns="3"
  android:verticalSpacing="8dp"
  android:horizontalSpacing="8dp"
  android:stretchMode="columnWidth"
  android:clipToPadding="false"
  android:padding="8dp"
  android:scrollbarStyle="outsideOverlay"
  android:scrollbars="vertical"
  android:overScrollMode="never"
  android:layout_marginTop="8dp" />

注意,我们需要设置 android:layout_height="wrap_content",而非具体的数值。

接着,我们需要加入一个能够自适应高度的子控件,例如 LinearLayout。

<GridView
  android:id="@+id/gridView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:numColumns="3"
  android:verticalSpacing="8dp"
  android:horizontalSpacing="8dp"
  android:stretchMode="columnWidth"
  android:clipToPadding="false"
  android:padding="8dp"
  android:scrollbarStyle="outsideOverlay"
  android:scrollbars="vertical"
  android:overScrollMode="never"
  android:layout_marginTop="8dp">

  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <!-- GridItem -->

  </LinearLayout>

</GridView>

注意,我们需要将 LinearLayout 的高度设置为 wrap_content。

接下来,在 GridView 的 Adapter 中,我们需要在 getView 方法中获取 LinearLayout,然后根据子视图数量以及列数来动态设置 LinearLayout 的高度。具体方法如下:

public View getView(int position, View convertView, ViewGroup parent) {

  // 省略其他代码...

  LinearLayout linearLayout = convertView.findViewById(R.id.layoutGridItem);
  linearLayout.removeAllViews();

  // 往 LinearLayout 中添加子视图...
  
  int columnCount = 3; // 列数
  int rowCount = (int) Math.ceil((double) data.size() / columnCount); // 行数
  int verticalSpacing = (int) getResources().getDimension(R.dimen.grid_spacing_vertical);

  int totalHeight = (gridView.getWidth() - gridView.getPaddingLeft() - gridView.getPaddingRight()) / columnCount * rowCount + verticalSpacing * (rowCount - 1);

  AbsListView.LayoutParams layoutParams = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, totalHeight);
  linearLayout.setLayoutParams(layoutParams);

  return convertView;
}

需要注意的是,在计算 totalHeight 时,我们需要先得到 GridView 的宽度,并减去左右 padding 的值,再计算出每个格子的宽度,从而得到整个 GridView 的总高度。

最后,我们可以在 GridView 上覆盖一个与其高度相等、背景透明的 View,从而达到颤动效果。

<View
  android:id="@+id/shimmerView"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:layout_below="@+id/gridView"
  android:layout_alignParentBottom="true"
  android:background="@android:color/transparent" />
结语

以上便是如何实现颤动 GridView 的方法,通过设置无限高度,以及动态设置子视图的宽高,我们可以轻松实现这一效果。