先来看一下效果图:
其实核心功能就两个:
1、选中后改变字体颜色及加上下标
2、事件回调
实现思路:
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">
<item
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;//单位为DP
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);
//重置当前RadioGroup的高度
setMeasuredDimension(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp2px(this.layoutHeight), 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());
//绑定Selector(核心!!!)
radioButton.setTextColor(getResources().getColorStateList(R.drawable.selector_text_color));
radioButton.setBackground(getResources().getDrawable(R.drawable.selector_indicator));
//设置RadioButton的大小
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) {//默认选中第一个Tab
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;//单位为DP
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>
最后
主要是依靠现有的View进行组合来实现的,还可以依据这个思路搞出一些其他的View出来。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。