反应原生的TextInput焦点样式

时间:2015-12-04 11:34:10

标签: react-native

在React Native中,当焦点变为焦点时,如何更改textInput的样式?说我有像

这样的东西
class MyInput extends Component {
    render () {
        return <TextInput style={styles.textInput} />;
    }
};

const stylesObj = {
    textInput: {
        height: 50,
        fontSize: 15,
        backgroundColor: 'yellow',
        color: 'black',
    }
};
const styles = StyleSheet.create(stylesObj);

我想将焦点上的背景颜色更改为green

This documentation让我相信解决方案就像

class MyInput extends Component {
    constructor (props) {
        super(props);
        this.state = {hasFocus: false};
    }

    render () {
        return (<TextInput
            style={this.state.hasFocus ? styles.focusedTextInput : styles.textInput}
            onFocus={this.setFocus.bind(this, true)}
            onBlur={this.setFocus.bind(this, false)}
        />);
    }

    setFocus (hasFocus) {
        this.setState({hasFocus});
    }
};

const stylesObj = {
    textInput: {
        height: 50,
        fontSize: 15,
        backgroundColor: 'yellow',
        color: 'black',
    }
};
const styles = StyleSheet.create({
    ...stylesObj,
    focusedTextInput: {
        ...stylesObj,
        backgroundColor: 'green',
    }
});

忽略样式结构中的潜在错误,这会被认为是处理它的正确方法吗?这对我来说似乎非常冗长。

9 个答案:

答案 0 :(得分:25)

你可以通过传入onFocus和onBlur事件来实现这一点,以便在聚焦和模糊时设置和取消设置样式:

  onFocus() {
    this.setState({
        backgroundColor: 'green'
    })
  },

  onBlur() {
    this.setState({
      backgroundColor: '#ededed'
    })
  },

然后,在TextInput中执行此操作:

<TextInput 
    onBlur={ () => this.onBlur() }
    onFocus={ () => this.onFocus() }
    style={{ height:60, backgroundColor: this.state.backgroundColor, color: this.state.color }}  />

我已经设置了一个完整的工作项目here。我希望这有帮助!

https://rnplay.org/apps/hYrKmQ

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput
} = React;

