仿iOS Segmented Control样式"
同步发表于http://avenwu.net/2015/02/05/styled_radiogroup_segmented_control
Fork on github https://github.com/avenwu/support
iOS中有一个Segmented Control组件,android中的RadioGroup与之类似,但是RadioGroup的默认样式不是很美观,但是只需要稍微调一下就可以长得和Segmented Control控件一样简洁优雅。



实现
直接写style文件当然是最快的,只需设置每个RadioButton的对其为居中,修改默认的android:button资源,然后加上背景、文字的selector。
<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样式
<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等,所以可以做一些简单的封装,暴露一些必要的属性用于自定义,比如边框线的宽度,背景色等。
简单封装
自定义RadioGroup,将必要的初始化配置在内部完成。
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;
}
}
属性
定义需要暴露给外面的属性
<?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时只需要少量的的配置:
- app:tab_border_width="1dp" 边线宽度
- app:tab_border_color="@android:color/white" 边线颜色
- app:tab_items="@array/demo_array" tabs字符串数组
- app:tab_radius="5dp" 边框弧度
- app:tab_textSize="16sp" 文本字号
- app:tab_textColor="@color/radio_button_color_light_blue" 文本颜色selector
示例:
<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>
小结
完整代码可以再这里获取:
仿iOS Segmented Control样式"的更多相关文章
- CSS 仿 iOS 系统通知数字样式
/** 仿 iOS 系统通知数字样式 **/ .num_span{ background-color: #f00; background-image: -webkit-linear-gradient( ...
- iOS动画效果集合、 通过摄像头获取心率、仿淘宝滑动样式、瀑布流、分类切换布局等源码
iOS精选源码 动画知识运用及常见动画效果收集 较为美观的多级展开列表 MUImageCache -简单轻量的图片缓存方案 iOS 瀑布流之栅格布局 一用就上瘾的JXCategoryView iOS ...
- 从零开始学ios开发(六):IOS控件(3),Segmented Control、Switch
这次的学习还是基于上一个项目继续进行(你也可以新建一个项目)学习Segmented Control和Switch. Segmented Control Switch Segmented Control ...
- IOS学习之segmented control
转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/27086877 作者:小马 什么是segmented control? 先上几张图: ...
- WPF C#仿ios 安卓 红点消息提示
原文:WPF C#仿ios 安卓 红点消息提示 先把效果贴出来,大家看看. 代码下载地址: http://download.csdn.net/detail/candyvoice/9730751 点击+ ...
- WPF 仿IPhone滑块开关 样式 - CheckBox
原文:WPF 仿IPhone滑块开关 样式 - CheckBox <Style x:Key="CheckRadioFocusVisual"> <Setter Pr ...
- android 仿ios 对话框已封装成工具类
对话框 在android中是一种非经常见的交互提示用户的方式,可是非常多产品狗都叫我们这些做android的仿ios,搞的我们android程序猿非常苦逼,凭什么效果老是仿ios,有没有一点情怀,只是 ...
- react-native自定义Modal模态框|仿ios、微信弹窗RN版
前序 纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验.如:微信.支付宝.ios都有很成熟的一套弹窗UI展示场景. 最近一直沉迷在rea ...
- div css仿京东订单流程图样式代码
效果展示 http://hovertree.com/texiao/css/25/ 本效果适合PC,也适合移动端 手机扫描二维码查看效果: 效果图: 代码如下: <!DOCTYPE html> ...
随机推荐
- win7连接共享打印机 错误为
1. xp局域网共享打印机,本机运行 –> \\共享电脑ip –> 选择驱动目录 .INF 文件 –> 确认. 直接报错..... 2. 参考方法: 开始——设备和打印机——添 ...
- React Native填坑之旅--Button篇
从React过来,发现React Native(以下简称RN)居然没有Button.隔壁的iOS是有UIButton的,隔壁的隔壁的Android里也是有的.没有Button,就没有点击效果啊.这还真 ...
- [转]关闭ORACLE数据库
SQL> shutdown immediateORA-24324: 未初始化服务句柄ORA-24323: 不允许此值ORA-01090: 正在关闭 - 不允许连接 SQL> shutdow ...
- Model层数据验证
问题1:View层如何向Controller的Action传递Model数据?在View中,可以使用Form表单进行模型数据的提交,同样的,我们需要关联提交数据的类型,则需要在View中使用@mode ...
- Modifiers: virtual, override, new, abstract, sealed, internal
internal 声明类.类成员.接口或接口成员具有内部可见性. internal 修饰符使类.接口或成员仅在当前包中可见. 当前包之外的代码不能访问 internal 成员.只有在同一程序集的文件中 ...
- 女友要下岗?Windows 10的Cortana何方妖孽?
在Windows 10中,一大特色就是内置的Cortana小娜.她的出现为广大单身贵族带来了福音,就连天天秀恩爱的情侣也有了危机感. 小娜,你这样夺位这样真的好么? 还不帮我快快开始搜索 从Windo ...
- Orleans中的Timer和Reminder
Timers and Reminder 定时器和提醒器 Orleans runtime 允许开发人员通过一种叫做timer和另一种叫做reminder的机制为grain添加周期性行为.接下来我分别为大 ...
- IE11下Forms身份认证无法保存Cookie的问题
ASP.NET中使用Forms身份认证常见的做法如下: 1. 网站根目录下的Web.config添加authentication节点 <authentication mode="For ...
- macd综合版
参数设置 SHORE 12 LONG 26 MID 9 DIF:EMA(CLOSE,SHORT)-EMA(CLOSE,LONG); DEA:EMA(DIF,MID),COLOR88888 ...
- hibernate对象三种状态
在Hibernate中,对象有三种状态:临 时状态(Transient).持久状态(Persistent)和游离状态(Detached). 处于持久态的对象也称为 PO(PersistenceObje ...