kotlin 单选按钮

The basics of radio buttons is to let the user have a bunch of options but only the possibility to select one of those options. So when a radio button is selected another radio button in the same group has to be deselected. This action always had me thinking if the little selection mark is just one which moves between the options? Or should they be considered physical buttons where the previously selected button pops out when a new option is pressed?

单选按钮基础是用户有一堆选择,但只可能选择这些选项之一。 因此,当选择单选按钮 ,必须取消选择同一组的另一个单选按钮。 我一直在想这个动作是否会使小选择标记只是在选项之间移动的标记? 还是应该将它们视为物理按钮,当按下选项时,先前选择的按钮会弹出?

In this case I’m considering the first one, where there is only one selection which is moved between the options as I think it can be more fun graphically. Let’s make Radio Buttons where the selection slides from its current position in the direction of the new position.

这种情况下,我正在考虑第一个选项,其中只有一个选项在选项之间移动,因为我认为它在图形上会更有趣。 让我们制作单选按钮,使选区从当前位置向新位置的方向滑动。

For this effect we will need to create a custom RadioGroup, a custom RadioButton, and the animations for the button transitions between selected states.

对于这个效果,我们需要创建一个自定义的RadioGroup中,自定义单选按钮,和动画选定状态之间的转换按钮。

In the CustomRadioGroup a reference to which of its CustomRadioButtons is selected is needed. So just create a simple class which extends RadioGroup and includes a reference to the currently selected CustomRadioButton.

CustomRadioGroup需要被选择为其中CustomRadioButton秒的参考。 因此,只需创建一个扩展 RadioGroup并包含对当前所选CustomRadioButton的引用的简单

class CustomRadioGroup : RadioGroup {    lateinit var selectedRadioButton: CustomRadioButton    constructor(context: Context) : super(context)    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(measuredWidth, measuredHeight)
}
}

Then for the CustomRadioButton we also want a reference to the CustomRadioGroup parent for easy access to the currently selected CustomRadioButton as well as an index to indicate where in the list of RadioButtons this button is placed. And we also want to override the toggle function to set the right animation for the newly and previous selected RadioButton.

那么对于CustomRadioButton我们也想为方便到当前选定CustomRadioButtonCustomRadioGroup父级的引用 以及一个指数来指示在单选按钮列表中该按钮被放置。 而且我们还想覆盖切换功能,为新选择的RadioButton和先前选择的RadioButton设置正确的动画。

class CustomRadioButton: AppCompatRadioButton {    var order = -1
lateinit var customRadioGroup: CustomRadioGroup constructor(context: Context) : super(context) constructor(context: Context, attrs: AttributeSet) : super(context, attrs) constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(measuredWidth, measuredHeight)
} /**
* Selects and sets the correct drawable if the previous selection was below or above the current one
*/
override fun toggle() {
if (slidingRadioGroup.selectedRadioButton.order < order) {
setButtonDrawable(R.drawable.ic_radio_up)
slidingRadioGroup.selectedRadioButton.setButtonDrawable(R.drawable.ic_radio_down)
} else {
setButtonDrawable(R.drawable.ic_radio_down)
slidingRadioGroup.selectedRadioButton.setButtonDrawable(R.drawable.ic_radio_up)
}
super.toggle()
}
}

In toggle we want to compare the order of the newly selected RadioButton (order) and the previously selected button (`slidingRadioGroup.selectedRadioButton.order`). If the newly selected RadioButton is further down the list than the previous one, we want the selection to slide down in the previously select RadioButton and come sliding in to the center of the newly selected RadioButton from above. The opposite if the newly selected RadioButton comes before the previous one in the list.

在切换中,我们要比较新选择的RadioButton(顺序)和先前选择的按钮(“ slidingRadioGroup.selectedRadioButton.order”)的顺序。 如果新选择的RadioButton比上一个更靠下,则我们希望选择在先前选择的RadioButton中向下滑动,然后从上方滑入新选择的RadioButton的中心。 如果新选择的RadioButton在列表中的前一个按钮之前,则相反。

Next up we have to create two animated-selectors for sliding up to selected, sliding from selected up, sliding down to selected and sliding from selected down. In `ic_radio_down.xml` I keep the selection and deselection of a RadioButton when the animation come from the bottom or animates towards the bottom. And the opposite in `ic_radio_up.xml`. Here is a zip-file of the drawable resources used in this animation. You can use them as a reference to create your own style.

接下来,我们必须创建两个动画选择器,以向上滑动到选定的位置,从向上选定的位置滑动,向下滑动到选定的位置以及从选定向下滑动的位置。 在ic_radio_down.xml中,当动画来自底部或朝底部动画时,我会保留对RadioButton的选择和取消选择。 与“ ic_radio_up.xml”相反。 这是此动画中使用的可绘制资源的zip文件。 您可以将它们用作创建自己的样式的参考。

ic_radio_down.xml

