Android Studio中点击按钮动态创建LinearLayout布局的实现
实现方案
1. 重构布局文件
先把需要重复的产品行抽成独立布局item_product.xml,新增删除按钮:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/background_round" android:orientation="vertical" android:padding="5dp" android:layout_marginBottom="10dp"> <!-- 产品选择栏 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal"> <AutoCompleteTextView android:id="@+id/tv_product" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" android:gravity="left" android:inputType="text" android:hint="Enter Product"/> <Button android:id="@+id/btn_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="删除" android:textColor="@color/white" android:background="@color/red"/> </LinearLayout> <!-- 数量、价格、规格栏 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight=".5" android:orientation="vertical"> <EditText android:id="@+id/prod_qty" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Enter Quantity" android:gravity="left" android:inputType="number"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight=".5" android:orientation="vertical"> <EditText android:id="@+id/prod_price" android:layout_width="match_parent" android:layout_height="wrap_content" android:editable="false" android:focusable="false" android:focusableInTouchMode="false" android:hint="Prod Price" android:gravity="left" android:inputType="none"/> </LinearLayout> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight=".5" android:orientation="vertical"> <EditText android:id="@+id/prod_specs" android:layout_width="match_parent" android:layout_height="wrap_content" android:editable="false" android:focusable="false" android:focusableInTouchMode="false" android:hint="Prod Specs" android:gravity="left" android:inputType="none"/> </LinearLayout> </LinearLayout> </LinearLayout>
修改原Fragment布局fragment_product.xml,改成容纳多行的容器,将添加按钮移到容器下方:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <!-- 动态产品行容器 --> <ScrollView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"> <LinearLayout android:id="@+id/container_products" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"/> </ScrollView> <!-- 添加新产品按钮 --> <Button android:id="@+id/btn_add_product" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add New Product" android:textColor="@color/white" android:layout_marginTop="10dp"/> </LinearLayout>
2. 创建产品实体类
存储从JSON读取的产品信息:
public class Product { private String name; private String price; private String specs; public Product(String name, String price, String specs) { this.name = name; this.price = price; this.specs = specs; } public String getName() { return name; } public String getPrice() { return price; } public String getSpecs() { return specs; } }
3. 读取本地JSON文件
假设products.json放在assets文件夹下,内容示例:
[ {"name":"Product A", "price":"100", "specs":"Size M"}, {"name":"Product B", "price":"200", "specs":"Size L"}, {"name":"Product C", "price":"150", "specs":"Size S"} ]
实现读取解析逻辑:
private List<Product> loadProductsFromJson() { List<Product> productList = new ArrayList<>(); try { InputStream is = getActivity().getAssets().open("products.json"); int size = is.available(); byte[] buffer = new byte[size]; is.read(buffer); is.close(); String json = new String(buffer, StandardCharsets.UTF_8); JSONArray jsonArray = new JSONArray(json); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObj = jsonArray.getJSONObject(i); String name = jsonObj.getString("name"); String price = jsonObj.getString("price"); String specs = jsonObj.getString("specs"); productList.add(new Product(name, price, specs)); } } catch (IOException | JSONException e) { e.printStackTrace(); } return productList; }
4. Fragment核心逻辑
实现动态添加/删除布局、产品选择自动填充功能:
public class ProductFragment extends Fragment { private LinearLayout containerProducts; private List<Product> productList; private ArrayAdapter<String> productAdapter; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_product, container, false); containerProducts = view.findViewById(R.id.container_products); Button btnAdd = view.findViewById(R.id.btn_add_product); // 加载产品数据并初始化适配器 productList = loadProductsFromJson(); List<String> productNames = new ArrayList<>(); for (Product p : productList) { productNames.add(p.getName()); } productAdapter = new ArrayAdapter<>(getActivity(), android.R.layout.simple_dropdown_item_1line, productNames); // 默认添加一行产品 addProductRow(); // 添加按钮点击事件 btnAdd.setOnClickListener(v -> addProductRow()); return view; } // 动态添加产品行 private void addProductRow() { LayoutInflater inflater = LayoutInflater.from(getActivity()); View productRow = inflater.inflate(R.layout.item_product, containerProducts, false); // 获取行内控件 AutoCompleteTextView tvProduct = productRow.findViewById(R.id.tv_product); EditText etPrice = productRow.findViewById(R.id.prod_price); EditText etSpecs = productRow.findViewById(R.id.prod_specs); Button btnDelete = productRow.findViewById(R.id.btn_delete); // 设置产品选择适配器 tvProduct.setAdapter(productAdapter); // 选中产品后自动填充价格和规格 tvProduct.setOnItemClickListener((parent, view, position, id) -> { String selectedName = (String) parent.getItemAtPosition(position); for (Product p : productList) { if (p.getName().equals(selectedName)) { etPrice.setText(p.getPrice()); etSpecs.setText(p.getSpecs()); break; } } }); // 删除当前行 btnDelete.setOnClickListener(v -> containerProducts.removeView(productRow)); containerProducts.addView(productRow); } // 读取本地JSON方法(同步骤3) private List<Product> loadProductsFromJson() { // ... 实现代码 ... } }
关键说明
- 将重复布局抽成独立item,避免冗余代码,方便动态生成
- 使用
LayoutInflater加载布局,复用XML中定义的样式和属性 - 每行单独设置监听,确保删除、产品选择逻辑互不干扰
- 本地JSON文件放在
assets目录,通过AssetManager读取解析
内容的提问来源于stack exchange,提问作者Moeez
相关产品推荐
相关产品推荐

