仿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> ...
随机推荐
- HTTP学习笔记(2)HTTP报文
1,什么是http报文? 上一节我们了解到数据在浏览器和服务器之间进程传送,这些数据被称为报文流,报文流有流入流出之分,当然在也有上游和下游,这些都是来确定报文的流向. 报文的流向都是向下,而不会回流 ...
- SQL语句汇总(终篇)—— 表联接与联接查询
上一篇博文说到相关子查询效率低下,那我们怎么能将不同表的信息一起查询出来呢?这就需要用到表联接. 和之前的UNION组合查询不同,UNION是将不同的表组合起来,也就是纵向联接,说白了就是竖着拼起来. ...
- 个性二维码开源专题<液化/圆角/效果>
基础方法: ChangeFillShape //修改填充形状 ChangeFillShape(...) // 摘要: // 修改填充形状 // // 参数: // g: // 图形画板 // // F ...
- 无环的visitor模式
无环的访问者模式,是来改进原有访问者模式的不足之处的,是Robert C. Martin首次提出的.我们知道访问者模式的优点是为被访问继承体系动态添加行为,而无须改变继承体系.但是GOF访问者模式的缺 ...
- node-webkit教程(16)调试typescript
原文链接:node-webkit教程(16)调试typescript 本文所讲的内容同样适用于chrome浏览器. 在chrome的开发人员工具的配置项中,有一个sourcemap的选项,用来配置ja ...
- Oracle 创建主键自增表
200 ? "200px" : this.width)!important;} --> 介绍 本篇文章主要介绍在oracle中如果创建自增长表,这里要用到序列. create ...
- iOS系统app崩溃日志手动符号化
iOS系统app崩溃日志手动符号化步骤: 1.在桌面建立一个crash文件夹,将symbolicatecrash工具..crash文件..dSYM文件放到该文件夹中 a.如何查询symbolicate ...
- paip.网页右键复制菜单限制解除解决方案
paip.网页右键复制菜单限制解除解决方案 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net ...
- paip.最省内存的浏览器评测 cah
paip.最省内存的浏览器评测 cah 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/at ...
- Apache JMeter 测试Http请求
环境安装:JDK 下载:http://jmeter.apache.org/download_jmeter.cgi 启动: 简单HTTP请求测试