材质 UI<单选按钮/>,外观类似<按钮/>



仅使用材质UI,是否有任何方法可以将<Radio />对象设置为<Button />类型的外观?如果没有,最简单的选择是什么?

在花了几天时间阅读文档并进行实验之后,我觉得离解决方案不远了。感谢任何能提供指导的人。

以下是我的出发点(没有<Button />实验(,以防有人想使用我正在使用的东西:

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import RadioGroup from '@material-ui/core/RadioGroup';
import Radio from '@material-ui/core/Radio';
import Button from '@material-ui/core/Button';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';
const styles = theme => ({
textField: {
marginLeft: theme.spacing.unit,
marginRight: theme.spacing.unit,
width: '100%',
},
formControl: {
display: 'flex',
flexBasis: '100%',
alignItems: 'center',
}
});
class QRadios extends React.PureComponent {
constructor(props, context) {
super(props, context);
this.state = {
value: this.props.value,
};
}
handleChange = event => {
this.setState({
value: event.target.value,
},
this.props.onChange(event)); 
};
render() {
const { classes } = this.props;
return (
<FormControl component="ul" className={classes.formControl} required>
<RadioGroup
row={true}
id={this.props.id}
name={this.props.name}
value={this.state.value}
onChange={this.handleChange}
>
<FormControlLabel
htmlFor={this.props.id}
value="good"
control={<Radio />} 
/>
<FormControlLabel
htmlFor={this.props.id}
value="okay"
control={<Radio />}
/>
<FormControlLabel
htmlFor={this.props.id}
value="bad"
control={<Radio />} 
/>
<FormControlLabel
htmlFor={this.props.id}
value="na"
control={<Radio />} 
/>
</RadioGroup>
</FormControl>
);
}
}
QRadios.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(QRadios);

更新:

对于任何使用旧版本的Material UI的人,如果没有下面的答案所示的内置解决方案,你必须为按钮创建自己的CSS。如果你需要帮助,我就是这样实现的:

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import green from '@material-ui/core/colors/green';
import yellow from '@material-ui/core/colors/yellow';
import red from '@material-ui/core/colors/red';
import grey from '@material-ui/core/colors/grey';
import RadioGroup from '@material-ui/core/RadioGroup';
import Radio from '@material-ui/core/Radio';
import FormControl from '@material-ui/core/FormControl';
import InputLabel from '@material-ui/core/InputLabel';
const styles = theme => ({
formControl: {
display: 'flex',
flexBasis: '100%',
alignItems: 'stretch',
margin: theme.spacing.unit * 3 / 2
},
formGroup: {
alignItems: 'stretch',
justifyContent: 'space-around',
flexWrap: 'nowrap'
},
radioFlex: {
flex: '1 1 auto',
margin: '0 5px'
},
greenButtonRoot: {
backgroundColor: '#00000004',
borderRadius: 5,
border: '1px solid',
color: green.A700,
fontFamily: 'monospace',
fontSize: '180%',
height: 32,
'&$checked': {
backgroundColor: green.A700,
color: 'white'
},
'&:not($checked):hover': {
backgroundColor: green['50']
},
transition: 'background-color 250ms'
},
yellowButtonRoot: {
backgroundColor: '#00000004',
borderRadius: 5,
border: '1px solid',
color: yellow['700'],
fontFamily: 'monospace',
fontSize: '200%',
height: 32,
'&$checked': {
backgroundColor: yellow.A700,
color: 'white'
},
'&:not($checked):hover': {
backgroundColor: yellow['100']
},
transition: 'background-color 250ms'
},
redButtonRoot: {
backgroundColor: '#00000004',
borderRadius: 5,
border: '1px solid',
color: red.A700,
fontFamily: 'monospace',
fontSize: '160%',
height: 32,
'&$checked': {
backgroundColor: red.A700,
color: 'white'
},
'&:not($checked):hover': {
backgroundColor: red['50']
},
transition: 'background-color 250ms'
},
greyButtonRoot: {
backgroundColor: '#00000004',
borderRadius: 5,
border: '1px solid',
color: grey['700'],
fontFamily: 'monospace',
fontSize: '180%',
height: 32,
'&$checked': {
backgroundColor: grey['700'],
color: 'white'
},
'&:not($checked):hover': {
backgroundColor: grey['200']
},
transition: 'background-color 250ms'
},
disabled: {
backgroundColor: '#00000004'
},
checked: {}
});
function QRadios(props) {
const {
classes,
error,
required,
id,
label,
name,
binaryChoice,
value,
onChange,
onBlur
} = props;
return (
<FormControl className={classes.formControl} required={required}>
<InputLabel
error={error}
required={required}
shrink
style={{
position: 'relative',
marginBottom: '10px'
}}
>
{label}
</InputLabel>
<RadioGroup
className={classes.formGroup}
row
id={id}
name={name}
value={value}
onChange={onChange}
onBlur={onBlur}
>
<Radio
htmlFor={id}
className={classes.radioFlex}
value="good"
classes={{
root: classes.greenButtonRoot,
checked: classes.checked
}}
icon="〇"
checkedIcon="〇"
/>
<Radio
htmlFor={id}
className={classes.radioFlex}
value="okay"
classes={{
root: classes.yellowButtonRoot,
checked: classes.checked,
disabled: classes.disabled
}}
icon="△"
checkedIcon="△"
disabled={binaryChoice}
/>
<Radio
htmlFor={id}
className={classes.radioFlex}
value="bad"
classes={{
root: classes.redButtonRoot,
checked: classes.checked
}}
icon="✕"
checkedIcon="✕"
/>
<Radio
htmlFor={id}
className={classes.radioFlex}
value="na"
classes={{
root: classes.greyButtonRoot,
checked: classes.checked
}}
icon="-"
checkedIcon="-"
/>
</RadioGroup>
</FormControl>
);
}
QRadios.propTypes = {
classes: PropTypes.object.isRequired,
required: PropTypes.bool,
error: PropTypes.bool,
id: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
binaryChoice: PropTypes.bool,
value: PropTypes.string,
onChange: PropTypes.func.isRequired,
onBlur: PropTypes.func
};
QRadios.defaultProps = {
required: false,
binaryChoice: false,
error: false,
onBlur: null,
value: ''
};
export default withStyles(styles)(QRadios);

用法。。。

<QRadios
error={!whateverThing.isValid}
id="whateverThing"
name="whateverThing"
label="What's your judgement of whateverThing?"
value={whateverThing.value}
onChange={this.someHandlerFunc}
onBlur={this.someCheckFunc}
/>

您有没有调查过https://material-ui.com/components/toggle-button/或https://material-ui.com/api/toggle-button-group/?我认为这是一个相对较新的添加(即,当你解决这个问题时并不存在(,但它可能对以后发现这个问题的人有所帮助。

ToggleButtonGroup将在给定其自己的值道具时控制其子按钮的选定状态。

下面是该页面上给出的示例:

<ToggleButtonGroup
value={alignment}
exclusive
onChange={handleAlignment}
aria-label="text alignment"
>
<ToggleButton value="left" aria-label="left aligned">
<FormatAlignLeftIcon />
</ToggleButton>
<ToggleButton value="center" aria-label="centered">
<FormatAlignCenterIcon />
</ToggleButton>
<ToggleButton value="right" aria-label="right aligned">
<FormatAlignRightIcon />
</ToggleButton>
<ToggleButton value="justify" aria-label="justified" disabled>
<FormatAlignJustifyIcon />
</ToggleButton>
</ToggleButtonGroup>

这是你可以让一个单选按钮有一个类似的按钮,我已经为此创建了一支笔,请检查https://codepen.io/praveen-rao-chavan/pen/JBpgLX

<section>
<h1>Simple material design CSS only radio button example</h1>
<div>
<ul  class="donate-now">
<li class="md-radio">
<input id="1" type="radio" name="g" checked>
<label for="1">Option 1</label>
</li>
<li class="md-radio">
<input id="2" type="radio" name="g">
<label for="2">Option 2</label>
</li>
</ul>
</div>
</section>

CSS

@import url(https://fonts.googleapis.com/css?family=Roboto);
$md-radio-checked-color: rgb(51, 122, 183);
$md-radio-border-color: rgba(0, 0, 0, 0.54);
$md-radio-size: 20px;
$md-radio-checked-size: 10px; 
$md-radio-ripple-size: 15px;
@keyframes ripple {
0% {
box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.0);
}
50% { 
box-shadow: 0px 0px 0px $md-radio-ripple-size rgba(0, 0, 0, 0.1);
}
100% {
box-shadow: 0px 0px 0px $md-radio-ripple-size rgba(0, 0, 0, 0);
}
}
.md-radio {
margin: 16px 0;
&.md-radio-inline {
display: inline-block;
}
input[type="radio"] {
display: none;
&:checked + label:before {
--border-color: $md-radio-checked-color;
--animation: ripple 0.2s linear forwards;   
}
&:checked + label:after {
--transform: scale(1);
}
}
label {
display: inline-block;
height:$md-radio-size;
position: relative;
padding: 0 ($md-radio-size + 10px);
margin-bottom: 0;
cursor: pointer;
vertical-align: bottom;
&:before, &:after {
position: absolute;            
content: '';  
border-radius: 50%;
transition: all .3s ease;
transition-property: transform, border-color;
}
&:before {
left: 0;
top: 0;
width: $md-radio-size;
height: $md-radio-size;
border: 2px solid $md-radio-border-color;
}
&:after {
top: $md-radio-size / 2 - $md-radio-checked-size / 2;
left: $md-radio-size / 2 - $md-radio-checked-size / 2;
width:$md-radio-checked-size;
height:$md-radio-checked-size;
transform: scale(0);
background:$md-radio-checked-color;
}
}
}

// *************************************
// *************************************
*, *:before, *:after {
box-sizing: border-box;
}
body {
background:#f0f0f0;
position: absolute;
width:100%;
padding:0;
margin:0;
font-family: "Roboto", sans-serif;
color: #333;
}
section {
background:white;
margin:0 auto;
padding: 4em;
max-width: 800px;
h1 {
margin: 0 0 2em;
}
}

.donate-now {
list-style-type:none;
margin:25px 0 0 0;
padding:0;
}
.donate-now li {
float:left;
margin:0 5px 0 0;
width:100px;
height:40px;
position:relative;
}
.donate-now label, .donate-now input {
display:block;
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
}
.donate-now input[type="radio"] {
opacity:0.011;
z-index:100;
}
.donate-now input[type="radio"]:checked + label {
background:yellow;
}
.donate-now label {
padding:5px;
border:1px solid #CCC; 
cursor:pointer;
z-index:90;
}
.donate-now label:hover {
background:#DDD;
}

您可以根据自己的风格进行自定义。

我使用MUi5切换按钮并覆盖它们的样式,使其成为类似的按钮

检查我的代码沙盒链接

最新更新