Hướng dẫn này trình bày cách tạo và thêm Button (hoặc bất kỳ View nào) vào layout hoàn toàn bằng code Java/Kotlin tại runtime, thay vì khai báo trong XML. Kỹ thuật này hữu ích khi số lượng view không xác định trước (dựa trên dữ liệu từ server, user input...).
Các bước thực hiện
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project và điền thông tin cần thiết.
Bước 2: Layout (res/layout/activity_main.xml)
Chỉ cần một container (ViewGroup) rỗng với ID để thêm view con vào.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:id="@+id/relativeLayout"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
</RelativeLayout>
Bước 3: Code MainActivity (src/MainActivity.java)
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
RelativeLayout relativeLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
relativeLayout = findViewById(R.id.relativeLayout);
// 1. Tạo Button mới
Button button = new Button(this);
button.setText("Button tạo động");
// 2. Thiết lập LayoutParams (PHẢI khớp với loại ViewGroup CHA - RelativeLayout)
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
// Có thể thêm rules cho RelativeLayout:
// params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);
// params.addRule(RelativeLayout.BELOW, R.id.someOtherView);
button.setLayoutParams(params);
// 3. Gán sự kiện click
button.setOnClickListener(v -> {
Toast.makeText(MainActivity.this, "Button này được tạo động bằng code!", Toast.LENGTH_SHORT).show();
});
// 4. Thêm vào parent
if (relativeLayout != null) {
relativeLayout.addView(button);
}
}
}
Bước 4: Cấu hình AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.com.sample">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Chạy ứng dụng
Kết nối thiết bị, nhấn Run. Button "Button tạo động" sẽ xuất hiện ở giữa màn hình (do parent RelativeLayout có gravity=center). Nhấn vào nó sẽ hiện Toast.

Các lưu ý quan trọng khi tạo View động
1. LayoutParams phải khớp ViewGroup CHA
| ViewGroup cha | LayoutParams class |
|---|---|
| LinearLayout | LinearLayout.LayoutParams |
| RelativeLayout | RelativeLayout.LayoutParams |
| FrameLayout | FrameLayout.LayoutParams |
| ConstraintLayout | ConstraintLayout.LayoutParams |
| GridLayout | GridLayout.LayoutParams |
| CoordinatorLayout | CoordinatorLayout.LayoutParams |
Sai LayoutParams → ClassCastException tại runtime.
2. Thêm nhiều View - cân nhắc RecyclerView
Nếu cần thêm nhiều view cùng loại (danh sách, lưới), KHÔNG nên tạo thủ công trong vòng lặp. Hãy dùng:
- RecyclerView + Adapter (chuẩn, hiệu năng tốt, view recycling)
- ListView (cũ)
- FlowLayout / FlexboxLayout cho layout dòng chảy
3. Xóa View động
// Xóa 1 view cụ thể relativeLayout.removeView(button); // Xóa tất cả con relativeLayout.removeAllViews();
4. Tùy chỉnh View nâng cao
Button button = new Button(this);
button.setText("Tùy chỉnh");
button.setTextSize(18);
button.setTextColor(Color.WHITE);
button.setBackgroundColor(Color.parseColor("#2196F3"));
button.setPadding(32, 16, 32, 16);
button.setAllCaps(false); // Tắt tự động viết hoa
button.setId(View.generateViewId()); // Tạo ID duy nhất (API 17+) để findViewById sau này
5. Thêm vào vị trí cụ thể (index)
// Thêm vào đầu (index 0) relativeLayout.addView(button, 0, params); // Thêm sau view khác (cần ID của view kia) RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(...); params.addRule(RelativeLayout.BELOW, R.id.existingView); relativeLayout.addView(button, params);
Kotlin Extension Function (Rút gọn code)
// Extension function cho ViewGroup
fun ViewGroup.addButton(text: String, click: (View) -> Unit): Button {
val button = Button(context).apply {
this.text = text
layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
setOnClickListener(click)
}
addView(button)
return button
}
// Sử dụng:
relativeLayout.addButton("Nút 1") { toast("Nút 1") }
relativeLayout.addButton("Nút 2") { toast("Nút 2") }
Tóm tắt
- Tạo View:
new Button(context) - Set LayoutParams phù hợp ViewGroup cha
- Gán listener, tùy chỉnh thuộc tính
parent.addView(view)hoặcparent.addView(view, index, params)- Ưu tiên RecyclerView cho danh sách động