Jumpman987
Jumpman987

Reputation: 317

List item won't change height in response to large text from accessibility being turned on

I'm currently working in React Native and I'm trying to make my list item components accessible to people with poor vision and might need bigger text, because of this I've ran into some issues with the text clipping or not showing entirely. What I'm trying to do is pretty straightforward, if the user turns on large text in accessibility then my event listener will pick up on it and using that information will determine the height of my list component when rendering. Unfortunately, it seems as though my app can never detect when the accessibility is on because in the console I get a lot of false and default height of 50 (when no large text is active). I'll attach some screenshots and then some code.

This is what my list view looks with large text, as you can see the text has gotten bigger but my individual list items aren't sizing correctly to fit the bigger text (should be 150, but still at 50).

List items don't size correctly

This is what I get in the console..

console output

Now here are some bits of code. Note, I omitted some code for brevity.

class NodeListItem extends PureComponent {

    constructor() {
        super();

        this.state = {
            largeTextEnabled: undefined,
        };
        this.itemPressed = this.itemPressed.bind(this);
    }

    componentDidMount() {
        AccessibilityInfo.addEventListener(
          'change',
          this._handleAccessibilityToggled
        );
        AccessibilityInfo.fetch().done((isEnabled) => {
            console.log(`Is enabled didMount: ${isEnabled}`);
            this.setState({
                largeTextEnabled: isEnabled,
            });
        });
    }

    componentWillUnmount() {
        AccessibilityInfo.removeEventListener(
          'change',
          this._handleAccessibilityToggled
        );
    }

    _handleAccessibilityToggled = (isEnabled) => {
        this.setState({
            largeTextEnabled: isEnabled,
        });
    };

    render() {
        const { displayName } = this.props.item;
        const adjustForAccessibility = this.state.largeTextEnabled ? 150 : 50
        console.log(`Here is height: ${adjustForAccessibility} and it is: ${this.state.largeTextEnabled}`);
        console.log(`Height ${this.state.largeTextEnabled ? 150 : 50}`);
        return (
            <TouchableOpacity style={{ flex: 1, height: this.state.largeTextEnabled ? 150 : 50 }} onPress={this.itemPressed}>
                <View style={styles.viewContainer}>
                    <Text style={CommonStyles.textDefaultBlackMedium} textAlign={'left'} allowFontScaling={true} numberOfLines={3} >{displayName}</Text>
                    {this.renderArrow()}
                </View>
            </TouchableOpacity>
        );
    }
}

I took inspiration from these 2 links, first and second. Essentially the idea is my app listens for change in accessibility and then updates the state with a boolean, then when rendering my component reads the value and adjusts height accordingly. Any idea why my list item components are not updating their size from 50 to 150 after turning accessibility on? I only ever see undefined or false in the console. Any help would be welcome.

Upvotes: 0

Views: 209

Answers (1)

Tom Rowe
Tom Rowe

Reputation: 479

EDIT: Resolved in the comments, issue was that the setting being altered was not part of the AccessibilityInfo API.

After a quick search I came across this issue which looks like the solution you are after:

https://github.com/facebook/react-native/issues/14725

No need to jump too deep into native code, you can almost always be certain someones already written it :P Especially with the recent focus on accessibility.


A Toggle function, when used with state should always reference the previous state and simple invert the boolean.

I'm not sure where your accessibility button is, but essentially your toggle function should look more like this:

_handleAccessibilityToggled = () => {
        this.setState(prevState => {
            return {
                largeTextEnabled: !prevState.largeTextEnabled,
            }            
        });
    };

This way every click will flick the largeTextEnabled to the opposite state, I would also suggest removing event listeners for the button click and holding the state in a parent of both components if possible.

The main issue is that onChange you aren't actually passing isEnabled to the toggle function hence why it is always undefined or false.

Upvotes: 1

Related Questions