ic_radio_down.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/unchecked_dis" android:drawable="@drawable/rb_deselected_disabled" android:state_checked="false" android:state_enabled="false"/>
<item android:id="@+id/checked_dis" android:drawable="@drawable/rb_selected_disabled" android:state_checked="true" android:state_enabled="false"/>
<item android:id="@+id/unchecked" android:drawable="@drawable/ic_radio_unchecked" android:state_checked="false" />
<item android:id="@+id/checked" android:drawable="@drawable/ic_radio_checked" android:state_checked="true"/><transition android:fromId="@+id/unchecked" android:toId="@+id/checked">
<animation-list>
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_6" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_5" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_4" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_3" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_2" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_1" />
<item android:duration="18" android:drawable="@drawable/ic_radio_checked" />
</animation-list>
</transition>
<transition android:fromId="@+id/checked" android:toId="@+id/unchecked">
<animation-list>
<item android:duration="18" android:drawable="@drawable/ic_radio_checked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_1" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_2" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_3" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_4" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_5" />
<item android:duration="18" android:drawable="@drawable/ic_radio_down_6" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
</animation-list>
</transition>
</animated-selector>

ic_radio_up.xml

ic_radio_up.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/unchecked_dis" android:drawable="@drawable/rb_deselected_disabled" android:state_checked="false" android:state_enabled="false"/>
<item android:id="@+id/checked_dis" android:drawable="@drawable/rb_selected_disabled" android:state_checked="true" android:state_enabled="false"/>
<item android:id="@+id/unchecked" android:drawable="@drawable/ic_radio_unchecked" android:state_checked="false" />
<item android:id="@+id/checked" android:drawable="@drawable/ic_radio_checked" android:state_checked="true"/><transition android:fromId="@+id/unchecked" android:toId="@+id/checked">
<animation-list>
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_6" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_5" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_4" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_3" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_2" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_1" />
<item android:duration="18" android:drawable="@drawable/ic_radio_checked" />
</animation-list>
</transition>
<transition android:fromId="@+id/checked" android:toId="@+id/unchecked">
<animation-list>
<item android:duration="18" android:drawable="@drawable/ic_radio_checked" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_1" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_2" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_3" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_4" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_5" />
<item android:duration="18" android:drawable="@drawable/ic_radio_up_6" />
<item android:duration="18" android:drawable="@drawable/ic_radio_unchecked" />
</animation-list>
</transition>
</animated-selector>

As can be seen in both files, the animation from unchecked to checked has six images where there is no animation, this is to delay the entry of the selection to make it look like the selection mark had to travel a little bit before entering the newly selected radio button.

从两个文件都可以看出从未选中到选中的动画有六个图像,其中没有动画, 是为了延迟选择的输入以使其看起来像选择标记在进入新的位置之前必须经过一点移动选中的单选按钮。

That’s pretty much all you need to have sliding radio buttons. To use them just add the newly created CustomRadioGroup to your layout file, something similar to this.

这就是拥有滑动单选按钮所需的全部内容。 要使用它们,只需将新创建的CustomRadioGroup添加到您的布局文件即可。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background">...<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:fadeScrollbars="false"><com.app.views.CustomRadioGroup
android:id="@+id/customRadioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="24dp"
android:layout_marginRight="24dp"
android:layout_marginBottom="16dp"/></ScrollView>...</RelativeLayout>

Then all you have to do is to populate the CustomRadioGroup with some CustomRadioButtons.

然后,您要做的就是用一些CustomRadioButton填充CustomRadioGroup。

customRadioGroup.setOnCheckedChangeListener(null)
customRadioGroup.removeAllViews()
customRadioGroup.selectedRadioButton = CustomRadioButton(this)
for ((index, option) in listOfOptions.withIndex()) {
val customRadioButton = CustomRadioButton(this)
customRadioButton.id = View.generateViewId()
customRadioButton.order = index
customRadioButton.slidingRadioGroup = customRadioGroup
customRadioButton.text = option.name
customRadioGroup.addView(customRadioButton)
}customRadioGroup.setOnCheckedChangeListener { radioGroup, clickedButton ->
val customRadioButton: CustomRadioButton = radioGroup.findViewById(clickedButton)
if (customRadioButton.isChecked) {
customRadioGroup.selectedRadioButton = customRadioButton
}
}

The first two lines are only needed if you need to refresh the CustomRadioGroup with new buttons. The third line sets the default selection, which in this case is just an empty selection, but you could bake it in to the for loop. In the for loop it’s pretty straight forward. Set an ID, order, the CustomRadioGroup, name and then add it to the `customRadioGroup` parent.

仅在需要使用新按钮刷新CustomRadioGroup时才需要前两行。 第三行设置默认选择,在这种情况下,这只是一个空选择,但是您可以将其烘烤到for循环中。 在for循环中,它非常简单。 设置ID,顺序, CustomRadioGroup和名称,然后将其添加到`customRadioGroup`父级。

Last we have to add a `setOnCheckedChangeListener` to the radio group, get the RadioButton which just changed, and if its checked, set it as the currently selected CustomRadioButton in the CustomRadioGroup.

最后,我们必须向单选组添加一个“ setOnCheckedChangeListener”,获取刚刚更改的RadioButton,如果选中,则将其设置为CustomRadioGroup中当前选择的CustomRadioButton

This article was originally published here.

本文最初发表在这里

翻译自: https://medium.com/@andreborud/sliding-radio-buttons-in-android-using-kotlin-7a023b986f75

kotlin 单选按钮

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