同步发表于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>

小结

完整代码可以再这里获取:

https://github.com/avenwu/support/blob/master/sample/src/main/java/com/avenwu/deepinandroid/StyledRadioButtonDemo.java

仿iOS Segmented Control样式"的更多相关文章

  1. CSS 仿 iOS 系统通知数字样式

    /** 仿 iOS 系统通知数字样式 **/ .num_span{ background-color: #f00; background-image: -webkit-linear-gradient( ...

  2. iOS动画效果集合、 通过摄像头获取心率、仿淘宝滑动样式、瀑布流、分类切换布局等源码

    iOS精选源码 动画知识运用及常见动画效果收集 较为美观的多级展开列表 MUImageCache -简单轻量的图片缓存方案 iOS 瀑布流之栅格布局 一用就上瘾的JXCategoryView iOS ...

  3. 从零开始学ios开发(六):IOS控件(3),Segmented Control、Switch

    这次的学习还是基于上一个项目继续进行(你也可以新建一个项目)学习Segmented Control和Switch. Segmented Control Switch Segmented Control ...

  4. IOS学习之segmented control

    转载请注明出处 http://blog.csdn.net/pony_maggie/article/details/27086877 作者:小马 什么是segmented control? 先上几张图: ...

  5. WPF C#仿ios 安卓 红点消息提示

    原文:WPF C#仿ios 安卓 红点消息提示 先把效果贴出来,大家看看. 代码下载地址: http://download.csdn.net/detail/candyvoice/9730751 点击+ ...

  6. WPF 仿IPhone滑块开关 样式 - CheckBox

    原文:WPF 仿IPhone滑块开关 样式 - CheckBox <Style x:Key="CheckRadioFocusVisual"> <Setter Pr ...

  7. android 仿ios 对话框已封装成工具类

    对话框 在android中是一种非经常见的交互提示用户的方式,可是非常多产品狗都叫我们这些做android的仿ios,搞的我们android程序猿非常苦逼,凭什么效果老是仿ios,有没有一点情怀,只是 ...

  8. react-native自定义Modal模态框|仿ios、微信弹窗RN版

    前序 纵观每个优质项目,无论web端还是native原生应用开发,弹窗都是不可忽视的一环,能很大程度上直接决定用户体验.如:微信.支付宝.ios都有很成熟的一套弹窗UI展示场景. 最近一直沉迷在rea ...

  9. div css仿京东订单流程图样式代码

    效果展示 http://hovertree.com/texiao/css/25/ 本效果适合PC,也适合移动端 手机扫描二维码查看效果: 效果图: 代码如下: <!DOCTYPE html> ...

随机推荐

  1. 6.1-6.5关于html

    网页一般是两种元素组合起来的,一种是内联元素, 也就是行内显示,加上width和height没效果.一种是区块元素,可以加上对应的width和height, 通常使用在网页的布局,最常用的就是< ...

  2. Titanium系列--安装Titanium Studio 中的Android SDK,JDK以及环境变量的配置(二)

    Ubuntu安装配置JDK 1.先去 Oracle下载Linux下的JDK压缩包,我下载的是jdk-8u25-linux-x64.tar.gz文件,下好后直接解压 Step1:# 将解压好的jdk1. ...

  3. iOS 关于nil和Nil及null与<null>的区别

    问题是这样的. NSDictionary *sample = [NSJSONSerialization JSONObjectWithData:received options:NSJSONReadin ...

  4. mysql 语句解释执行顺序

    (7) SELECT (8) DISTINCT <select_list> (1) FROM <left_table> (3) <join_type> JOIN & ...

  5. Asp.Net Web API 2第十四课——Content Negotiation(内容协商)

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET W ...

  6. 用AutoHotKey彻底解决“Ctrl键+鼠标滚动”时的缩放问题

    “Ctrl键+鼠标滚动”会造成代码编辑窗口的字体缩放,这是自Visual Studio 2010以来引入的一个新特性,也是一个恼人的问题,详见VS2010中尴尬的代码窗口缩放功能. 于是,每次安装Vi ...

  7. [游戏学习28] MFC 时钟

    >_<:这是一个时钟小程序 >_<:通过调用获得系统时间然后经过计算得出当前时间,然后再以3个圆环表示时分秒. >_<:TAO_CLOCK.h class CMyA ...

  8. js获取url中的参数,url中传递中文的时候通过js解码的方式

    如果传递的参数是: <a href="${pageContext.request.contextPath}/productdisplay/productDisplay_productD ...

  9. CentOS 7 service systemnctl

    在之前的版本中关闭防火墙等服务的命令是 service iptables stop /etc/init.d/iptables stop 在RHEL7中,其实没有这个服务 [root@rhel7 ~]# ...

  10. 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 ...