同步发表于http://avenwu.net/2015/02/05/styled_radiogroup_segmented_controljava
Fork on github https://github.com/avenwu/supportandroid
iOS中有一个Segmented Control组件,android中的RadioGroup与之相似,可是RadioGroup的默认样式不是很美观,可是只须要稍微调一下就能够长得和Segmented Control控件同样简洁优雅。ios
直接写style文件固然是最快的,只需设置每一个RadioButton的对其为居中,修改默认的android:button资源,而后加上背景、文字的selector。git
<RadioGroup android:layout_width="match_parent" android:layout_height="48dp" android:orientation="horizontal" android:gravity="center_vertical"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A" android:id="@+id/radioButton" style="@style/FlatRadioButtonStyle" android:background="@drawable/flat_round_shape_left" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="B" android:id="@+id/radioButton2" android:checked="true" style="@style/FlatRadioButtonStyle" android:background="@drawable/flat_round_shape_middle" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="C" android:id="@+id/radioButton3" style="@style/FlatRadioButtonStyle" android:background="@drawable/flat_round_shape_right" /> </RadioGroup>
style样式github
<style name="FlatRadioButtonStyle"> <item name="android:layout_weight">1</item> <item name="android:button">@null</item> <item name="android:gravity">center</item> <item name="android:textAppearance">?android:textAppearanceMedium</item> <item name="android:textColor">@color/radio_button_color</item> <item name="android:padding">5dp</item> </style>
背景selector数组
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true"> <shape android:shape="rectangle"> <corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp" /> <solid android:color="@android:color/white" /> <stroke android:color="@android:color/white" android:width="1dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <corners android:topLeftRadius="5dp" android:bottomLeftRadius="5dp" /> <solid android:color="@android:color/transparent" /> <stroke android:color="@android:color/white" android:width="1dp" /> </shape> </item> </selector>
这些都没什么问题,可是比较零散,每次都须要写不少的xml及其样式,selector等,因此能够作一些简单的封装,暴露一些必要的属性用于自定义,好比边框线的宽度,背景色等。app
自定义RadioGroup,将必要的初始化配置在内部完成。ide
package net.avenwu.support.widget; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.StateListDrawable; import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.RadioButton; import android.widget.RadioGroup; import net.avenwu.support.R; /** * Created by chaobin on 2/4/15. */ public class FlatTabGroup extends RadioGroup { public FlatTabGroup(Context context) { this(context, null); } private int mRadius; private int mStroke; private int mHighlightColor; private String[] mItemString; private float mTextSize; private ColorStateList mTextColor; public FlatTabGroup(Context context, AttributeSet attrs) { super(context, attrs); setOrientation(HORIZONTAL); setGravity(Gravity.CENTER_VERTICAL); TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.FlatTabGroup); mHighlightColor = array.getColor(R.styleable.FlatTabGroup_tab_border_color, Color.WHITE); mStroke = array.getDimensionPixelSize(R.styleable.FlatTabGroup_tab_border_width, 2); mRadius = array.getDimensionPixelOffset(R.styleable.FlatTabGroup_tab_radius, 5); mTextColor = array.getColorStateList(R.styleable.FlatTabGroup_tab_textColor); mTextSize = array.getDimensionPixelSize(R.styleable.FlatTabGroup_tab_textSize, 14); array.recycle(); int id = array.getResourceId(R.styleable.FlatTabGroup_tab_items, 0); mItemString = isInEditMode() ? new String[]{"TAB A", "TAB B", "TAB C"} : context.getResources().getStringArray(id); generateTabView(context, attrs); updateChildBackground(); } private void generateTabView(Context context, AttributeSet attrs) { if (mItemString == null) { return; } for (String text : mItemString) { RadioButton button = new RadioButton(context, attrs); button.setGravity(Gravity.CENTER); button.setButtonDrawable(android.R.color.transparent); button.setText(text); button.setTextColor(mTextColor); button.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); addView(button, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1)); } } @Override protected void onFinishInflate() { super.onFinishInflate(); updateChildBackground(); } private void updateChildBackground() { for (int i = 0; i < getChildCount(); i++) { View child = getChildAt(i); if (child instanceof RadioButton) { child.setBackgroundDrawable(generateTabBackground(i, mHighlightColor)); } } } private Drawable generateTabBackground(int position, int color) { StateListDrawable stateListDrawable = new StateListDrawable(); stateListDrawable.addState(new int[]{android.R.attr.state_checked}, generateDrawable(position, color)); stateListDrawable.addState(new int[]{}, generateDrawable(position, Color.TRANSPARENT)); return stateListDrawable; } private Drawable generateDrawable(int position, int color) { float[] radius; if (position == 0) { radius = new float[]{ mRadius, mRadius, 0, 0, 0, 0, mRadius, mRadius }; } else if (position == getChildCount() - 1) { radius = new float[]{ 0, 0, mRadius, mRadius, mRadius, mRadius, 0, 0 }; } else { radius = new float[]{ 0, 0, 0, 0, 0, 0, 0, 0 }; } GradientDrawable shape = new GradientDrawable(); shape.setCornerRadii(radius); shape.setColor(color); shape.setStroke(mStroke, mHighlightColor); return shape; } }
属性this
定义须要暴露给外面的属性spa
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="FlatTabGroup"> <attr name="tab_items" format="reference" /> <attr name="tab_border_width" format="dimension|reference" /> <attr name="tab_border_color" format="color|reference" /> <attr name="tab_radius" format="dimension|reference" /> <attr name="tab_textColor" format="dimension|reference" /> <attr name="tab_textSize" format="dimension|reference" /> </declare-styleable> </resources>
如今须要写一个RadioGroup时只须要少许的的配置:
示例:
<net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color_light_blue" android:paddingTop="5dp" android:paddingBottom="5dp" />
因此如今写RadioGroup就很是方便,只须要根据需求配置相应属性便可。好比实现文章开头的效果,能够这样:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/ll_container"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:orientation="vertical" android:background="@android:color/holo_red_dark"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="RadioGroup with custom style" android:textColor="@android:color/white" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" /> <RadioGroup android:layout_width="match_parent" android:layout_height="48dp" android:orientation="horizontal" android:gravity="center_vertical"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="A" android:id="@+id/radioButton" style="@style/FlatRadioButtonStyle" android:background="@drawable/flat_round_shape_left" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="B" android:id="@+id/radioButton2" android:checked="true" style="@style/FlatRadioButtonStyle" android:background="@drawable/flat_round_shape_middle" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="C" android:id="@+id/radioButton3" style="@style/FlatRadioButtonStyle" android:background="@drawable/flat_round_shape_right" /> </RadioGroup> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Custom FlatTabGroup extend RadioGroup" android:textColor="@android:color/white" android:layout_marginTop="10dp" /> </LinearLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:background="@android:color/holo_red_dark"> <net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color" android:paddingTop="5dp" android:paddingBottom="5dp" /> </FrameLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:background="@color/tab_orange"> <net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color_orange" android:paddingTop="5dp" android:paddingBottom="5dp" /> </FrameLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:background="@color/tab_purple"> <net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color_purple" android:paddingTop="5dp" android:paddingBottom="5dp" /> </FrameLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:background="@color/tab_blue"> <net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color_blue" android:paddingTop="5dp" android:paddingBottom="5dp" /> </FrameLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:background="@color/tab_light_blue"> <net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color_light_blue" android:paddingTop="5dp" android:paddingBottom="5dp" /> </FrameLayout> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="20dp" android:background="@color/tab_green"> <net.avenwu.support.widget.FlatTabGroup android:layout_width="match_parent" android:layout_height="40dp" app:tab_border_width="1dp" app:tab_border_color="@android:color/white" app:tab_items="@array/demo_array" app:tab_radius="5dp" app:tab_textSize="16sp" app:tab_textColor="@color/radio_button_color_green" android:paddingTop="5dp" android:paddingBottom="5dp" /> </FrameLayout> </LinearLayout> </ScrollView>
颜色selector
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/tab_light_blue" android:state_checked="true" /> <item android:color="@android:color/white" /> </selector>
tab数组
<string-array name="demo_array"> <item>A</item> <item>B</item> <item>C</item> </string-array>
完整代码能够再这里获取: