可自动换行的RadioGroup
来源:互联网 发布:网易养猪场知乎 编辑:程序博客网 时间:2024/06/08 00:40
主要重写了onMeasure和onLayout
import android.content.Contextimport android.content.res.TypedArrayimport android.support.annotation.IdResimport android.util.AttributeSetimport android.view.Viewimport android.view.ViewGroupimport android.widget.CompoundButtonimport android.widget.LinearLayoutimport android.widget.RadioButtonimport java.util.concurrent.atomic.AtomicIntegeropen class MultiRadioGroup : LinearLayout { var columnCount = 3//写到属性中 var checkedRadioButtonId = -1 @get:IdRes private var mChildOnCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null private var mProtectFromCheckedChange = false private var mOnCheckedChangeListener: OnCheckedChangeListener? = null private var mPassThroughListener: PassThroughHierarchyChangeListener? = null constructor(context: Context) : super(context) { orientation = LinearLayout.VERTICAL init() } constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { init() } private fun init() { mChildOnCheckedChangeListener = CheckedStateTracker() mPassThroughListener = PassThroughHierarchyChangeListener() super.setOnHierarchyChangeListener(mPassThroughListener) } override fun setOnHierarchyChangeListener(listener: ViewGroup.OnHierarchyChangeListener) { // the user listener is delegated to our pass-through listener mPassThroughListener!!.mOnHierarchyChangeListener = listener } override fun onFinishInflate() { super.onFinishInflate() // checks the appropriate radio button as requested in the XML file if (checkedRadioButtonId != -1) { mProtectFromCheckedChange = true setCheckedStateForView(checkedRadioButtonId, true) mProtectFromCheckedChange = false setCheckedId(checkedRadioButtonId) } } override fun addView(child: View, index: Int, params: ViewGroup.LayoutParams) { if (child is RadioButton) { val button = child if (button.isChecked) { mProtectFromCheckedChange = true if (checkedRadioButtonId != -1) { setCheckedStateForView(checkedRadioButtonId, false) } mProtectFromCheckedChange = false setCheckedId(button.id) } } super.addView(child, index, params) } fun check(@IdRes id: Int) { // don't even bother if (id != -1 && id == checkedRadioButtonId) { return } if (checkedRadioButtonId != -1) { setCheckedStateForView(checkedRadioButtonId, false) } if (id != -1) { setCheckedStateForView(id, true) } setCheckedId(id) } private fun setCheckedId(@IdRes id: Int) { checkedRadioButtonId = id if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener!!.onCheckedChanged(this, checkedRadioButtonId) } } private fun setCheckedStateForView(viewId: Int, checked: Boolean) { val checkedView = findViewById(viewId) if (checkedView != null && checkedView is RadioButton) { checkedView.isChecked = checked } } fun clearCheck() { check(-1) } fun setOnCheckedChangeListener(listener: OnCheckedChangeListener) { mOnCheckedChangeListener = listener } override fun generateLayoutParams(attrs: AttributeSet): LayoutParams { return MultiRadioGroup.LayoutParams(context, attrs) } override fun checkLayoutParams(p: ViewGroup.LayoutParams): Boolean { return p is MultiRadioGroup.LayoutParams } override fun generateDefaultLayoutParams(): LinearLayout.LayoutParams { return LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT) } override fun getAccessibilityClassName(): CharSequence { return MultiRadioGroup::class.java.name } class LayoutParams : LinearLayout.LayoutParams { constructor(c: Context, attrs: AttributeSet) : super(c, attrs) {} constructor(w: Int, h: Int) : super(w, h) {} constructor(w: Int, h: Int, initWeight: Float) : super(w, h, initWeight) {} constructor(p: ViewGroup.LayoutParams) : super(p) {} constructor(source: ViewGroup.MarginLayoutParams) : super(source) {} override fun setBaseAttributes(a: TypedArray, widthAttr: Int, heightAttr: Int) { if (a.hasValue(widthAttr)) { width = a.getLayoutDimension(widthAttr, "layout_width") } else { width = ViewGroup.LayoutParams.WRAP_CONTENT } if (a.hasValue(heightAttr)) { height = a.getLayoutDimension(heightAttr, "layout_height") } else { height = ViewGroup.LayoutParams.WRAP_CONTENT } } } interface OnCheckedChangeListener { fun onCheckedChanged(group: MultiRadioGroup, @IdRes checkedId: Int) } private inner class CheckedStateTracker : CompoundButton.OnCheckedChangeListener { override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) { // prevents from infinite recursion if (mProtectFromCheckedChange) { return } mProtectFromCheckedChange = true if (checkedRadioButtonId != -1) { setCheckedStateForView(checkedRadioButtonId, false) } mProtectFromCheckedChange = false val id = buttonView.id setCheckedId(id) } } private inner class PassThroughHierarchyChangeListener : ViewGroup.OnHierarchyChangeListener { var mOnHierarchyChangeListener: ViewGroup.OnHierarchyChangeListener? = null override fun onChildViewAdded(parent: View, child: View) { if (parent === this@MultiRadioGroup && child is RadioButton) { var id = child.getId() // generates an id if it's missing if (id == View.NO_ID) { id = generateId() child.setId(id) } var clazz = CompoundButton::class.java var method = clazz.getDeclaredMethod("setOnCheckedChangeWidgetListener", CompoundButton.OnCheckedChangeListener::class.java) method.isAccessible = true method.invoke(child, mChildOnCheckedChangeListener) } mOnHierarchyChangeListener?.onChildViewAdded(parent, child) } override fun onChildViewRemoved(parent: View, child: View) { if (parent === this@MultiRadioGroup && child is RadioButton) { var clazz = CompoundButton::class.java var method = clazz.getDeclaredMethod("setOnCheckedChangeWidgetListener", CompoundButton.OnCheckedChangeListener::class.java) method.isAccessible = true method.invoke(child, null) } mOnHierarchyChangeListener?.onChildViewRemoved(parent, child) } } private val nextGeneratedId = AtomicInteger(1) fun generateId(): Int { while (true) { val result = nextGeneratedId.get() var newValue = result + 1 if (newValue > 0x00FFFFFF) newValue = 1 // Roll over to 1, not 0. if (nextGeneratedId.compareAndSet(result, newValue)) { return result } } } override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { layoutHorizontal(l, t, r, b) } private fun setChildFrame(child: View, left: Int, top: Int, width: Int, height: Int) { child.layout(left, top, left + width, top + height) } internal fun layoutHorizontal(left: Int, top: Int, right: Int, bottom: Int) { val paddingTop = paddingTop var childTop: Int var childLeft: Int val count = childCount childLeft = paddingLeft childTop = paddingTop var start = 0 var dir = 1 var i = 0 while (i < count) { val childIndex = start + dir * i val child = getChildAt(childIndex) if (child == null) { childLeft += 0 } else if (child!!.visibility != View.GONE) { val childHeight = child!!.measuredHeight val lp = child!!.layoutParams as MultiRadioGroup.LayoutParams val childWidth = (measuredWidth - columnCount * (lp.leftMargin + lp.rightMargin)) / columnCount child.measure(childWidth, childHeight) if (i > 0 && i % columnCount == 0) { childLeft = paddingLeft childTop += lp.topMargin childTop += childHeight + lp.bottomMargin } childLeft += lp.leftMargin setChildFrame(child, childLeft, childTop, childWidth, childHeight) childLeft += childWidth + lp.rightMargin i += 0 } i++ } } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) var i = 0 var height = paddingTop while (i < childCount) { if (i % columnCount == 0) { val childIndex = i val child = getChildAt(childIndex) val childHeight = child!!.measuredHeight val lp = child!!.layoutParams as MultiRadioGroup.LayoutParams height += lp.topMargin height += childHeight + lp.bottomMargin } i++ } setMeasuredDimension(measuredWidth, height) }}
阅读全文
0 0
- 可自动换行的RadioGroup
- 可自动换行的RadioGroup
- 自动换行的RadioGroup
- 可以自动换行的radioGroup
- 筛选菜单--弹性式RadioGroup(可自动换行)
- 可自动换行的radiobutton
- 可以自动换行的RadioGroup (默认水平布局)
- RadioGroup 的分列换行
- 可以换行的RadioGroup
- 可自动换行的单选 RadioGroupEx
- Android开发之自动换行RadioGroup
- RadioGroup 自动换行且保留点击事件
- android 之RadioGroup 的换行
- 可滑动的自动换行的ViewGroup-ScrollableFlowLayout
- Flex中button可自动换行的label
- Android 可自动换行的单选 RadioGroupEx
- 可自动换行的RadioGroupEx,支持RadioButton设置margin
- RadioGroup的换行、换行后的均分实现
- QSS使用规则
- SpringBoot init
- IOS响应式编程框架ReactiveCocoa(RAC)使用示例
- 数据挖掘系列(2)--关联规则FpGrowth算法
- U盘exe病毒还原文件以及永久防毒
- 可自动换行的RadioGroup
- 模拟试——match
- JS移动某些元素到指定位置
- Kotlin Coroutine 协程Gradle配置
- MAC下GDB出现问题-Unable to find Mach task port for process-id 1262: (os/kern) failure (0x5).
- Android常用组件-editview
- JAVA---TTML
- docker搭建registry(对于认证的个人用户)
- Kendo Grid 指定位置增加记录