JKになりたい

何か書きたいことを書きます。主にWeb方面の技術系記事が多いかも。

俺が求めてるボタンはTouchableHighlightじゃない

ReactNativeではボタンを作る時にTouchableHighlightを使う。
デフォルトでは押した時にunderlayColorで指定した色が背景に表示される。
こんな感じ。
f:id:deeptoneworks:20160923205340g:plain

おかしいやん。誰が求めてるの?テキストじゃなくて画像のボタンだったらいいんだけどね。

求めてるのはiOSのデフォルトのボタンみたいに、テキストがハイライトするやつ。
こんなやつ。
f:id:deeptoneworks:20160923205747g:plain

これを作るのが若干めんどい・・・。
TouchableHighlightコンポーネントじゃ実装できないので、TouchableWithoutFeedbackコンポーネントを使う。
これは名前の通り、デフォルトのままでは押しても何の反応も示さない。
このコンポーネントのonPressInとonPressOut propsをいじってテキストがハイライトするように実装する。

_onPressButton(){
//some action
}
_textColor(){
    if(this.state.isHighlight){
        return styles.textHighlight;
    }
    return styles.textNormal;
}
_highlightText(){
    this.setState({isHighlight:true});
}
_resetText(){
    this.setState({isHighlight:false});
}
render() {
    return (
        <View>
        <TouchableWithoutFeedback onPress={this._onPressButton.bind(this)} onPressIn={this._highlightText.bind(this)} onPressOut={this._resetText.bind(this)}>
        <View style={styles.button}>
        <Text style={this._textColor()}>サンプル</Text>
        </View>
        </TouchableWithoutFeedback>
        </View>
        );
}
}
const styles = StyleSheet.create({
    button: {
        top: 100,
        width:80,
        left:100,
    },
    textHighlight:{
        color:‘#90C3D4’,
    },
    textNormal:{
        color:‘#31ADD6’,
    },
});

f:id:deeptoneworks:20160923210513g:plain

でーきた。
ほんまにこんな実装でええんか・・?

やってる事は単純で、ボタンを押した時と離した時でisHighlight statusを切り替えて、this._textColor()で渡されるスタイルを切り替えている。
やりたい事は凄いシンプルなのに、若干めんどいなあ。。

ちなみに、TouchableHighlightコンポーネントは直下の子にTextとかImageコンポーネントを持ってこれるけど、TouchableWithoutFeedbackはダメっぽい。
Viewでラップしてあげましょう。

(追記)
こんな感じのコンポーネントにしたよ

import React, { Component } from ‘react’;
import {StyleSheet, Text, View ,TouchableWithoutFeedback} from ‘react-native’;
class TouchableHighlightText extends Component {
    constructor(props) {
        super(props);
        this.state = {isHighlight:false};
        this.styles = StyleSheet.create({
            textHighlight:{
                color:props.highLightColor,
            },
            textNormal:{
                color:props.defaultColor,
            },
        });
    }
    _onPressButton(){
        this.props.action();
    }
    _textColor(){
        if(this.state.isHighlight){
            return this.styles.textHighlight;
        }
        return this.styles.textNormal;
    }
    _highlightText(){
        this.setState({isHighlight:true});
    }
    _resetText(){
        this.setState({isHighlight:false});
    }
    render() {
        return (
            <TouchableWithoutFeedback onPress={this._onPressButton.bind(this)} onPressIn={this._highlightText.bind(this)} onPressOut={this._resetText.bind(this)}>
            <View style={this.props.style}>
            <Text style={this._textColor()}>{this.props.titleLabel}</Text>
            </View>
            </TouchableWithoutFeedback>
            );
        }
    }
    TouchableHighlightText.PropTypes = {
        titleLabel:React.PropTypes.string.isRequired,
        highLightColor:React.PropTypes.string.isRequired,
        defaultColor:React.PropTypes.string.isRequired,
        action:React.PropTypes.func.isRequired
    };
export default TouchableHighlightText;