参考Android仿IOS的Segmented Control 选项卡。
自定义View。
public class SwitchButton extends RadioGroup implements OnCheckedChangeListener {
private final int[] CHECKED_STATE = { android.R.attr.state_checked }, UNCHECKED_STATE = { -android.R.attr.state_checked };
/** 默认选项卡数量 */
private final static int DEFAULT_SWITCH_COUNT = 2;
private final static int EX = 5;// 余量
private ColorStateList mTextColor;
private int mParentWidth, mParentHeight;
private int mRadioStyle;
private float cornerRadius, textSize;
private int checkedColor, unCheckedColor, strokeColor, strokeWidth;
private CharSequence[] mTexts;
private int switchCount;
// 是否测量完毕
private boolean isMeasure;
private SparseArray<RadioButton> mRadioArrays;
private SparseArray<Drawable> mButtonDrawables;
private SparseArray<StateListDrawable> mStateDrawables;
private SparseIntArray mSparseIds;
private int mCurrentPosition;
private OnChangeListener changeListener;
/** * @param context */
public SwitchButton(Context context) {
super(context, null);
}
public SwitchButton(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.orientation, android.R.attr.layout_height });
setOrientation(a.getInt(0, LinearLayout.HORIZONTAL));
mParentHeight = a.getDimensionPixelSize(1, 0);
a.recycle();
a = context.obtainStyledAttributes(attrs, R.styleable.switchButton);
setTextColor(a.getColorStateList(R.styleable.switchButton_android_textColor));
setTextArray(a.getTextArray(R.styleable.switchButton_sw_textArray));
setSwitchCount(a.getInteger(R.styleable.switchButton_sw_switchCount, DEFAULT_SWITCH_COUNT));
setSwitchStyle(a.getResourceId(R.styleable.switchButton_sw_ThemeStyle, 0));
setCornerRadius(a.getDimension(R.styleable.switchButton_sw_CornerRadius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, getResources().getDisplayMetrics())));
setCheckedColor(a.getColor(R.styleable.switchButton_sw_checkedColor, Color.GREEN));
setUnCheckedColor(a.getColor(R.styleable.switchButton_sw_unCheckedColor, Color.WHITE));
setStrokeColor(a.getColor(R.styleable.switchButton_sw_strokeColor, Color.GREEN));
setStrokeWidth((int) a.getDimension(R.styleable.switchButton_sw_strokeWidth, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, getResources().getDisplayMetrics())));
setTextSize(a.getDimension(R.styleable.switchButton_android_textSize, 0f));
a.recycle();
setOnCheckedChangeListener(this);
}
/** * 初始化UI * * @param context */
@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void initUI(Context context) {
if (mTexts != null && mTexts.length != switchCount) {
throw new IllegalArgumentException("The textArray's length must equal to the switchCount");
}
if (mParentWidth == 0)
return;
ColorDrawable colorDrawable = new ColorDrawable();
LayoutParams mParams = new LayoutParams(mParentWidth / (switchCount > 2 ? switchCount : (switchCount + 1)), mParentHeight, 1);
for (int i = 0; i < switchCount; i++) {
if (mRadioArrays == null)
mRadioArrays = new SparseArray<RadioButton>();
RadioButton mRadioButton = mRadioArrays.get(i, createRadioView());
mRadioButton.setLayoutParams(mParams);
mRadioButton.setButtonDrawable(mButtonDrawables != null ? mButtonDrawables.get(i, colorDrawable) : colorDrawable);
if (Build.VERSION.SDK_INT >= 16) {
mRadioButton.setBackground(getStateDrawable(i));
} else {
mRadioButton.setBackgroundDrawable(getStateDrawable(i));
}
mRadioButton.setText(mTexts[i]);
if (mRadioButton.getId() < 0) {
int id = getViewId();
if (mSparseIds == null)
mSparseIds = new SparseIntArray();
mSparseIds.put(i, id);
mRadioButton.setId(id);
} else {
removeView(mRadioButton);
}
mRadioButton.setChecked(mCurrentPosition == i);
addView(mRadioButton, i);
mRadioArrays.put(i, mRadioButton);
}
}
private Drawable getStateDrawable(int i) {
if (mStateDrawables == null)
mStateDrawables = new SparseArray<StateListDrawable>();
StateListDrawable mStateListDrawable = mStateDrawables.size() >= i + 1 && (i != switchCount - 1 || i == switchCount - 1) ? null : mStateDrawables.get(i);
if (mStateListDrawable == null) {
float leftRadius = i == 0 ? cornerRadius : 0;
float rightRadius = i == 0 ? 0 : i == switchCount - 1 ? cornerRadius : 0;
float[] cRadius = { leftRadius, leftRadius, rightRadius, rightRadius, rightRadius, rightRadius, leftRadius, leftRadius };
mStateListDrawable = new StateListDrawable();
GradientDrawable cornerDrawable = new GradientDrawable();
cornerDrawable.setColor(checkedColor);
cornerDrawable.setCornerRadii(cRadius);
mStateListDrawable.addState(CHECKED_STATE, cornerDrawable);
cornerDrawable = new GradientDrawable();
cornerDrawable.setColor(unCheckedColor);
cornerDrawable.setStroke(strokeWidth, strokeColor);
cornerDrawable.setCornerRadii(cRadius);
mStateListDrawable.addState(UNCHECKED_STATE, cornerDrawable);
mStateDrawables.put(i, mStateListDrawable);
}
return mStateListDrawable;
}
private RadioButton createRadioView() {
RadioButton mRadioButton = new RadioButton(getContext(), null, mRadioStyle > 0 ? mRadioStyle : android.R.attr.radioButtonStyle);
if (mRadioStyle == 0) {
mRadioButton.setGravity(Gravity.CENTER);
mRadioButton.setEllipsize(TruncateAt.END);
}
if (mTextColor != null)
mRadioButton.setTextColor(mTextColor);
if (textSize > 0)
mRadioButton.setTextSize(textSize);
return mRadioButton;
}
@Deprecated
public void initialize() {
notifyDataSetChange();
}
/** * 刷新数据(Button数量跟随刷新的文本数据变化) */
public void notifyDataSetChange() {
removeAllViews();
switchCount = mTexts != null ? mTexts.length : switchCount;
initUI(getContext());
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!isMeasure) {
initUI(getContext());
isMeasure = !isMeasure;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mParentWidth = widthMeasureSpec - EX;
mParentHeight = mParentHeight == 0 ? heightMeasureSpec : mParentHeight;
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (changeListener != null)
changeListener.onChange(mSparseIds.indexOfValue(checkedId));
}
/** * 设置当前选中项 * * @param selectedPosition */
public void setCurrentPosition(int selectedPosition) {
if (selectedPosition >= 0 && selectedPosition <= switchCount) {
mCurrentPosition = selectedPosition;
}
}
/** * 设置选中项 * * @param selectedPosition */
public void setCheckedPosition(int selectedPosition) {
if (selectedPosition >= 0 && selectedPosition <= switchCount) {
mCurrentPosition = selectedPosition;
if (mSparseIds != null)
check(mSparseIds.get(mSparseIds.keyAt(selectedPosition)));
}
}
public void setTextColor(ColorStateList mTextColor) {
this.mTextColor = mTextColor;
}
public void setSwitchStyle(int mSwitchStyle) {
this.mRadioStyle = mSwitchStyle;
}
public void setTextArray(CharSequence[] mTexts) {
this.mTexts = mTexts;
}
public int getSwitchCount() {
return switchCount;
}
public void setParentWidth(int mParentWidth) {
this.mParentWidth = mParentWidth;
}
public void setParentHeight(int mParentHeight) {
this.mParentHeight = mParentHeight;
}
public void setSwitchCount(int switchCount) {
this.switchCount = switchCount < 2 ? DEFAULT_SWITCH_COUNT : switchCount;
if (mButtonDrawables == null)
mButtonDrawables = new SparseArray<Drawable>();
}
public void setCornerRadius(float cornerRadius) {
this.cornerRadius = cornerRadius;
}
public void setCheckedColor(int checkedColor) {
this.checkedColor = checkedColor;
}
public void setUnCheckedColor(int unCheckedColor) {
this.unCheckedColor = unCheckedColor;
}
public void setStrokeColor(int strokeColor) {
this.strokeColor = strokeColor;
}
public void setStrokeWidth(int strokeWidth) {
this.strokeWidth = strokeWidth;
}
public void setTextSize(float textSize) {
this.textSize = textSize;
}
public void setSwitchButton(int position, int mDrawableResId) {
mButtonDrawables.put(position, getResources().getDrawable(mDrawableResId));
}
public void setOnChangeListener(OnChangeListener eventListener) {
this.changeListener = eventListener;
}
public interface OnChangeListener {
public void onChange(int position);
}
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
public int getViewId() {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range
// under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF)
newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
}
values下创建array.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="test">
<item>一</item>
<item>二</item>
</string-array>
</resources>
arrts.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="switchButton">
<attr name="android:textColor" />
<attr name="android:textSize" />
<attr name="sw_textArray" format="string" />
<attr name="sw_switchCount" format="integer" />
<attr name="sw_ThemeStyle" format="reference" />
<attr name="sw_CornerRadius" format="dimension" />
<attr name="sw_checkedColor" format="color|reference" />
<attr name="sw_unCheckedColor" format="color|reference" />
<attr name="sw_strokeColor" format="color|reference" />
<attr name="sw_strokeWidth" format="dimension" />
</declare-styleable>
</resources>
dimens.xml
<resources>
<dimen name="icon_arrow_width">16dp</dimen>
<dimen name="body_margin">10dp</dimen>
<dimen name="twenty">20dp</dimen>
</resources>
drawable.xml 的 switch_textcolor_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- title sitch -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:color="@color/colorPrimary"/>
<item android:state_checked="true" android:color="@color/white"/>
</selector>
mSwitchButton = (SwitchButton) findViewById(R.id.switchButton);
mSwitchButton.setOnChangeListener(new SwitchButton.OnChangeListener() {
@Override
public void onChange(int position) {
if (position==0){
FragmentManager fm = getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
fragment1 = new Fragment1();
ft.replace(android.R.id.content, fragment1);
ft.commit();
}
else {
FragmentManager fm = getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
fragment2 = new Fragment2();
ft.replace(android.R.id.content, fragment2);
ft.commit();
}
}
});
效果