1、通过向RadioGroup中添加RadioButton实现Tab的填充
2、通过设置设置特定属性去除选择按钮效果
3、通过使用Selector控制RadioButton的字体及下标
准备下标的drawable:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
android:height="3dp"
android:top="40dp">
<shape>
<solid android:color="@color/colorAccent"></solid>
</shape>
</item>
</layer-list>
复制代码
效果图:
准备字体颜色切换的Selector
主要用于字体黑灰之间的切换。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/black" android:state_checked="true"></item>
<item android:color="@android:color/darker_gray" android:state_checked="false"></item>
</selector>
复制代码
准备下标切换的Selector
选中则显示刚才使用layer-list定义的下标Drawable,否则什么都不设置,也就是不显示下标。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/shape_indicator" android:state_checked="true"></item>
</selector>
复制代码
重写RadioGroup
核心就在add 方法了,直接通过代码创建RadioButton并加入到当前布局中即可。
public class TabLayout extends RadioGroup {
private int layoutHeight = 50;
public TabLayout(Context context) {
super(context);
init();
public TabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
private void init() {
setOrientation(HORIZONTAL);
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.makeMeasureSpec(ViewHelper.dp2px(50), MeasureSpec.EXACTLY));
public void addTab(String title) {
add(new Tab(title));
public void addTab(String title, Object tag) {
add(new Tab(title, tag));
@SuppressLint({"NewApi", "ResourceType"})
private void add(Tab tab) {
RadioButton radioButton = new RadioButton(getContext());
radioButton.setText(tab.getTitle());
radioButton.setTextColor(getResources().getColorStateList(R.drawable.selector_text_color));
radioButton.setBackground(getResources().getDrawable(R.drawable.selector_indicator));
LayoutParams params = new LayoutParams(0, dp2px(50));
params.weight = 1;
radioButton.setLayoutParams(params);
radioButton.setGravity(Gravity.CENTER);
radioButton.setTag(tab);
radioButton.setButtonDrawable(null);
this.addView(radioButton);
if (getChildCount() == 1) {
radioButton.setChecked(true);
* 将特定的dp值转换为像素单位
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
public static class Tab {
private String title;
private Object tag;
public Tab(String title) {
this.title = title;
public Tab(String title, Object tag) {
this.title = title;
this.tag = tag;
public Object getTag() {
return tag;
public void setTag(Object tag) {
this.tag = tag;
public String getTitle() {
return title;
public void setTitle(String title) {
this.title = title;
复制代码
效果图:
增加事件回调
省略了部分无关代码。
public class TabLayout extends RadioGroup {
private int layoutHeight = 50;
private ItemClickListener itemClickListener;
public TabLayout(Context context) {
super(context);
init();
public TabLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
private void init() {
setOrientation(HORIZONTAL);
setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton radio = group.findViewById(checkedId);
if (!radio.isChecked()) return;
Tab tab = (Tab) radio.getTag();
if (itemClickListener != null) {
itemClickListener.onClick(tab, indexOfChild(radio));
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
public interface ItemClickListener {
void onClick(Tab tab, int position);
复制代码
具体使用
public class MainActivity extends AppCompatActivity {
private TabLayout tabLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.tabLayout = findViewById(R.id.tabLayout);
this.tabLayout.addTab("Type 1");
this.tabLayout.addTab("Type 2");
this.tabLayout.addTab("Type 3");
this.tabLayout.setItemClickListener(new TabLayout.ItemClickListener() {
@Override
public void onClick(TabLayout.Tab tab, int position) {
Toast.makeText(MainActivity.this, tab.getTitle(), Toast.LENGTH_SHORT).show();
复制代码
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.qylost.myapplication.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
复制代码
最后