1.概述
android开发当中有可能会碰到以下这种情况,某个页面,内容不确定,根据用户需求增加或减少相应控件数。这种情况一般发生在编辑类页面当中,比如你的应用包含用户发帖功能,其内容组织结构和多少是可变的。
本文实现了一个动态添加和删除控件的简单例子!先上截图:
2.代码实现
(1)布局文件activity_main.xml
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@android:color/darker_gray"
- tools:context=".MainActivity" >
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none" >
- <LinearLayout
- android:id="@+id/content_view"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:isScrollContainer="true"
- android:orientation="vertical"
- android:padding="10.0dip" >
- <LinearLayout
- android:id="@+id/ll_one"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dip"
- android:background="#FFA2CD5A"
- android:orientation="vertical"
- android:padding="5dip" >
- <EditText
- android:id="@+id/et_content1"
- android:layout_width="match_parent"
- android:layout_height="80dip"
- android:background="#FFFFFFFF"
- android:gravity="left"
- android:inputType="textMultiLine"
- android:paddingLeft="5dip"
- android:textSize="16sp" />
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dip" >
- <ImageButton
- android:id="@+id/ibn_add1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:background="@drawable/ic_add" />
- <!--
- <ImageButton
- android:id="@+id/ibn_del1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="10dip"
- android:layout_toLeftOf="@id/ibn_add1"
- android:background="@drawable/ic_delete" />
- -->
- </RelativeLayout>
- </LinearLayout>
- </LinearLayout>
- </ScrollView>
- </RelativeLayout>
简单来讲,一个ScrollView和内嵌的LinearLayout的组合实现了本例。LinearLayout内部控件可增可减,因为其包含在ScrollView里,所以内容超出页面显示范围时可以滚动。
该布局文件显示效果如上面第一个截图所示,包含一个编辑框(EditText)和“添加”按钮。
(2)MainActivity文件
- package com.example.androiddynamiclayout;
- import java.util.LinkedList;
- import android.os.Bundle;
- import android.app.Activity;
- import android.graphics.Color;
- import android.text.InputType;
- import android.view.Gravity;
- import android.view.Menu;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.EditText;
- import android.widget.ImageButton;
- import android.widget.LinearLayout;
- import android.widget.RelativeLayout;
- public class MainActivity extends Activity {
- // 外围的LinearLayout容器
- private LinearLayout llContentView;
- private EditText etContent1;
- // “+”按钮控件List
- private LinkedList<ImageButton> listIBTNAdd;
- // “+”按钮ID索引
- private int btnIDIndex = 1000;
- // “-”按钮控件List
- private LinkedList<ImageButton> listIBTNDel;
- private int iETContentHeight = 0; // EditText控件高度
- private float fDimRatio = 1.0f; // 尺寸比例(实际尺寸/xml文件里尺寸)
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initCtrl();
- }
- /**
- * 初始化控件
- */
- private void initCtrl()
- {
- llContentView = (LinearLayout) this.findViewById(R.id.content_view);
- etContent1 = (EditText) this.findViewById(R.id.et_content1);
- listIBTNAdd = new LinkedList<ImageButton>();
- listIBTNDel = new LinkedList<ImageButton>();
- // “+”按钮(第一个)
- ImageButton ibtnAdd1 = (ImageButton) this.findViewById(R.id.ibn_add1);
- ibtnAdd1.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // 获取尺寸变化比例
- iETContentHeight = etContent1.getHeight();
- fDimRatio = iETContentHeight / 80;
- addContent(v);
- }
- });
- listIBTNAdd.add(ibtnAdd1);
- listIBTNDel.add(null); // 第一组隐藏了“-”按钮,所以为null
- }
- /**
- * 添加一组新控件
- * @param v 事件触发控件,其实就是触发添加事件对应的“+”按钮
- */
- private void addContent(View v) {
- if (v == null) {
- return;
- }
- // 判断第几个“+”按钮触发了事件
- int iIndex = -1;
- for (int i = 0; i < listIBTNAdd.size(); i++) {
- if (listIBTNAdd.get(i) == v) {
- iIndex = i;
- break;
- }
- }
- if (iIndex >= 0) {
- // 控件实际添加位置为当前触发位置点下一位
- iIndex += 1;
- // 开始添加控件
- // 1.创建外围LinearLayout控件
- LinearLayout layout = new LinearLayout(MainActivity.this);
- LinearLayout.LayoutParams lLayoutlayoutParams = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- // 设置margin
- lLayoutlayoutParams.setMargins(0, (int) (fDimRatio * 5), 0, 0);
- layout.setLayoutParams(lLayoutlayoutParams);
- // 设置属性
- layout.setBackgroundColor(Color.argb(255, 162, 205, 90)); // #FFA2CD5A
- layout.setPadding((int) (fDimRatio * 5), (int) (fDimRatio * 5),
- (int) (fDimRatio * 5), (int) (fDimRatio * 5));
- layout.setOrientation(LinearLayout.VERTICAL);
- // 2.创建内部EditText控件
- EditText etContent = new EditText(MainActivity.this);
- LinearLayout.LayoutParams etParam = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, iETContentHeight);
- etContent.setLayoutParams(etParam);
- // 设置属性
- etContent.setBackgroundColor(Color.argb(255, 255, 255, 255)); // #FFFFFFFF
- etContent.setGravity(Gravity.LEFT);
- etContent.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);
- etContent.setPadding((int) (fDimRatio * 5), 0, 0, 0);
- etContent.setTextSize(16);
- // 将EditText放到LinearLayout里
- layout.addView(etContent);
- // 3.创建“+”和“-”按钮外围控件RelativeLayout
- RelativeLayout rlBtn = new RelativeLayout(MainActivity.this);
- RelativeLayout.LayoutParams rlParam = new RelativeLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- // rlParam.setMargins(0, (int) (fDimRatio * 5), 0, 0);
- rlBtn.setPadding(0, (int) (fDimRatio * 5), 0, 0);
- rlBtn.setLayoutParams(rlParam);
- // 4.创建“+”按钮
- ImageButton btnAdd = new ImageButton(MainActivity.this);
- RelativeLayout.LayoutParams btnAddParam = new RelativeLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- // 靠右放置
- btnAddParam.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
- btnAdd.setLayoutParams(btnAddParam);
- // 设置属性
- btnAdd.setBackgroundResource(R.drawable.ic_add);
- btnAdd.setId(btnIDIndex);
- // 设置点击操作
- btnAdd.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- addContent(v);
- }
- });
- // 将“+”按钮放到RelativeLayout里
- rlBtn.addView(btnAdd);
- listIBTNAdd.add(iIndex, btnAdd);
- // 5.创建“-”按钮
- ImageButton btnDelete = new ImageButton(MainActivity.this);
- btnDelete.setBackgroundResource(R.drawable.ic_delete);
- RelativeLayout.LayoutParams btnDeleteAddParam = new RelativeLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- btnDeleteAddParam.setMargins(0, 0, (int) (fDimRatio * 5), 0);
- // “-”按钮放在“+”按钮左侧
- btnDeleteAddParam.addRule(RelativeLayout.LEFT_OF, btnIDIndex);
- btnDelete.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- deleteContent(v);
- }
- });
- // 将“-”按钮放到RelativeLayout里
- rlBtn.addView(btnDelete, btnDeleteAddParam);
- listIBTNDel.add(iIndex, btnDelete);
- // 6.将RelativeLayout放到LinearLayout里
- layout.addView(rlBtn);
- // 7.将layout同它内部的所有控件加到最外围的llContentView容器里
- llContentView.addView(layout, iIndex);
- btnIDIndex++;
- }
- }
- /**
- * 删除一组控件
- * @param v 事件触发控件,其实就是触发删除事件对应的“-”按钮
- */
- private void deleteContent(View v) {
- if (v == null) {
- return;
- }
- // 判断第几个“-”按钮触发了事件
- int iIndex = -1;
- for (int i = 0; i < listIBTNDel.size(); i++) {
- if (listIBTNDel.get(i) == v) {
- iIndex = i;
- break;
- }
- }
- if (iIndex >= 0) {
- listIBTNAdd.remove(iIndex);
- listIBTNDel.remove(iIndex);
- // 从外围llContentView容器里删除第iIndex控件
- llContentView.removeViewAt(iIndex);
- }
- }
- /*@Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.activity_main, menu);
- return true;
- } */
- }
浏览这段代码需要注意以下几两点:
1.llContentView:这个变量对应的是上面布局文件提到的那个LinearLayout,通过llContentView.addView(layout, iIndex)往某一位置添加子控件,通过llContentView.removeViewAt(iIndex)删除某一位置上的子控件。
2.List对象listIBTNAdd和listIBTNDel:存储了当前所包含的所有“添加”和“删除”按钮对象,在发生添加或删除事件时,用于定位触发事件位
置。
原文地址:https://blog.csdn.net/chadeltu/article/details/42390047