android仿ios实现分段选择控件UISegmentedControl

2 篇文章 0 订阅
1 篇文章 0 订阅

在ios7中有一种扁平风格的控件叫做分段选择控件UISegmentedControl,控件上横放或竖放着几个被简单线条隔开的按钮,每次点击能切换不同的按钮和按钮所对应的界面,比如qq客户端V6.5.3版本中消息页与电话页分离就是用的这种原理。但是很可惜的是Android系统并没有自带这种控件,不过我们也可以通过自定义RadioGroup实现该类效果,幸运的是Github上已有开源:https://github.com/Kaopiz/android-segmented-control

实现步骤如下:

第一步,在as中导入依赖:
dependencies {
compile ‘info.hoang8f:android-segmented:1.0.6’
}

第二步,在布局中引用控件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:segmentedgroup="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--自定义的RadioButton单选按钮组-->
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="@dimen/dimenActionBarHeight"
        android:background="@color/colorActionbar"
        android:gravity="center"
        android:minHeight="40dp">

        <info.hoang8f.android.segmented.SegmentedGroup
            android:id="@+id/mSegmentedGroup"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginRight="14dp"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            segmentedgroup:sc_border_width="1dp"
            segmentedgroup:sc_checked_text_color="@color/colorActionbar"
            segmentedgroup:sc_corner_radius="10dp"
            segmentedgroup:sc_tint_color="@color/colorWhite">

            <RadioButton
                android:id="@+id/radioButtonOne"
                style="@style/RadioButton"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="案例展示" />

            <RadioButton
                android:id="@+id/radioButtonTwo"
                style="@style/RadioButton"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="导师风采" />
        </info.hoang8f.android.segmented.SegmentedGroup>
    </RelativeLayout>

    <!--内容区-->
    <FrameLayout
        android:id="@+id/foundFrameLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

第三步,在代码中绑定碎片(Fragment):

public class FoundActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener{

    private SegmentedGroup mSegmentedGroup;
    private RadioButton radioButtonOne, radioButtonTwo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_found);

        initWidget();//初始化组件
        initData();//初始化数据
        initEvent();//初始化是事件

    }

    private void initEvent() {
        radioButtonOne.setChecked(true);//默认选择第一个(案例展示碎片)
    }

    private void initData() {
    }

    private void initWidget() {
        mSegmentedGroup = (SegmentedGroup) findViewById(R.id.mSegmentedGroup);//控件组
        radioButtonOne = (RadioButton) findViewById(R.id.radioButtonOne);//单选按钮一
        radioButtonTwo = (RadioButton) findViewById(R.id.radioButtonTwo);//单选按钮二

        mSegmentedGroup.setTintColor(Color.WHITE);//设置默认线条颜色及背景色
        mSegmentedGroup.setOnCheckedChangeListener(this);//绑定单选按钮选择监听

    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        switch (checkedId) {
            case R.id.radioButtonOne:
                FragmentManager fm = this.getSupportFragmentManager();//获得碎片管理器
                FragmentTransaction tr = fm.beginTransaction();//Transaction事物
                //将fragment碎片添加到对应的帧布局中
                tr.replace(R.id.foundFrameLayout, new CaseShowFragment());//案例展示碎片
                tr.commit();//提交
                break;
            case R.id.radioButtonTwo:
                FragmentManager fm2 = this.getSupportFragmentManager();
                FragmentTransaction tr2 = fm2.beginTransaction();
                tr2.replace(R.id.foundFrameLayout, new TutorStyleFragment());//导师咨询碎片
                tr2.commit();
                break;
        }
    }
}

好了,代码写到这里相信就已经达到了我们想要的效果,是不是很开ing呢?,哈哈,休息之余,不要忘记看看源码哦:

第四步,自定义RadioGroup源码分析:

public class SegmentedGroup extends RadioGroup {
    private int mMarginDp;
    private Resources resources = this.getResources();
    private int mTintColor;
    private int mCheckedTextColor = -1;
    private SegmentedGroup.LayoutSelector mLayoutSelector;
    private Float mCornerRadius;

    public SegmentedGroup(Context context) {
        super(context);
        this.mTintColor = this.resources.getColor(color.radio_button_selected_color);
        this.mMarginDp = (int)this.getResources().getDimension(dimen.radio_button_stroke_border);
        this.mCornerRadius = Float.valueOf(this.getResources().getDimension(dimen.radio_button_conner_radius));
        this.mLayoutSelector = new SegmentedGroup.LayoutSelector(this.mCornerRadius.floatValue());
    }

