Giới thiệu về Ripple Animation
Hiệu ứng Ripple (gợn sóng) là hiệu ứng visual feedback khi người dùng chạm vào view (Button, TextView, CardView...). Hiệu ứng lan tỏa từ điểm chạm tạo cảm giác phản hồi tự nhiên. Kể từ Android 5.0 (API 21, Lollipop), Ripple là hiệu ứng mặc định cho các widget Material Design.
Bước 1: Tạo dự án mới
Mở Android Studio, chọn File → New Project, điền thông tin cần thiết.
Bước 2: Tạo drawable ripple (res/drawable/ripple.xml)
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:color="#80FF5722" <!-- Màu ripple (có alpha) -->
tools:targetApi="lollipop">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#FF5722" /> <!-- Màu nền view -->
<corners android:radius="4dp" /> <!-- Bo góc tùy chọn -->
</shape>
</item>
</ripple>
Giải thích:
android:color: Màu của hiệu ứng gợn sóng (nên có độ trong suốt, ví dụ#80FF5722)android:id="@android:id/mask": Định nghĩa hình dạng khu vực ripple (bắt buộc)tools:targetApi="lollipop": Chỉ áp dụng từ API 21+
Bước 3: Áp dụng vào View (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btnRipple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nhấn vào đây"
android:textSize="20sp"
android:background="@drawable/ripple"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Gán android:background="@drawable/ripple" cho bất kỳ View nào (Button, TextView, LinearLayout, CardView...).
Bước 4: Code Java (src/MainActivity.java) - Tùy chọn
package com.example.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnRipple = findViewById(R.id.btnRipple);
btnRipple.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Ripple hoạt động!", Toast.LENGTH_SHORT).show();
}
});
}
}
Chạy ứng dụng
Kết nối thiết bị (API 21+) và chạy ứng dụng.

Nhấn và giữ vào button để thấy hiệu ứng ripple:

Mẹo nâng cao:
- Ripple không giới hạn (unbounded): Bỏ
maskitem → ripple lan tỏa ra ngoài view- Ripple giới hạn (bounded): Có
mask→ ripple giới hạn trong hình dạng view (mặc định)- Tương thích ngược (pre-Lollipop): Dùng
?android:attr/selectableItemBackgroundhoặc?attr/selectableItemBackgroundBorderlesslàm background- Tùy chỉnh màu theo theme:
android:color="?attr/colorControlHighlight"- Cho ImageView/ImageButton: Cần
android:foreground="@drawable/ripple"thay vì background