android通过代码动态添加和删除控件

1.概述

android开发当中有可能会碰到以下这种情况,某个页面,内容不确定,根据用户需求增加或减少相应控件数。这种情况一般发生在编辑类页面当中,比如你的应用包含用户发帖功能,其内容组织结构和多少是可变的。

本文实现了一个动态添加和删除控件的简单例子!先上截图:

截图1






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:存储了当前所包含的所有“添加”和“删除”按钮对象,在发生添加或删除事件时,用于定位触发事件位置。
其他内容可以看代码注释,详细信息可以下载源码跑一跑工程!

3.源码


源码下载地址:



评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符 “速评一下”
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页