Kotlin实现RadioFlexboxGroup组件
来源:互联网 发布:软件著作权加急官费 编辑:程序博客网 时间:2024/06/15 12:56
如果使用过RadioGroup组件都是在,这个有很大的局限性,基本上设计师稿子一出来你就知道要自定义才可以实现的这些效果。
如果使用FlexBoxLayout就知道,这个东西还是挺好用了,如果还没使用过,不妨参考http://www.oschina.net/news/73442/google-flexbox-layout
这里我结合RadioGroup实现的单选效果加上FlexBoxLayout,简直太好用了,而且不需要写任何多余的代码,方便又好用,好了,废话不多说,先上效果图
当然我这里只列了基本效果,当然如果想要其他效果,可以充分发挥FlexBoxLayout布局优势
下边是布局文件xml:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout 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"> <com.example.myproject.component.RadioFlexboxGroup android:id="@+id/rg_1" android:layout_width="match_parent" android:layout_height="wrap_content" app:justifyContent="space_around" app:flexWrap="wrap"> <RadioButton android:id="@+id/radio_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:checked="true" android:text="不限" /> <RadioButton android:id="@+id/radio_2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="精选项目" /> <RadioButton android:id="@+id/radio_3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="转让项目" /> </com.example.myproject.component.RadioFlexboxGroup> <com.example.myproject.component.RadioFlexboxGroup android:id="@+id/rg_2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_marginTop="16dp" app:flexDirection="column" app:justifyContent="space_around" app:layout_constraintLeft_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/rg_1"> <RadioButton android:id="@+id/radio_11" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/radio_text_coloraccent_select" android:text="不限" /> <RadioButton android:id="@+id/radio_12" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/radio_text_coloraccent_select" android:text="精选项目" /> <RadioButton android:id="@+id/radio_13" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@color/radio_text_coloraccent_select" android:checked="true" android:text="转让项目" /> </com.example.myproject.component.RadioFlexboxGroup> <com.example.myproject.component.RadioFlexboxGroup android:id="@+id/rg_3" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="32dp" android:layout_marginRight="32dp" android:layout_marginTop="16dp" app:flexDirection="row_reverse" app:justifyContent="space_between" app:layout_constraintLeft_toRightOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@+id/rg_2"> <RadioButton android:id="@+id/radio_22" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/radio_select" android:button="@null" android:paddingBottom="4dp" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="4dp" android:textColor="@color/radio_text_select" android:text="\t\t不限\t\t" /> <RadioButton android:id="@+id/radio_23" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/radio_select" android:button="@null" android:checked="true" android:paddingBottom="4dp" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="4dp" android:textColor="@color/radio_text_select" android:text="精选项目" /> <RadioButton android:id="@+id/radio_24" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/radio_select" android:button="@null" android:paddingBottom="4dp" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="4dp" android:textColor="@color/radio_text_select" android:text="转让项目" /> </com.example.myproject.component.RadioFlexboxGroup></android.support.constraint.ConstraintLayout>
Activity界面其实啥都没有:
class RadioFlexBoxGroupActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_radio_group) }}
最后就是组件的代码:
class RadioFlexboxGroup : FlexboxLayout { /** * * Returns the identifier of the selected radio button in this group. * Upon empty selection, the returned value is -1. * @return the unique id of the selected radio button in this group * * * @attr ref android.R.styleable#RadioGroup_checkedButton * * * @see .check * @see .clearCheck */ var mCheckedId = -1 var checkedRadioButtonId = -1 @IdRes get() = mCheckedId private set // tracks children radio buttons checked state private var mChildOnCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null // when true, mOnCheckedChangeListener discards events private var mProtectFromCheckedChange = false private var mOnCheckedChangeListener: OnCheckedChangeListener? = null private var mPassThroughListener: PassThroughHierarchyChangeListener? = null constructor(context: Context?) : super(context) constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) init { init() } private fun init() { mChildOnCheckedChangeListener = CheckedStateTracker() mPassThroughListener = PassThroughHierarchyChangeListener() super.setOnHierarchyChangeListener(mPassThroughListener) } /** * {@inheritDoc} */ override fun setOnHierarchyChangeListener(listener: ViewGroup.OnHierarchyChangeListener?) { // the user listener is delegated to our pass-through listener mPassThroughListener?.mOnHierarchyChangeListener = listener } /** * {@inheritDoc} */ override fun onFinishInflate() { super.onFinishInflate() // checks the appropriate radio button as requested in the XML file if (mCheckedId != -1) { mProtectFromCheckedChange = true setCheckedStateForView(mCheckedId, true) mProtectFromCheckedChange = false setCheckedId(mCheckedId) } } override fun addView(child: View, index: Int, params: ViewGroup.LayoutParams) { if (child is RadioButton) { val button = child if (button.isChecked) { mProtectFromCheckedChange = true if (mCheckedId != -1) { setCheckedStateForView(mCheckedId, false) } mProtectFromCheckedChange = false setCheckedId(button.id) } } super.addView(child, index, params) } /** * * Sets the selection to the radio button whose identifier is passed in * parameter. Using -1 as the selection identifier clears the selection; * such an operation is equivalent to invoking [.clearCheck]. * @param id the unique id of the radio button to select in this group * * * @see .getMCheckedId * @see .clearCheck */ fun check(@IdRes id: Int) { // don't even bother if (id != -1 && id == mCheckedId) { return } if (mCheckedId != -1) { setCheckedStateForView(mCheckedId, false) } if (id != -1) { setCheckedStateForView(id, true) } setCheckedId(id) } private fun setCheckedId(@IdRes id: Int) { mCheckedId = id if (mOnCheckedChangeListener != null) { mOnCheckedChangeListener?.onCheckedChanged(this, mCheckedId) } } private fun setCheckedStateForView(viewId: Int, checked: Boolean) { val checkedView = findViewById<RadioButton>(viewId) if (checkedView != null) { checkedView.isChecked = checked } } /** * * Clears the selection. When the selection is cleared, no radio button * in this group is selected and [.getMCheckedId] returns * null. * @see .check * @see .getMCheckedId */ fun clearCheck() { check(-1) } /** * * Register a callback to be invoked when the checked radio button * changes in this group. * @param listener the callback to call on checked state change */ fun setOnCheckedChangeListener(listener: OnCheckedChangeListener) { mOnCheckedChangeListener = listener } /** * {@inheritDoc} */ override fun generateLayoutParams(attrs: AttributeSet?): LayoutParams { return RadioFlexboxGroup.LayoutParams(context, attrs) } /** * {@inheritDoc} */ override fun checkLayoutParams(p: ViewGroup.LayoutParams?): Boolean { return p is LayoutParams } override fun generateDefaultLayoutParams(): LayoutParams { return LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) } override fun getAccessibilityClassName(): CharSequence { return RadioFlexboxGroup::class.java.name } /** * * This set of layout parameters defaults the width and the height of * the children to [.WRAP_CONTENT] when they are not specified in the * XML file. Otherwise, this class ussed the value read from the XML file. * * * * See * for a list of all child view attributes that this class supports. */ class LayoutParams : FlexboxLayout.LayoutParams { /** * {@inheritDoc} */ constructor(c: Context?, attrs: AttributeSet?) : super(c, attrs) /** * {@inheritDoc} */ constructor(w: Int, h: Int) : super(w, h) /** * {@inheritDoc} */ constructor(p: ViewGroup.LayoutParams?) : super(p) /** * {@inheritDoc} */ constructor(source: ViewGroup.MarginLayoutParams?) : super(source) /** * * Fixes the child's width to * [ViewGroup.LayoutParams.WRAP_CONTENT] and the child's * height to [ViewGroup.LayoutParams.WRAP_CONTENT] * when not specified in the XML file. * @param a the styled attributes set * * * @param widthAttr the width attribute to fetch * * * @param heightAttr the height attribute to fetch */ 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 definition for a callback to be invoked when the checked * radio button changed in this group. */ interface OnCheckedChangeListener { /** * * Called when the checked radio button has changed. When the * selection is cleared, checkedId is -1. * @param group the group in which the checked radio button has changed * * * @param checkedId the unique identifier of the newly checked radio button */ fun onCheckedChanged(group: RadioFlexboxGroup, @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 (mCheckedId != -1) { setCheckedStateForView(mCheckedId, false) } mProtectFromCheckedChange = false val id = buttonView.id setCheckedId(id) } } /** * * A pass-through listener acts upon the events and dispatches them * to another listener. This allows the table layout to set its own internal * hierarchy change listener without preventing the user to setup his. */ private inner class PassThroughHierarchyChangeListener : ViewGroup.OnHierarchyChangeListener { var mOnHierarchyChangeListener: ViewGroup.OnHierarchyChangeListener? = null /** * {@inheritDoc} */ override fun onChildViewAdded(parent: View, child: View) { if (parent === this@RadioFlexboxGroup && child is RadioButton) { var id = child.getId() // generates an id if it's missing if (id == View.NO_ID) { id = generateViewId() child.setId(id) } child.setOnCheckedChangeListener( mChildOnCheckedChangeListener) } mOnHierarchyChangeListener?.onChildViewAdded(parent, child) } /** * {@inheritDoc} */ override fun onChildViewRemoved(parent: View, child: View) { if (parent === this@RadioFlexboxGroup && child is RadioButton) { child.setOnCheckedChangeListener(null) } mOnHierarchyChangeListener?.onChildViewRemoved(parent, child) } } companion object { private val sNextGeneratedId = AtomicInteger(1) fun generateViewId(): Int { while (true) { val result = sNextGeneratedId.get() // aapt-generated IDs have the high byte nonzero; clamp to the range under that. var newValue = result + 1 if (newValue > 0x00FFFFFF) newValue = 1 // Roll over to 1, not 0. if (sNextGeneratedId.compareAndSet(result, newValue)) { return result } } } }}
其实我这里是继承FlexBoxLayout实现的效果,所有拥有FLexBoxLayout的所有属性效果,整体还是很简单的
github地址:https://github.com/ttarfall/RadioFlexboxGroup
阅读全文
0 0
- Kotlin实现RadioFlexboxGroup组件
- 《Kotlin 程序设计》第十一章 Kotlin实现DSL
- kotlin中安卓listview实现
- Kotlin实现propertyAnimator
- kotlin实现登录逻辑
- Kotlin实现recyclerView列表
- < Kotlin > Kotlin For Gank.io (干货集中营Kotlin实现)
- Kotlin类、继承、接口实现
- Kotlin实现MVP设计模式
- Kotlin使用retrofit实现recyclerview
- Kotlin初探:用Kotlin实现Android的ListView列表
- Kotlin
- Kotlin
- Kotlin
- Kotlin
- kotlin
- kotlin
- Kotlin
- 代码小记
- Furion Scheduler的混合负载管理
- 算法题目---树中两个结点的最低公共祖先
- 战争
- 活动中的 findViewById()方法总结以及Button按钮的使用
- Kotlin实现RadioFlexboxGroup组件
- delphi中SendMessage使用说明
- js 获取当前网址/项目地址
- HDU 5875
- QNX驱动开发—APP应用与resource manger的交互通信,进程间通信
- CO-IP技术详解
- 慕课玩转算法课程之动态规划入门——1
- 移动设备手势事件库Touch.js
- ctrl+home在16寸笔记本中的使用