You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android动态布局增删问题求助:删错行、数据存储与数量限制

Fixing Your Dynamic Row Add/Delete Issues in Android

Hey there! Let's work through your three main issues step by step. I'll provide updated code and explain each change so you understand why it works.

1. Fixing the Wrong Row Deletion Problem

The root cause here is that you were using findViewById(R.id.button2) directly in the Add click listener, which always grabs the first Delete button in your layout instead of the one belonging to the newly inflated row. You need to find the Delete button within the specific row view you just created.

Here's the corrected code snippet for the Add button click listener, plus a helper method to keep row numbers accurate:

add.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // Check max row limit first (covered in point 3)
        if (data.getChildCount() >= 20) {
            Toast.makeText(MainActivity.this, "Maximum 20 rows allowed", Toast.LENGTH_SHORT).show();
            return;
        }

        try {
            LayoutInflater li = LayoutInflater.from(MainActivity.this);
            final View view = li.inflate(R.layout.tryandtest, data, false); // Attach to parent properly
            data.addView(view);

            // Set spinner adapter for this row
            Spinner s = view.findViewById(R.id.spinner);
            s.setAdapter(adapter2);

            // Find Delete button INSIDE the current row view
            Button delete = view.findViewById(R.id.button2);
            delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // Check min row limit before deleting
                    if (data.getChildCount() <= 1) {
                        Toast.makeText(MainActivity.this, "At least 1 row must remain", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    data.removeView(view);
                    // Update row numbers after deletion
                    updateRowNumbers(data);
                }
            });

            // Update row numbers after adding a new row
            updateRowNumbers(data);
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("inflate exception", e.toString());
        }
    }
});

Helper method to keep row labels (like "1", "2") up-to-date:

private void updateRowNumbers(LinearLayout parentLayout) {
    for (int i = 0; i < parentLayout.getChildCount(); i++) {
        View row = parentLayout.getChildAt(i);
        TextView rowNumber = row.findViewById(R.id.textView);
        rowNumber.setText(String.valueOf(i + 1));
    }
}

2. Saving All Group IDs to ArrayList on Start Button Click

First, add a Start button to your UI XML if you haven't already:

<Button
    android:id="@+id/button_start"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Start"
    android:layout_gravity="center_horizontal"/>

Then, set up the click listener to collect all selected Group IDs:

Button startBtn = findViewById(R.id.button_start);
startBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ArrayList<String> groupIdsList = new ArrayList<>();
        LinearLayout dataLayout = findViewById(R.id.leanierLayout_test);

        for (int i = 0; i < dataLayout.getChildCount(); i++) {
            View row = dataLayout.getChildAt(i);
            Spinner spinner = row.findViewById(R.id.spinner);
            String selectedGroupId = spinner.getSelectedItem().toString();
            groupIdsList.add(selectedGroupId);
        }

        // Use the list as needed (example: log or show toast)
        Log.d("Group IDs", "Saved IDs: " + groupIdsList.toString());
        Toast.makeText(MainActivity.this, "Saved " + groupIdsList.size() + " group IDs", Toast.LENGTH_SHORT).show();
    }
});

3. Implementing Add/Delete Limits

We already added these checks in the code above, but let's recap:

  • Max 20 rows: Before inflating a new row, check data.getChildCount() >= 20 and show a toast if true.
  • Min 1 row: Before deleting a row, check data.getChildCount() <= 1 and show a toast if true.

These checks prevent users from exceeding your row limits and ensure you never end up with zero rows.

Full Updated onCreate Method

Here's the complete onCreate method with all fixes included:

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

    // Assuming groupId is your existing list of spinner options
    ArrayAdapter<String> adapter2 = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, groupId);
    adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

    Button add = findViewById(R.id.button1);
    final LinearLayout data = findViewById(R.id.leanierLayout_test);

    // Add initial row (since we need at least 1 row)
    addInitialRow(data, adapter2);

    add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (data.getChildCount() >= 20) {
                Toast.makeText(MainActivity.this, "Maximum 20 rows allowed", Toast.LENGTH_SHORT).show();
                return;
            }

            try {
                LayoutInflater li = LayoutInflater.from(MainActivity.this);
                final View view = li.inflate(R.layout.tryandtest, data, false);
                data.addView(view);

                Spinner s = view.findViewById(R.id.spinner);
                s.setAdapter(adapter2);

                Button delete = view.findViewById(R.id.button2);
                delete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (data.getChildCount() <= 1) {
                            Toast.makeText(MainActivity.this, "At least 1 row must remain", Toast.LENGTH_SHORT).show();
                            return;
                        }
                        data.removeView(view);
                        updateRowNumbers(data);
                    }
                });

                updateRowNumbers(data);
            } catch (Exception e) {
                e.printStackTrace();
                Log.d("inflate exception", e.toString());
            }
        }
    });

    Button startBtn = findViewById(R.id.button_start);
    startBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ArrayList<String> groupIdsList = new ArrayList<>();
            for (int i = 0; i < data.getChildCount(); i++) {
                View row = data.getChildAt(i);
                Spinner spinner = row.findViewById(R.id.spinner);
                groupIdsList.add(spinner.getSelectedItem().toString());
            }
            Log.d("Group IDs", "Saved: " + groupIdsList);
            Toast.makeText(MainActivity.this, "Saved " + groupIdsList.size() + " entries", Toast.LENGTH_SHORT).show();
        }
    });
}

private void addInitialRow(LinearLayout parent, ArrayAdapter<String> adapter) {
    LayoutInflater li = LayoutInflater.from(this);
    View view = li.inflate(R.layout.tryandtest, parent, false);
    parent.addView(view);

    Spinner s = view.findViewById(R.id.spinner);
    s.setAdapter(adapter);

    Button delete = view.findViewById(R.id.button2);
    delete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (parent.getChildCount() <= 1) {
                Toast.makeText(MainActivity.this, "At least 1 row must remain", Toast.LENGTH_SHORT).show();
                return;
            }
            parent.removeView(view);
            updateRowNumbers(parent);
        }
    });

    updateRowNumbers(parent);
}

private void updateRowNumbers(LinearLayout parentLayout) {
    for (int i = 0; i < parentLayout.getChildCount(); i++) {
        View row = parentLayout.getChildAt(i);
        TextView rowNumber = row.findViewById(R.id.textView);
        rowNumber.setText(String.valueOf(i + 1));
    }
}

A few extra notes:

  • I changed getApplicationContext() to MainActivity.this in the LayoutInflater to avoid potential context issues.
  • Added addInitialRow to ensure your layout starts with at least one row (since we can't delete all rows).
  • Used li.inflate(R.layout.tryandtest, data, false) instead of null to properly attach the row to the parent layout while avoiding immediate layout passes.

内容的提问来源于stack exchange,提问作者Shubham Chander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:43:11