Giới thiệu
Bài viết hướng dẫn tùy chỉnh giao diện Switch (công tắc bật/tắt) trên Android bằng file XML drawable: thay đổi màu thumb, track, bo góc, gradient, viền cho 2 trạng thái ON/OFF.
Các bước thực hiện
Bước 1: Tạo dự án mới
Android Studio → File → New Project → Empty Activity.
Bước 2: Layout chính (res/layout/activity_main.xml)
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp"
tools:context=".MainActivity">
<Switch
android:id="@+id/switchBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textOn="BẬT"
android:textOff="TẮT"
android:thumb="@drawable/custom_switch_selector"
android:track="@drawable/custom_track" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/switchBtn"
android:layout_marginTop="20dp"
android:text="Vuốt Switch BẬT/TẮT"
android:textSize="24sp"
android:textAlignment="center"
android:textStyle="bold" />
</RelativeLayout>
Bước 3: Drawable Selector cho Thumb (res/drawable/custom_switch_selector.xml)
Định nghĩa hình ảnh thumb cho 2 trạng thái checked/unchecked.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="https://schemas.android.com/apk/res/android">
<!-- Trạng thái BẬT (checked) -->
<item android:state_checked="true">
<shape android:shape="rectangle"
android:dither="true"
android:useLevel="false"
android:visible="true">
<corners android:radius="15dp" />
<gradient
android:angle="270"
android:startColor="#66AAFF00"
android:endColor="#6600FF00" />
<size android:width="37dp" android:height="37dp" />
<stroke android:width="4dp" android:color="#0000FF" />
</shape>
</item>
<!-- Trạng thái TẮT (unchecked) -->
<item android:state_checked="false">
<shape android:shape="rectangle"
android:dither="true"
android:useLevel="false"
android:visible="true">
<corners android:radius="15dp" />
<gradient
android:angle="270"
android:startColor="#FF0000"
android:endColor="#FF0000" />
<size android:width="37dp" android:height="37dp" />
<stroke android:width="4dp" android:color="#0000FF" />
</shape>
</item>
</selector>
Bước 4: Drawable cho Track (res/drawable/custom_track.xml)
Track là thanh nền trượt của switch.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:visible="true"
android:dither="true"
android:useLevel="false">
<gradient
android:startColor="#27170432"
android:endColor="#27170432"
android:angle="270" />
<corners android:radius="15dp" />
<size android:width="80dp" android:height="40dp" />
</shape>
Bước 5: Logic (src/MainActivity.java)
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
Switch aSwitch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
aSwitch = findViewById(R.id.switchBtn);
aSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked) {
Toast.makeText(MainActivity.this, "Switch BẬT", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "Switch TẮT", Toast.LENGTH_SHORT).show();
}
});
}
}
Bước 6: Manifest
<?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. Vuốt switch → thumb chuyển động với gradient xanh (ON) / đỏ (OFF), track xám bo tròn.

Giải thích các thuộc tính Drawable
| Thuộc tính | Chức năng |
|---|---|
android:state_checked | Selector chọn item dựa trên trạng thái checked |
<shape> | Hình dạng: rectangle, oval, line, ring |
<corners android:radius> | Bo góc (dp) |
<gradient> | Độ dốc màu: startColor, endColor, angle, centerX/Y, type (linear/radial/sweep) |
<size> | Kích thước width/height (dp) |
<stroke> | Viền: width, color, dashWidth/dashGap |
android:dither | Dithering cho gradient mượt hơn |
Cách hiện đại: Material Components Switch
Từ Material Components 1.1.0+, dùng MaterialSwitch (tự động Material Design 3):
<com.google.android.material.switchmaterial.SwitchMaterial
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textOn="ON"
android:textOff="OFF"
app:trackColor="@color/switch_track_color_selector"
app:thumbColor="@color/switch_thumb_color_selector"
app:thumbIcon="@drawable/ic_check" />
Color Selector (res/color/switch_track_color_selector.xml)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="https://schemas.android.com/apk/res/android">
<item android:color="@color/colorPrimary" android:state_checked="true" />
<item android:alpha="0.38" android:color="@color/colorOnSurface" android:state_checked="false" />
<item android:color="@color/colorOnSurface" /> <!-- disabled -->
</selector>
So sánh
| Cách | Ưu điểm | Nhược điểm |
|---|---|---|
| Drawable XML (bài này) | Tùy chỉnh hoàn toàn hình dạng, gradient, viền | Phức tạp, nhiều file, khó maintain |
| MaterialSwitch + ColorSelector | Tuân thủ Material Design, ít code, hỗ trợ Motion, ripple | Ít tùy chỉnh hình dạng thumb (chỉ tròn/bo tròn) |
| Jetpack Compose Switch | Declarative, state-driven, preview realtime | Yêu cầu migrate sang Compose |