    private void initAttrs(AttributeSet attrs) {
        TypedArray typedArray = this.getContext().getTheme().obtainStyledAttributes(attrs, styleable.SegmentedGroup, 0, 0);

        try {
            this.mMarginDp = (int)typedArray.getDimension(styleable.SegmentedGroup_sc_border_width, this.getResources().getDimension(dimen.radio_button_stroke_border));
            this.mCornerRadius = Float.valueOf(typedArray.getDimension(styleable.SegmentedGroup_sc_corner_radius, this.getResources().getDimension(dimen.radio_button_conner_radius)));
            this.mTintColor = typedArray.getColor(styleable.SegmentedGroup_sc_tint_color, this.getResources().getColor(color.radio_button_selected_color));
            this.mCheckedTextColor = typedArray.getColor(styleable.SegmentedGroup_sc_checked_text_color, this.getResources().getColor(17170443));
        } finally {
            typedArray.recycle();
        }

    }

    public SegmentedGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mTintColor = this.resources.getColor(color.radio_button_selected_color);
        this.mMarginDp = (int)this.getResources().getDimension(dimen.radio_button_stroke_border);
        this.mCornerRadius = Float.valueOf(this.getResources().getDimension(dimen.radio_button_conner_radius));
        this.initAttrs(attrs);
        this.mLayoutSelector = new SegmentedGroup.LayoutSelector(this.mCornerRadius.floatValue());
    }

    protected void onFinishInflate() {
        super.onFinishInflate();
        this.updateBackground();
    }

    public void setTintColor(int tintColor) {
        this.mTintColor = tintColor;
        this.updateBackground();
    }

    public void setTintColor(int tintColor, int checkedTextColor) {
        this.mTintColor = tintColor;
        this.mCheckedTextColor = checkedTextColor;
        this.updateBackground();
    }

    public void updateBackground() {
        int count = super.getChildCount();

        for(int i = 0; i < count; ++i) {
            View child = this.getChildAt(i);
            this.updateBackground(child);
            if(i == count - 1) {
                break;
            }

            LayoutParams initParams = (LayoutParams)child.getLayoutParams();
            LayoutParams params = new LayoutParams(initParams.width, initParams.height, initParams.weight);
            if(this.getOrientation() == 0) {
                params.setMargins(0, 0, -this.mMarginDp, 0);
            } else {
                params.setMargins(0, 0, 0, -this.mMarginDp);
            }

            child.setLayoutParams(params);
        }

    }

    private void updateBackground(View view) {
        int checked = this.mLayoutSelector.getSelected();
        int unchecked = this.mLayoutSelector.getUnselected();
        ColorStateList colorStateList = new ColorStateList(new int[][]{{16842919}, {-16842919, -16842912}, {-16842919, 16842912}}, new int[]{-7829368, this.mTintColor, this.mCheckedTextColor});
        ((Button)view).setTextColor(colorStateList);
        Drawable checkedDrawable = this.resources.getDrawable(checked).mutate();
        Drawable uncheckedDrawable = this.resources.getDrawable(unchecked).mutate();
        ((GradientDrawable)checkedDrawable).setColor(this.mTintColor);
        ((GradientDrawable)checkedDrawable).setStroke(this.mMarginDp, this.mTintColor);
        ((GradientDrawable)uncheckedDrawable).setStroke(this.mMarginDp, this.mTintColor);
        ((GradientDrawable)checkedDrawable).setCornerRadii(this.mLayoutSelector.getChildRadii(view));
        ((GradientDrawable)uncheckedDrawable).setCornerRadii(this.mLayoutSelector.getChildRadii(view));
        StateListDrawable stateListDrawable = new StateListDrawable();
        stateListDrawable.addState(new int[]{-16842912}, uncheckedDrawable);
        stateListDrawable.addState(new int[]{16842912}, checkedDrawable);
        if(VERSION.SDK_INT >= 16) {
            view.setBackground(stateListDrawable);
        } else {
            view.setBackgroundDrawable(stateListDrawable);
        }

    }

    private class LayoutSelector {
        private int children;
        private int child;
        private final int SELECTED_LAYOUT;
        private final int UNSELECTED_LAYOUT;
        private float r;
        private final float r1;
        private final float[] rLeft;
        private final float[] rRight;
        private final float[] rMiddle;
        private final float[] rDefault;
        private final float[] rTop;
        private final float[] rBot;
        private float[] radii;

        public LayoutSelector(float cornerRadius) {
            this.SELECTED_LAYOUT = drawable.radio_checked;
            this.UNSELECTED_LAYOUT = drawable.radio_unchecked;
            this.r1 = TypedValue.applyDimension(1, 0.1F, SegmentedGroup.this.getResources().getDisplayMetrics());
            this.children = -1;
            this.child = -1;
            this.r = cornerRadius;
            this.rLeft = new float[]{this.r, this.r, this.r1, this.r1, this.r1, this.r1, this.r, this.r};
            this.rRight = new float[]{this.r1, this.r1, this.r, this.r, this.r, this.r, this.r1, this.r1};
            this.rMiddle = new float[]{this.r1, this.r1, this.r1, this.r1, this.r1, this.r1, this.r1, this.r1};
            this.rDefault = new float[]{this.r, this.r, this.r, this.r, this.r, this.r, this.r, this.r};
            this.rTop = new float[]{this.r, this.r, this.r, this.r, this.r1, this.r1, this.r1, this.r1};
            this.rBot = new float[]{this.r1, this.r1, this.r1, this.r1, this.r, this.r, this.r, this.r};
        }

        private int getChildren() {
            return SegmentedGroup.this.getChildCount();
        }

        private int getChildIndex(View view) {
            return SegmentedGroup.this.indexOfChild(view);
        }

        private void setChildRadii(int newChildren, int newChild) {
            if(this.children != newChildren || this.child != newChild) {
                this.children = newChildren;
                this.child = newChild;
                if(this.children == 1) {
                    this.radii = this.rDefault;
                } else if(this.child == 0) {
                    this.radii = SegmentedGroup.this.getOrientation() == 0?this.rLeft:this.rTop;
                } else if(this.child == this.children - 1) {
                    this.radii = SegmentedGroup.this.getOrientation() == 0?this.rRight:this.rBot;
                } else {
                    this.radii = this.rMiddle;
                }

            }
        }

        public int getSelected() {
            return this.SELECTED_LAYOUT;
        }

        public int getUnselected() {
            return this.UNSELECTED_LAYOUT;
        }

        public float[] getChildRadii(View view) {
            int newChildren = this.getChildren();
            int newChild = this.getChildIndex(view);
            this.setChildRadii(newChildren, newChild);
            return this.radii;
        }
    }
}

