仿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> ...
随机推荐
- 6.1-6.5关于html
网页一般是两种元素组合起来的,一种是内联元素, 也就是行内显示,加上width和height没效果.一种是区块元素,可以加上对应的width和height, 通常使用在网页的布局,最常用的就是< ...
- Titanium系列--安装Titanium Studio 中的Android SDK,JDK以及环境变量的配置(二)
Ubuntu安装配置JDK 1.先去 Oracle下载Linux下的JDK压缩包,我下载的是jdk-8u25-linux-x64.tar.gz文件,下好后直接解压 Step1:# 将解压好的jdk1. ...
- iOS 关于nil和Nil及null与<null>的区别
问题是这样的. NSDictionary *sample = [NSJSONSerialization JSONObjectWithData:received options:NSJSONReadin ...
- mysql 语句解释执行顺序
(7) SELECT (8) DISTINCT <select_list> (1) FROM <left_table> (3) <join_type> JOIN & ...
- Asp.Net Web API 2第十四课——Content Negotiation(内容协商)
前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...
- 用AutoHotKey彻底解决“Ctrl键+鼠标滚动”时的缩放问题
“Ctrl键+鼠标滚动”会造成代码编辑窗口的字体缩放,这是自Visual Studio 2010以来引入的一个新特性,也是一个恼人的问题,详见VS2010中尴尬的代码窗口缩放功能. 于是,每次安装Vi ...
- [游戏学习28] MFC 时钟
>_<:这是一个时钟小程序 >_<:通过调用获得系统时间然后经过计算得出当前时间,然后再以3个圆环表示时分秒. >_<:TAO_CLOCK.h class CMyA ...
- js获取url中的参数,url中传递中文的时候通过js解码的方式
如果传递的参数是: <a href="${pageContext.request.contextPath}/productdisplay/productDisplay_productD ...
- CentOS 7 service systemnctl
在之前的版本中关闭防火墙等服务的命令是 service iptables stop /etc/init.d/iptables stop 在RHEL7中,其实没有这个服务 [root@rhel7 ~]# ...
- sublime text 3 or sublime text 2 安装install package control
步骤 ctrl+` or View > Show Console sublime text 3 import urllib.request,os,hashlib; h = '7183a2d3e ...