IOSRadioGroup
来源:互联网 发布:拉货搬家软件 编辑:程序博客网 时间:2024/06/05 17:08
TextView Button RadioButton
public class Button extends TextView { public Button(Context context) { this(context, null); } public Button(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.buttonStyle); } public Button(Context context, AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0); } public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public CharSequence getAccessibilityClassName() { return Button.class.getName(); }}TextView 和 Button 区别,一个用了 textViewStyle,一个用了 buttonStyle。
CompoundButton 是 RadioButton 的父类 ,它和 Button 的区别:
View 的 onTouchEvent 会调用 performClick。
@Override public boolean performClick() { toggle(); // ... }
public void toggle() { setChecked(!mChecked); }
public void setChecked(boolean checked) { if (mChecked != checked) { mChecked = checked; refreshDrawableState(); notifyViewAccessibilityStateChangedIfNeeded( AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); // Avoid infinite recursions if setChecked() is called from a listener if (mBroadcasting) { return; } mBroadcasting = true; if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener.onCheckedChanged(this, mChecked); } if (mOnCheckedChangeWidgetListener != null) { mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); } mBroadcasting = false; } }RadioButton 重写了 toggle ,只允许选中:
@Override public void toggle() { // we override to prevent toggle when the radio is already // checked (as opposed to check boxes widgets) if (!isChecked()) { super.toggle(); } }为什么 RadioButton 是可选中的,Button 确不行:
@Override protected int[] onCreateDrawableState(int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) { mergeDrawableStates(drawableState, CHECKED_STATE_SET); } return drawableState; }
而 RadioGroup 就是可以监听选中并清除其他子 RadioButton 选中的 LinearLayout。
----------------------------------------------------------------------------------------- 进入正题
https://github.com/Kaopiz/android-segmented-control
很棒的库,虽说不要重复造轮子,但我认为摸索是必要的。
利用之前的知识,外加 RadioButton 隐藏 ButtonDrawable 后,很容易做到。
除了 setCornerRaduis ,还有更细致的 setCornRadii 可用,然后:
有点像样了,还有个问题,相邻的 stroke 应该只显示一条。
我是没想到怎么解决,看看作者的做法:
layoutParams.setMargins(-strokeWidth, 0, 0, 0);
真是太聪明了。
RadioGroup 在 onMeasure 和 onLayout 方面其实就是 LinearLayout。
LinearLayout 的 onMeasure ,依赖于 child view 的 onMeasure 结果。
缩小 child view 是无济于事的,drawable 重画时会随 View 扩展。
这里的做法,是把 “选项二” 和 “选项三” 向左平移了 strokeWidth。
onMeasure 时总长度,确实减少了 leftMargin。
mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child));
onLayout 时向确实向左偏了 leftMargin,但 child 大小是不变的。
childLeft += lp.leftMargin; setChildFrame(child, childLeft + getLocationOffset(child), childTop, childWidth, childHeight);
最终结果图:
开源库中还是使用了矢量字体,TransitionDrawable 渐变切换,还加了按下的 maskDrawable 的效果等等。
int maskColor = Color.argb(50, Color.red(mTintColor), Color.green(mTintColor), Color.blue(mTintColor)); maskDrawable.setColor(maskColor);
public class IOSRadioGroup extends RadioGroup { private int cornerRadius; private int mainColor; final int strokeWidth = 2; float[] leftCornerRadii; float[] middleCornerRadii; float[] rightCornerRadii; // public IOSRadioGroup(Context context) { super(context); } public IOSRadioGroup(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundCornerTextView); float dp = typedArray.getDimension(R.styleable.RoundCornerTextView_rc_corner_radius, 0.0f); cornerRadius = dp2px(context, dp); leftCornerRadii = new float[]{cornerRadius, cornerRadius, 0, 0, 0, 0, cornerRadius, cornerRadius}; middleCornerRadii = new float[]{0, 0, 0, 0, 0, 0, 0, 0}; rightCornerRadii = new float[]{0, 0, cornerRadius, cornerRadius, cornerRadius, cornerRadius, 0, 0}; mainColor = typedArray.getColor(R.styleable.RoundCornerTextView_rc_background_color, Color.TRANSPARENT); typedArray.recycle(); } // @Override protected void onFinishInflate() { super.onFinishInflate(); init(); } // @Override protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { View first = getChildAt(0); if (child != first) { LayoutParams layoutParams = (LayoutParams) child.getLayoutParams(); // Third Point // child 的大小没有变化,但位置会发生了变化,有了些许重叠。 layoutParams.setMargins(-strokeWidth, 0, 0, 0); } super.measureChildWithMargins(child, parentWidthMeasureSpec, widthUsed, parentHeightMeasureSpec, heightUsed); } // private void init() { for (int i = 0; i != getChildCount(); i++) { RadioButton child = (RadioButton) getChildAt(i); // Second Point // 不同 child 的 stroke 形状不同 float[] radii; if (i == 0) { radii = leftCornerRadii; } else if (i == getChildCount() - 1) { radii = rightCornerRadii; } else { radii = middleCornerRadii; } changeChildBackground(child, radii); } } // private void changeChildBackground(RadioButton radioButton, float[] cornerRadii) { GradientDrawable unchecked = new GradientDrawable(); unchecked.setCornerRadii(cornerRadii); unchecked.setColor(Color.WHITE); unchecked.setStroke(strokeWidth, mainColor); GradientDrawable checked = new GradientDrawable(); checked.setCornerRadii(cornerRadii); checked.setColor(mainColor); StateListDrawable background = new StateListDrawable(); background.addState(new int[]{-android.R.attr.state_checked}, unchecked); background.addState(new int[]{android.R.attr.state_checked}, checked); radioButton.setBackground(background); // First Point // 把默认的 style 中的 ButtonDrawable 去除。 radioButton.setButtonDrawable(null); ColorStateList colorStateList = new ColorStateList( new int[][]{{-android.R.attr.state_checked}, {android.R.attr.state_checked}}, new int[]{mainColor, Color.WHITE} ); radioButton.setTextColor(colorStateList); } // protected int dp2px(Context context, float dp) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); } }
- IOSRadioGroup
- 我的linux学习之路:Git常用命令
- 蓝桥杯单片机设计与开发笔记(四)
- Codeforces Round #346 (Div. 2) ABCDE
- POJ 2114 Boatherds 点分治
- Java集合---ConcurrentHashMap原理分析
- IOSRadioGroup
- 数据结构之“堆”
- Android Linux内核编译调试
- unity3D ~ 视频播放
- HDU4331 Image Recognition
- 环境配置中path和classpath的作用
- Java并发编程系列之十一:synchronized(2)
- 最成功的失败学——《创游记:游戏团队创业成长之路》
- Java设计模式之单例模式