第五步,效果图:

这里写图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可自定义样式、功能全面的分段控件。项目地址:https://github.com/klongmitre/android-segmented-control-view效果图:如何使用xml中直接创建<org.mitre.ascv.AndroidSegmentedControlView         android:id="@ id/androidSegmentedControlView"         android:layout_width="match_parent"         android:layout_height="wrap_content"         ascv:ascv_defaultSelection="0"         ascv:ascv_unselectedTextColor="@color/test_attr_unselected_text_color"         ascv:ascv_selectedTextColor="@color/test_attr_selected_text_color"         ascv:ascv_selectedColor="@color/test_attr_selected_color"         ascv:ascv_unselectedColor="@color/test_attr_unselected_color"         ascv:ascv_items="@array/three_state_option"/>2. java中添加监听器,监听item的切换ascv = (AndroidSegmentedControlView)this.findViewById(R.id.androidSegmentedControlView); ascv.setIdentifier("ascv01"); //ascv.setItems(new String[]{"Test1aaaaa", "Test2", "Test3"}, new String[]{"1", "2", "3"}); ascv.setOnSelectionChangedListener(new OnSelectionChangedListener(){     @Override     public void newSelection(String identifier, String value) {//当item切换时触发  Toast.makeText(MainActivity.this, "identifier:" identifier "  value:" value, Toast.LENGTH_SHORT).show();     } });参数identifier是当有多个分段控件时,同时使用一个监听器时,用于区别是哪个触发了事件。属性说明属性名类型使用说明ascv_unselectedTextColorreference未选中的item的文字颜色ascv_unselectedColorreference未选中的item的背景颜色,不包括边框ascv_selectedColorreference选中的item背景的颜色以及边框的颜色ascv_selectedTextColorreference选中的item的文字颜色ascv_itemsreference控件item上显示的文字ascv_valuesreference控件item的值,会被传给监听器。未设置时,默认使用ascv_items。ascv_equalWidthboolean当item上的文字,即ascv_items设置的文字,长度不一致时,item的宽度是否还等长。ascv_stretchboolean是否被拉伸。即控件是否填充整个父容器。ascv_defaultSelectioninteger默认哪个item被选中,下标从0开始ascv_identifierstring控件的ID

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值