先來看一下效果圖:java
其實核心功能就兩個:android
一、選中後改變字體顏色及加上下標app
二、事件回調ide
實現思路:佈局
一、經過向RadioGroup中添加RadioButton實現Tab的填充字體
二、經過設置設置特定屬性去除選擇按鈕效果this
三、經過使用Selector控制RadioButton的字體及下標spa
準備下標的drawable:3d
<?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>
效果圖:code
準備字體顏色切換的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出來。