React Native開発者必見:Textコンポーネントをグレーアウトして無効に見せるスタイリングテクニック
しかし、React Nativeでテキスト表示を「無効化された」ように見せたり、ユーザーの操作を制限したりする方法はいくつかあります。文脈によって意味合いが変わってくるので、いくつかパターンを説明します。
TextInputにおける「無効化」
もしあなたが入力可能なテキストフィールド(TextInput
)について話しているのであれば、disabled
に相当する機能はeditable
プロパティで実現できます。
通常のText
コンポーネントはテキストを表示するだけで、直接ユーザーが操作するものではありません。そのため、HTMLのようにdisabled
属性で「無効化」する意味合いは薄いです。
しかし、以下のような意味で「無効化」された表示をしたい場合があります。
-
アクセシビリティにおける「無効化」: スクリーンリーダーなどの支援技術を使用するユーザー向けに、「このテキストは現在操作できません」という情報を伝える必要がある場合があります。React Nativeの
Text
コンポーネントにはaccessibilityState
プロパティがあり、これに{ disabled: true }
を設定することで、スクリーンリーダーに「無効」であることを伝えることができます。 ただし、通常のText
コンポーネントはそもそも操作対象ではないため、このプロパティが直接的に大きな影響を与えることは稀です。主に、Text
をTouchableOpacity
などの操作可能なコンポーネントの内部に配置し、その操作可能なコンポーネント自体を無効化する場合に、合わせて視覚的な表現やアクセシビリティ情報を付与することが一般的です。import React from 'react'; import { Text, View, StyleSheet, TouchableOpacity } from 'react-native'; function App() { const isButtonDisabled = true; return ( <View style={styles.container}> <TouchableOpacity onPress={() => alert('ボタンが押されました!')} disabled={isButtonDisabled} // TouchableOpacity自体を無効化 style={[styles.button, isButtonDisabled && styles.disabledButton]} accessibilityState={{ disabled: isButtonDisabled }} // アクセシビリティ状態も設定 > <Text style={styles.buttonText}> {isButtonDisabled ? "無効なボタン" : "有効なボタン"} </Text> </TouchableOpacity> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, button: { backgroundColor: 'blue', padding: 10, borderRadius: 5, }, disabledButton: { backgroundColor: 'gray', opacity: 0.7, }, buttonText: { color: 'white', fontSize: 18, }, }); export default App;
-
視覚的に「無効」に見せる: CSSの
opacity
(透明度)やcolor
(色)を使って、テキストを灰色にしたり、薄く表示したりすることで、ユーザーにそれが非アクティブであることを示唆できます。これは、関連するボタンや入力フィールドが無効な場合に、そのテキストも視覚的に無効な状態であることを示すためによく行われます。import React from 'react'; import { Text, View, StyleSheet } from 'react-native'; function App() { const isDisabled = true; // またはstateで管理 return ( <View style={styles.container}> <Text style={styles.normalText}>通常のテキスト</Text> <Text style={[styles.normalText, isDisabled && styles.disabledText]}> {isDisabled ? "無効化されたテキスト" : "有効なテキスト"} </Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, normalText: { fontSize: 20, color: 'black', marginBottom: 10, }, disabledText: { color: 'gray', opacity: 0.5, // 半透明にする }, }); export default App;
React NativeのText
コンポーネントに直接disabled
プロパティは存在しません。
- アクセシビリティの観点から「無効」であることを伝える場合は、親の操作可能なコンポーネント(例:
TouchableOpacity
)のdisabled
プロパティとaccessibilityState
プロパティを適切に設定します。 - 表示用のテキスト(
Text
)を視覚的に無効に見せる場合は、style
プロパティで色や透明度を調整します。 - 入力可能なテキスト(
TextInput
)を無効にする場合は、editable={false}
を使用します。
-
TextInput
コンポーネントのeditable={false}
に関連する問題:Text
と名前が似ているTextInput
コンポーネントは、テキスト入力フィールドであり、editable
プロパティで入力の可否を制御します。このeditable={false}
の使用時に発生する可能性のある問題です。 -
Text
コンポーネントを「無効」に見せるためのスタイリングやアクセシビリティ設定に関連する問題:Text
コンポーネント自体は入力機能を持たないため、通常はスタイル(色、透明度など)で「無効」であることを視覚的に表現したり、アクセシビリティのために情報を付与したりします。これらの設定で発生する問題です。
それぞれの文脈での一般的なエラーとトラブルシューティングを説明します。
TextInputにおけるeditable={false}に関連する一般的なエラーとトラブルシューティング
TextInput
のeditable={false}
は、ユーザーがテキストを入力・変更できないようにするプロパティです。
一般的なエラー/問題
value
とdefaultValue
の混同:TextInput
の値を制御する際に、value
とdefaultValue
のどちらを使うべきか、混乱して期待通りに表示されないことがあります。- スタイルが期待通りに適用されない:
editable={false}
にしたときに、無効化された見た目(例: グレーアウト)にしたいのに、スタイルが適用されない、または他のスタイルと競合してしまう。 - 入力できないはずなのに、キーボードが表示される、または選択できてしまう:
editable={false}
を設定しても、一部のプラットフォームや状況でテキストの選択やキーボードの表示が完全に抑制されない場合があります。特にAndroidで発生しやすいです。
トラブルシューティング
value
とdefaultValue
の使い分け:TextInput
の値をプログラムから完全に制御したい場合は、value
プロパティを使用し、onChangeText
でその値を更新する「制御コンポーネント」として扱います。- 初期値を設定するだけで、それ以降はユーザーの入力に任せたい場合は、
defaultValue
を使用します。editable={false}
の場合は、defaultValue
を使うのが一般的です。
- スタイルの競合/適用漏れ:
- 無効化されたスタイルを適用する際は、通常のスタイルと競合しないように、条件付きでスタイルを適用する(例:
[styles.base, isDisabled && styles.disabled]
)ことを確認してください。 TextInput
はデフォルトで特定のスタイルを持っている場合があるので、明示的に上書きする必要があるかもしれません。
- 無効化されたスタイルを適用する際は、通常のスタイルと競合しないように、条件付きでスタイルを適用する(例:
- キーボード表示や選択の抑制:
editable={false}
に加えて、以下のプロパティも試してみてください。selectTextOnFocus={false}
: フォーカス時にテキストが自動選択されるのを防ぎます。showSoftInputOnFocus={false}
: フォーカス時にソフトキーボードが表示されるのを防ぎます。
- これらのプロパティを組み合わせることで、より完全にユーザー操作を制限できます。
Textコンポーネントを「無効」に見せるためのスタイリングやアクセシビリティ設定に関連する一般的なエラーとトラブルシューティング
Text
コンポーネントは入力機能を持たないため、視覚的な表現やアクセシビリティに関する問題が中心になります。
一般的なエラー/問題
- カスタムフォントが適用されない: 無効化されたテキストのスタイルとしてカスタムフォントを使用しようとしたときに、フォントが正しく表示されないことがあります。
- アクセシビリティの誤解:
Text
に直接accessibilityState={{ disabled: true }}
を設定しても、それが単なるテキスト表示であるため、スクリーンリーダーが「無効」と読み上げることに違和感を感じることがあります。これは、操作可能なコンポーネント(ボタンなど)の一部としてテキストを配置する場合に、その操作可能なコンポーネント全体が無効であることを示すために使われるのが適切です。 - プラットフォームごとの表示の違い: 特定のスタイリング(特にフォント関連)がiOSとAndroidで見た目が異なる場合があります。
- スタイルが子コンポーネントに継承されない:
Text
の子要素として別のText
をネストした場合、親のText
に設定したスタイル(特にopacity
やcolor
)が子に継承されないことがあります。- 例:
<Text style={{ opacity: 0.5 }}><Text>子テキスト</Text></Text>
の場合、子テキストの透明度が親から継承されないことがあります。
- 例:
トラブルシューティング
- カスタムフォントの適用:
- カスタムフォントが正しくバンドルされているか確認してください。
react-native.config.js
にフォントのパスが正しく設定されており、npx react-native link
またはnpx react-native-asset
が実行されているか確認します。 fontWeight
プロパティがカスタムフォントのファイル名や含まれるスタイルと競合していないか確認します(例:Roboto-Bold.ttf
を使用しているのにfontWeight: 'normal'
を設定すると表示がおかしくなるなど)。カスタムフォントを使う場合は、fontFamily
で正確なフォント名を指定し、fontWeight
はできるだけ避けるか、フォントファミリーが提供するウェイトに合わせて使用します。
- カスタムフォントが正しくバンドルされているか確認してください。
- アクセシビリティの適切な使用:
Text
は本来、ユーザーの操作対象ではないため、accessibilityState={{ disabled: true }}
を直接設定するよりも、TouchableOpacity
やPressable
のような操作可能なコンポーネントの中にText
を配置し、それらのコンポーネントにdisabled
プロパティを設定する方が適切です。Text
自体を無効と伝える必要がある場合は、そのテキストが何らかのインタラクションと関連していることを前提とし、それが無効であることを示すべきです。
- プラットフォームごとの表示の違い:
Platform.select
を使用して、OSごとに異なるスタイルを適用することを検討します。- 特にフォント関連のスタイルは、各OSのレンダリングエンジンやデフォルトフォントが異なるため、注意が必要です。
- スタイルの継承問題:
- React Nativeの
Text
は、CSSのような完全な継承ルールを持ちません。特にopacity
などのプロパティは、子要素に明示的に設定する必要があります。 - もし子テキストに親のスタイルを適用したい場合は、プロパティを明示的に渡すか、
StyleSheet.flatten
を使ってスタイルをマージすることを検討してください。 opacity
は親のView
に適用すると、その中のすべての要素に影響します。- 色の透明度(アルファ値)を調整したい場合は、
rgba(R, G, B, A)
形式で色を指定することで、より細かく制御できます。// 親のTextにopacityを設定しても子が影響を受けない場合がある <Text style={{ opacity: 0.5 }}> これは親テキストです。<Text style={{ color: 'blue' }}>これは子テキストです。</Text> </Text> // 推奨される対応 (Viewで囲むか、子に直接スタイルを適用) <View style={{ opacity: 0.5 }}> <Text>これは半透明の親テキストです。</Text> <Text style={{ color: 'rgba(0, 0, 255, 0.5)' }}>これは半透明の子テキストです。</Text> </View>
- React Nativeの
- シンプルな例で再現性を確認する: 複雑なコンポーネントの中で問題が発生している場合、最小限のコードで問題が再現するかどうかを試すことで、原因を特定しやすくなります。
- 公式ドキュメントを確認する: React Nativeの公式ドキュメントは常に最新の情報を提供しており、特定のコンポーネントの挙動やプロパティに関する詳細な説明があります。
- アプリを再ビルドする:
npx react-native run-ios
やnpx react-native run-android
を実行して、アプリを完全に再ビルドします。 node_modules
を再インストールする:rm -rf node_modules && npm install
(またはyarn install
) を実行して、依存関係を再構築します。- 開発サーバーのキャッシュをクリアする:
npm start -- --reset-cache
またはyarn start -- --reset-cache
を実行して、Metro Bundlerのキャッシュをクリアすると、表示の問題が解決することがあります。
TextInput
コンポーネントを「無効化」する場合: テキスト入力フィールドを無効にするには、editable={false}
プロパティを使用します。Text
コンポーネントを視覚的に「無効」に見せる場合:Text
コンポーネント自体は操作対象ではないため、スタイルを適用して「無効な状態」であることを示唆します。
TextInputコンポーネントの「無効化」例
TextInput
はユーザーがテキストを入力できるコンポーネントです。これを無効化するにはeditable={false}
を使用します。
目的:
- 無効な状態であることを視覚的に示す(例: 色をグレーにする)。
- ユーザーがテキストを編集できないようにする。
コード例:
import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet, Button } from 'react-native';
const TextInputDisabledExample = () => {
const [isInputDisabled, setIsInputDisabled] = useState(true); // 初期値は無効
const [inputValue, setInputValue] = useState("これは編集できません。");
return (
<View style={styles.container}>
<Text style={styles.title}>TextInputの無効化例</Text>
{/* 編集不可のTextInput */}
<Text style={styles.label}>編集不可のテキスト入力:</Text>
<TextInput
style={[styles.input, isInputDisabled && styles.disabledInput]}
value={inputValue} // `editable={false}`の場合は`value`または`defaultValue`を使用
editable={false} // ★ここがポイント:編集を無効化
/>
{/* 編集可のTextInput (比較用) */}
<Text style={styles.label}>編集可能なテキスト入力:</Text>
<TextInput
style={styles.input}
placeholder="ここに入力してください"
onChangeText={text => console.log(text)}
/>
{/* `isInputDisabled`の状態を切り替えるボタン */}
<Button
title={isInputDisabled ? "入力フィールドを有効にする" : "入力フィールドを無効にする"}
onPress={() => setIsInputDisabled(!isInputDisabled)}
/>
{/* 動的に無効化状態を切り替えるTextInput */}
<Text style={styles.label}>動的に無効化を切り替える入力:</Text>
<TextInput
style={[styles.input, isInputDisabled && styles.disabledInput]}
value={isInputDisabled ? "現在無効です" : "現在有効です。入力可能。"}
editable={!isInputDisabled} // ★ここがポイント:`isInputDisabled`の状態に応じて切り替え
onChangeText={text => setInputValue(text)} // 有効な場合に値を更新
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: '#F5FCFF',
},
title: {
fontSize: 22,
fontWeight: 'bold',
marginBottom: 30,
},
label: {
fontSize: 16,
marginBottom: 5,
marginTop: 20,
alignSelf: 'flex-start', // 左寄せ
width: '80%',
},
input: {
height: 40,
borderColor: 'gray',
borderWidth: 1,
width: '80%',
paddingHorizontal: 10,
marginBottom: 10,
backgroundColor: 'white',
},
disabledInput: {
backgroundColor: '#e0e0e0', // 無効な状態の背景色
color: '#888', // 無効な状態の文字色
},
});
export default TextInputDisabledExample;
解説:
[styles.input, isInputDisabled && styles.disabledInput]
のように配列を使ってスタイルを適用することで、isInputDisabled
がtrue
の場合にのみdisabledInput
スタイルが追加され、背景色や文字色が変わるようにしています。isInputDisabled
というState変数を使って、入力フィールドの有効/無効を動的に切り替えています。editable={false}
をTextInput
に設定することで、ユーザーはテキストを編集できなくなります。
Text
コンポーネントは入力機能がないため、disabled
という概念は存在しません。代わりに、スタイル(色、透明度など)を使って「無効な状態」を表現します。これは、関連するUI要素(例えば、ボタン)が無効な場合に、その説明テキストも同様に無効であるように見せるためによく使われます。
目的:
- 関連するボタンが無効な場合に、そのテキストも無効に見せる。
Text
の文字色を薄くしたり、グレーにしたりして、視覚的に無効な状態を表現する。
コード例:
import React, { useState } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Button } from 'react-native';
const TextVisualDisabledExample = () => {
const [isButtonDisabled, setIsButtonDisabled] = useState(true); // 初期値はボタン無効
return (
<View style={styles.container}>
<Text style={styles.title}>Textコンポーネントの視覚的無効化例</Text>
{/* 無効なボタンとそのテキスト */}
<TouchableOpacity
onPress={() => alert('ボタンが押されました!')}
disabled={isButtonDisabled} // ボタン自体を無効化
style={[styles.button, isButtonDisabled && styles.disabledButton]}
>
<Text
style={[
styles.buttonText,
isButtonDisabled && styles.disabledText
]}
>
{isButtonDisabled ? "無効な操作ボタン" : "有効な操作ボタン"}
</Text>
</TouchableOpacity>
{/* 独立した無効なテキスト */}
<Text
style={[
styles.descriptionText,
isButtonDisabled && styles.disabledText
]}
>
{isButtonDisabled
? "上のボタンは現在無効です。下のテキストも無効に見せています。"
: "上のボタンは現在有効です。"}
</Text>
{/* `isButtonDisabled`の状態を切り替えるボタン */}
<Button
title={isButtonDisabled ? "ボタンを有効にする" : "ボタンを無効にする"}
onPress={() => setIsButtonDisabled(!isButtonDisabled)}
/>
{/* 常に無効に見えるテキスト */}
<Text style={[styles.descriptionText, styles.alwaysDisabledText]}>
これは常に無効に見えるテキストです。
</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: '#F5FCFF',
},
title: {
fontSize: 22,
fontWeight: 'bold',
marginBottom: 30,
},
button: {
backgroundColor: 'blue',
padding: 15,
borderRadius: 8,
marginBottom: 20,
width: '80%',
alignItems: 'center',
},
disabledButton: {
backgroundColor: '#a0a0a0', // 無効なボタンの背景色
},
buttonText: {
color: 'white',
fontSize: 18,
fontWeight: 'bold',
},
descriptionText: {
fontSize: 16,
textAlign: 'center',
marginHorizontal: 20,
marginBottom: 30,
color: 'black', // デフォルト色
},
disabledText: {
color: '#888', // 無効なテキストの文字色
opacity: 0.6, // 無効なテキストの透明度
},
alwaysDisabledText: {
color: '#ccc',
opacity: 0.4,
fontStyle: 'italic',
},
});
export default TextVisualDisabledExample;
解説:
TouchableOpacity
には実際にdisabled
プロパティがあり、これをtrue
にすると、ボタンが押せなくなり、デフォルトで見た目も少し変化します。これに合わせて、内部のText
もスタイルで無効に見せることで、一貫性のあるUXを提供します。styles.disabledText
では、color: '#888'
(灰色)とopacity: 0.6
(半透明)を設定し、テキストが無効であることを視覚的に示しています。Text
のstyle
プロパティに、isButtonDisabled && styles.disabledText
のように条件付きでスタイルを適用しています。Text
コンポーネント自体にはdisabled
プロパティがないため、isButtonDisabled
というState変数を使って、関連するUIの状態を管理します。
TextInput
コンポーネントを「無効化」する際の代替・補完的な方法:editable={false}
が基本的な方法ですが、これだけでは不十分な場合や、より高度な制御が必要な場合に考えられる代替策です。Text
コンポーネントを視覚的に「無効」に見せる際の代替・補完的な方法: スタイル(色、透明度)の調整が一般的ですが、アクセシビリティの考慮や、よりインタラクティブな要素の一部としての扱い方など、代替的なアプローチです。
TextInputコンポーネントを「無効化」する際の代替・補完的な方法
TextInput
のeditable={false}
は最も直接的な無効化方法ですが、それだけでは足りない場合や、他の制御方法を検討したい場合があります。
-
オーバーレイによるブロック:
TextInput
の上に透明なView
を重ねて、タッチイベントをブロックする方法です。これはあまり一般的ではありませんが、特定のデザイン要件や複雑なインタラクションが必要な場合に検討されることがあります。用途:
TextInput
の上に別の情報表示やアイコンを重ねつつ、同時にその下にあるTextInput
への操作をブロックしたい場合など。import React from 'react'; import { View, TextInput, Text, StyleSheet } from 'react-native'; function App() { return ( <View style={styles.container}> <Text style={styles.label}>オーバーレイでブロック:</Text> <View style={styles.inputWrapper}> <TextInput style={styles.input} value="このテキストは入力できません。(オーバーレイ)" editable={true} // 見た目は編集可能だが、オーバーレイでブロック /> <View style={styles.overlay} /> {/* ★透明なオーバーレイ */} </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, label: { fontSize: 16, marginBottom: 5, marginTop: 20, }, inputWrapper: { position: 'relative', width: '80%', }, input: { height: 40, borderColor: 'gray', borderWidth: 1, paddingHorizontal: 10, backgroundColor: 'white', }, overlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'transparent', // 透明だがタッチイベントはブロック zIndex: 1, // TextInputの上に重ねる }, }); export default App;
注意点:
- この方法は見た目上は
TextInput
が有効なように見えるため、ユーザーが混乱する可能性があります。スタイルもeditable={false}
時と合わせる必要があります。 - アクセシビリティの観点からは推奨されません。スクリーンリーダーは
TextInput
が有効であると認識する可能性があります。
- この方法は見た目上は
-
TextInputではなくTextコンポーネントを使用する: もし、ユーザーに値を入力させる必要がなく、単に表示だけさせたいのであれば、最初から
TextInput
ではなくText
コンポーネントを使用するのが最もシンプルで適切な方法です。これは「無効化」というより「非入力フィールド化」のアプローチです。用途: ユーザー入力が不要な、固定されたテキスト表示。
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; function App() { const displayValue = "これは入力フィールドではありません。単なる表示です。"; return ( <View style={styles.container}> <Text style={styles.label}>単なる表示テキスト:</Text> <Text style={styles.displayText}> {displayValue} </Text> <Text style={styles.label}>(これはTextInputではありません)</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, label: { fontSize: 16, marginBottom: 5, marginTop: 20, }, displayText: { fontSize: 18, color: '#555', padding: 10, borderColor: '#ddd', borderWidth: 1, width: '80%', backgroundColor: '#f0f0f0', }, }); export default App;
注意点:
- これは入力フィールドではないため、入力に関する機能は一切利用できません。
-
pointerEvents="none" の使用:
View
コンポーネントにpointerEvents="none"
を設定すると、そのViewとその子要素に対するすべてのタッチイベント(タップ、スワイプなど)が無効になります。TextInput
をView
で囲み、このプロパティを使用することで、editable={false}
に加えて、完全にタッチ操作をブロックできます。用途:
TextInput
を完全に操作不可にしたい場合。特に、editable={false}
でも一部のジェスチャーやキーボード表示が残るプラットフォームでの対策として有効です。import React from 'react'; import { View, TextInput, Text, StyleSheet } from 'react-native'; function App() { return ( <View style={styles.container}> <Text style={styles.label}>`pointerEvents="none"` で無効化:</Text> <View pointerEvents="none"> {/* ★ここがポイント */} <TextInput style={styles.input} value="このテキストは完全に操作できません。" /> </View> <Text style={styles.label}>通常のTextInput:</Text> <TextInput style={styles.input} placeholder="これは入力できます。" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, label: { fontSize: 16, marginBottom: 5, marginTop: 20, }, input: { height: 40, borderColor: 'gray', borderWidth: 1, width: '80%', paddingHorizontal: 10, backgroundColor: 'white', }, }); export default App;
注意点:
pointerEvents="none"
は、子要素のタップイベントなどもすべてブロックします。- アクセシビリティ(スクリーンリーダーなど)の観点からは、
editable={false}
の方がより明確な情報を提供できます。
Text
コンポーネントを無効に見せる最も一般的な方法はスタイル調整ですが、それ以外のアクセシビリティやインタラクティブな要素との連携も考慮できます。
-
特定のコンポーネント(例: Pressable)の内部でdisabled状態をハンドリング:
Pressable
コンポーネントは、ボタンなどのインタラクティブな要素を柔軟に作成するためのコンポーネントです。Pressable
にはdisabled
プロパティがあり、これを使用すると内部のコンテンツ(Text
を含む)の見た目を簡単に調整できます。用途: カスタムボタンやインタラクティブな要素に、統一された無効状態のロジックを適用したい場合。
import React, { useState } from 'react'; import { View, Text, Pressable, StyleSheet } from 'react-native'; function App() { const [isPressableDisabled, setIsPressableDisabled] = useState(true); return ( <View style={styles.container}> <Text style={styles.label}>Pressable内で無効状態をハンドリング:</Text> <Pressable onPress={() => alert('Pressableが押されました!')} disabled={isPressableDisabled} // Pressableを無効化 style={({ pressed }) => [ styles.pressableContainer, isPressableDisabled && styles.disabledPressableContainer, pressed && !isPressableDisabled && styles.pressedState, // 有効な時のみ pressed スタイル ]} > <Text style={({ pressed }) => [ styles.pressableText, isPressableDisabled && styles.disabledPressableText, pressed && !isPressableDisabled && styles.pressedText, ]} > {isPressableDisabled ? "無効なPressable" : "有効なPressable"} </Text> </Pressable> <Button title={isPressableDisabled ? "Pressableを有効にする" : "Pressableを無効にする"} onPress={() => setIsPressableDisabled(!isPressableDisabled)} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, label: { fontSize: 16, marginBottom: 10, marginTop: 20, }, pressableContainer: { padding: 15, borderRadius: 8, backgroundColor: 'purple', marginBottom: 20, }, disabledPressableContainer: { backgroundColor: '#a0a0a0', opacity: 0.7, }, pressedState: { backgroundColor: '#6a0dad', // 押された時の色 }, pressableText: { color: 'white', fontSize: 18, fontWeight: 'bold', }, disabledPressableText: { color: '#ccc', }, pressedText: { // 押された時のテキストスタイル(必要であれば) }, }); export default App;
解説:
Pressable
のstyle
と子要素のstyle
に、関数形式のスタイルを渡すことで、pressed
(押されているか)やdisabled
(無効か)といった状態に基づいてスタイルを動的に適用できます。- これにより、単に
Text
のスタイルを切り替えるだけでなく、親のインタラクティブな要素の無効状態と一貫した見た目と挙動を実現できます。
-
accessibilityState={{ disabled: true }} の使用(アクセシビリティの観点): これは視覚的な変更はもたらしませんが、スクリーンリーダーなどの支援技術を使用するユーザーに対して、その要素が「無効である」という情報を提供できます。
Text
単体で使うことは稀ですが、Text
がPressable
やTouchableOpacity
などのインタラクティブな要素の子要素として使われている場合に、親要素の無効状態と連動させて設定すると効果的です。用途: アクセシビリティを向上させたい場合。特に、テキストが何らかのインタラクションに関連している場合。
import React, { useState } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, Button } from 'react-native'; function App() { const [isActionDisabled, setIsActionDisabled] = useState(true); return ( <View style={styles.container}> <Text style={styles.label}>アクセシビリティの無効状態:</Text> <TouchableOpacity onPress={() => alert('アクション実行!')} disabled={isActionDisabled} // TouchableOpacityを無効化 style={[styles.button, isActionDisabled && styles.disabledButton]} > <Text style={[styles.buttonText, isActionDisabled && styles.visuallyDisabledText]} // ★ここがポイント:親要素の無効状態に合わせてアクセシビリティ状態も設定 accessibilityState={{ disabled: isActionDisabled }} > {isActionDisabled ? "アクション実行不可" : "アクション実行可能"} </Text> </TouchableOpacity> <Button title={isActionDisabled ? "アクションを有効にする" : "アクションを無効にする"} onPress={() => setIsActionDisabled(!isActionDisabled)} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, label: { fontSize: 16, marginBottom: 10, marginTop: 20, }, button: { padding: 15, borderRadius: 8, backgroundColor: 'blue', marginBottom: 20, }, disabledButton: { backgroundColor: 'gray', opacity: 0.7, }, buttonText: { color: 'white', fontSize: 18, fontWeight: 'bold', }, visuallyDisabledText: { color: '#ccc', // 視覚的にも無効に見せる }, }); export default App;
注意点:
- このプロパティは視覚的な効果を持たないため、必ず
style
による視覚的な表現と組み合わせて使用すべきです。 - スクリーンリーダーの挙動はOSやバージョンによって異なる場合があります。
- このプロパティは視覚的な効果を持たないため、必ず
React Nativeで「Text#disabled」を扱う場合、重要なのは「どのコンポーネントが対象か」と「どのような目的(入力制御、視覚的表現、アクセシビリティ)か」を明確にすることです。
- 表示テキストの無効化: スタイル(
color
,opacity
)による視覚的表現が基本。アクセシビリティのためにaccessibilityState
を使用したり、Pressable
のようなインタラクティブなコンポーネント内で状態をハンドリングしたりする。 - 入力フィールドの無効化:
TextInput
のeditable={false}
が基本。必要に応じてpointerEvents="none"
やText
コンポーネントへの置き換えを検討。