var SampleApp = React.createClass({

  getInitialState() {
    return {
        backgroundColor: '#ededed',
      color: 'white'
    }
  },

  onFocus() {
        this.setState({
        backgroundColor: 'green'
    })
  },

  onBlur() {
    this.setState({
      backgroundColor: '#ededed'
    })
  },

  render: function() {
    return (
      <View style={styles.container}>
       <TextInput 
        onBlur={ () => this.onBlur() }
        onFocus={ () => this.onFocus() }
        style={{ height:60, backgroundColor: this.state.backgroundColor, color: this.state.color }}  />
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop:60
  }
});

AppRegistry.registerComponent('SampleApp', () => SampleApp);

答案 1 :(得分:3)

当元素聚焦/模糊时,控制样式的最佳方法是创建自己的TextInput包装器

export const MyAppTextInput = (props) => {
  return (
    <TextInput
      {...props}
    />
  );
};

请注意,{...props}将传入您已经设置或可用于TextInput的任何属性。

然后通过添加状态以在聚焦/模糊时应用样式来扩展上述组件

export const MyAppTextInput = (props) => {
  const [isFocused, setIsFocused] = useState(false);
  return (
    <TextInput
      {...props}
      style={[props.style, isFocused && {borderWidth: 5, borderColor: 'blue'}]}
      onBlur={() => setIsFocused(false)}
      onFocus={() => setIsFocused(true)}
    />
  );
};

请记住,如示例所示,使用组件绑定值时(请参见value={passwordText});否则,状态更改后,随着新渲染的开始,该值将模糊消失。

<MyAppTextInput
          style={styles.input}
          value={passwordText}
          textContentType="password"
          autoCompleteType="off"
          secureTextEntry
          onChangeText={text => {
            setPasswordText(text);
          }}
        />

您当然可以避免创建包装器,但是如果输入多个,则会在输入父组件中造成混乱,因为您必须添加重复逻辑。

答案 2 :(得分:2)

使用refs,DirectManipulation和setNativeProps来提高性能:https://facebook.github.io/react-native/docs/direct-manipulation

class MyInput extends Component {
  focusedInput = () => { 
    this.textInput.setNativeProps({
      style: { backgroundColor: 'green' }
    }) 
  }

  blurredInput = () => { 
    this.textInput.setNativeProps({
      style: { backgroundColor: 'yellow' }
    }) 
  }

  render () {
      return <TextInput 
                ref={c => { this.textInput = c}} 
                style={styles.textInput}
                onFocus={this.focusedInput}
                onBlur={this.blurredInput} />
  }

}

const stylesObj = {       textInput:{           高度:50,           字号:15           backgroundColor:“黄色”,           颜色:“黑色”,       }   }

常量样式= StyleSheet.create(stylesObj)

这将直接更新TextInput组件,而无需重新呈现组件层次结构。

答案 3 :(得分:1)

Nader Dabit指出我做类似的事情 - 使用状态作为样式 - 但我认为如果为聚焦和不聚焦的样式创建单独的样式并仅传递样式ID,则可以以更清晰的方式完成如下:

this.state.style

在渲染中 - 由<TextInput onBlur={ () => this.onBlur() } onFocus={ () => this.onFocus() } style={ [styles.textinput, this.state.style] } /> 中的styleID引用,请注意不同的样式如何作为数组传递:

textinput_focused: {
  backgroundColor: 'red',
  color: 'white'
}
textinput_unfocused: {
  backgroundColor: 'green'
}

+你的样式表单点:

namespace _2D_game_num1
{
    class Enemy
    {
        int health;
        Vector2 enemy_location = new Vector2(50, 50);
        Vector2 enemy_speed = new Vector2(1, 1);
        Player player = new Player("dummy");

        public Enemy()
        {
            health = 100;
        }

        public void UpdateLocation()
        {
            //Vector2 player_pos = player.GetLocation();
            //if (player_pos.X < 200)
            // Using the players location to figure out where the enemy should move
            bool right = true;
            bool left = false;
            if (right)
            {
                enemy_location.X += enemy_speed.X;
                if (enemy_location.X == 500)
                {
                    right = false;
                    left = true;
                }
            }

            if (left)
            {
                enemy_location.X -= enemy_speed.X;
                if (enemy_location.X == 50)
                {
                    right = true;
                    left = false;
                }
            }

        }

        public Vector2 GetLocation()
        {
            return enemy_location;
        }


    }
}

答案 4 :(得分:1)

 <TextInput
 style={{ backgroundColor: 'white', height: 40, width: 100, alignItems: 'center' 
   }} 
 theme={{ colors: { placeholder: 'white', text: 'white', primary: 'white', 
  underlineColor: 'transparent', background: '#003489' } }}
   />

答案 5 :(得分:0)

嘿,我有点用大家的主意:p

@Felix给了我一个可能更干净的想法。 (我本来不想在静态组件中包含状态,只是为了改变样式。但是我对此很陌生,以便弄清楚。

这是我的解决方法:

import React, { Component } from 'react';
import { StyleSheet, TextInput } from 'react-native';

class TxtInput extends Component {
  constructor(props) {
    super(props);
    this.state = {
      style: {},
    };
  }

  onFocus = () => {
    const state = { ...this.state };
    state.style = {
      borderStyle: 'solid',
      borderColor: '#e74712',
    };

    this.setState(state);
  }

  onBlur = () => {
    console.log('on ONBLUR')
    const state = { ...this.state };
    state.style = {};

    this.setState(state);
  }

  render = () => <TextInput style={[styles.input, this.state.style]} onFocus={() => this.onFocus()} onBlur={() => this.onBlur()} />;
}

const styles = StyleSheet.create({
  input: {
    color: '#000000',
    fontFamily: 'MuseoSans 700 Italic',
    fontSize: 22,
    borderRadius: 34,
    borderStyle: 'solid',
    borderColor: 'transparent',
    borderWidth: 5,
    backgroundColor: '#ffffff',
    textAlign: 'center',
    width: '25%',
 },
});

export default TxtInput;

我将样式添加到数组中,对数组的第一个属性进行了所有实际的输入样式,第二个完成了焦点和蓝色的选择。

希望有帮助

答案 6 :(得分:0)

您可以创建一个状态来跟踪输入状态,并使用该状态来切换样式。这是一个简单的例子

const App = () => {
  const [isActive, setActive] = useState(false);

  return (
    <TextInput style={{ color: isActive ? 'black' : 'grey' }} onFocus={() => setActive(true)} onBlur={() => setActive(false)}/>
  );
}

答案 7 :(得分:0)

为此,我在功能组件中设计了这个简单的逻辑(它在类组件中的工作原理相同,但相关更改),它可以应用于多个 <textinputs/>。下面我举个例子:

// state
     const [isFocused, setIsFocused] = useState({
       name: false,
       email: false,
       phone: false,
     })
// handlers
     const handleInputFocus = (textinput) => {
       setIsFocused({
         [textinput]: true
       })
     }
     const handleInputBlur = (textinput) => {
       setIsFocused({
         [textinput]: false
       })
     }
// JSX

     <View style={styles.form} >
        <TextInput
          style={isFocused.name ? [styles.inputs, { borderColor: 'blue' }] : styles.inputs}
          placeholder='Name'
          placeholderTextColor={darkColors.text}
          textContentType='name'
          keyboardType='default'
          onFocus={() => handleInputFocus('name')}
          onBlur={() => handleInputBlur('name')}
        />
        <TextInput
          style={isFocused.email ? [styles.inputs, { borderColor: 'blue' }] : styles.inputs}
          placeholder='Email'
          placeholderTextColor={darkColors.text}
          textContentType='emailAddress'
          keyboardType='email-address'
          onFocus={() => handleInputFocus('email')}
          onBlur={() => handleInputBlur('email')}
        />
        <TextInput
          style={isFocused.phone ? [styles.inputs, { borderColor: 'blue' }] : styles.inputs}
          placeholder='Phone'
          placeholderTextColor={darkColors.text}
          keyboardType='phone-pad'
          onFocus={() => handleInputFocus('phone')}
          onBlur={() => handleInputBlur('phone')}
        />
      </View>

答案 8 :(得分:0)

在函数组件中设置初始值

const [warnColor, setWrnColor] = useState("grey");

在文本输入中设置

style={[styles.brdColor, { borderColor: warnColor }]}

在样式表中设置

 brdColor: {
    height: 40,
    borderColor: "grey",
    borderBottomWidth: 1,
    marginTop: heightToDp("2%"),
    width: "100%",
  }