Android GridView 单元格顺序改变

Android GridView cell sequence changing

我在填充 GridView 时遇到了一个非常奇怪的(对我来说)问题 - 当它第一次加载时一切看起来都很好,但滚动最终导致单元格中的数据移动到其他位置。在下面的示例中,我只有一个数字 0-800 的 ArrayList 和一个 8 列网格。加载时,0-7 在第一行,8-15 在第二行,依此类推,每行的第一个单元格中的值不同。但是滚动后第一列的值会改变。这是代码 - 它让我发疯!

MainActivity.java:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    ArrayList<Integer> positions = new ArrayList<Integer>();
    for(int i=0;i<800;i++) {
        positions.add(i);
    }

    GridView gvVals = findViewById(R.id.gvVals);
    CellAdapter adapter = new CellAdapter(this, new ArrayList<Integer>());
    adapter = new CellAdapter(this, positions);
    gvVals.setAdapter(adapter);
}

单元格 Adapter.java:

public class CellAdapter extends ArrayAdapter<Integer> {
private Context context;
public CellAdapter(Context context, ArrayList<Integer> vals) {
    super(context, 0, vals);
    this.context = context;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View v;
    if (convertView == null) {
        v = LayoutInflater.from(getContext()).inflate(R.layout.activity_cell, parent, false);
    } else {
        v = (View)convertView;
    }

    TextView tvDay = v.findViewById(R.id.tvVal);
    tvDay.setVisibility(View.VISIBLE);

    if(position % 8 == 0) {
        tvDay.setText("ST:"+position);
    }
    else
    {
        v.findViewById(R.id.btnM).setVisibility(View.VISIBLE);
        ((Button)v.findViewById(R.id.btnM)).setText(position + " ");
        tvDay.setText(" ");
    }
    return v;
}

ActivityMain.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
    android:id="@+id/gvVals"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="60dp"
    android:numColumns="8"/>
</android.support.constraint.ConstraintLayout>

ActivityCell.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
    android:id="@+id/tvVal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text=""
    android:visibility="invisible"/>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">
    <Button
        android:id="@+id/btnM"
        android:layout_width="0dp"
        android:layout_weight=".34"
        android:layout_height="20dp"
        android:text="M"
        android:background="@color/colorAccent"
        android:minWidth="0dp"
        android:visibility="invisible"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>

首次打开应用时的 GridView

向下滚动几行然后返回

改变这个:

TextView tvDay = v.findViewById(R.id.tvVal);
tvDay.setVisibility(View.VISIBLE);

if(position % 8 == 0) {
    tvDay.setText("ST:"+position);
}
else
{
    v.findViewById(R.id.btnM).setVisibility(View.VISIBLE);
    ((Button)v.findViewById(R.id.btnM)).setText(position + " ");
    tvDay.setText(" ");
}

对此:

boolean firstColumn = position % 8 == 0;

TextView tvDay = v.findViewById(R.id.tvVal);
tvDay.setVisibility(firstColumn ? View.VISIBLE : View.GONE);

Button btnM = v.findViewById(R.id.btnM);
btnM.setVisibility(firstColumn ? View.GONE : View.VISIBLE);

if(firstColumn) {
    tvDay.setText("ST:"+position);
}
else
{
    btnM.setText(position + " ");
}

使用 RecyclerView 时,请务必确保每次都更新每个视图。这是因为旧的视图持有者会被回收,所以如果您只在某些时候做某事,它可能会被覆盖或覆盖 "expected" 行为。

以前,如果 btnM 不是第一列,则您将其设置为可见,但如果 第一列,则您不会将其设置为不可见.