React-native-ui-kitten: Custom top-navigation content

Created on 24 Mar 2020  路  3Comments  路  Source: akveo/react-native-ui-kitten

馃挰 Question

How can I supply custom content for the top-navigation bar? I tried supplying a component to title, as well as supplying children. Neither seem to work.

I want to have a search in there.

Help wanted Duplicate

Most helpful comment

For anyone in my position you can use this:

import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Text, styled } from '@ui-kitten/components';

export class TopNavigationComponent extends React.Component {

  static styledComponentName = 'TopNavigation';

  getAlignmentDependentStyles = (alignment) => {
    if (alignment === 'center') {
      return {
        container: styles.containerCentered,
        titleContainer: styles.titleContainerCentered,
      };
    }

    return {
      rightControlsContainer: styles.rightControlsContainerStart,
    };
  };

  getComponentStyle = (source) => {
    const {
      titleTextAlign,
      titleFontFamily,
      titleFontSize,
      titleLineHeight,
      titleFontWeight,
      titleColor,
      subtitleTextAlign,
      subtitleFontFamily,
      subtitleFontSize,
      subtitleLineHeight,
      subtitleFontWeight,
      subtitleColor,
      ...containerParameters
    } = source;


    return {
      container: containerParameters,
      titleContainer: {},
      title: {
        textAlign: titleTextAlign,
        fontFamily: titleFontFamily,
        fontSize: titleFontSize,
        lineHeight: titleLineHeight,
        fontWeight: titleFontWeight,
        color: titleColor,
      },
      subtitle: {
        textAlign: subtitleTextAlign,
        fontFamily: subtitleFontFamily,
        fontSize: subtitleFontSize,
        color: subtitleColor,
        fontWeight: subtitleFontWeight,
        lineHeight: subtitleLineHeight,
      },
      leftControlContainer: {},
      rightControlsContainer: {},
    };
  };

  renderTextElement = (text, style) => {
    return (
      <Text style={style}>
        {text}
      </Text>
    );
  };

  renderActionElements(source) {
    return React.Children.map(source, (element, index) => {
      return React.cloneElement(element, {
        key: index,
        appearance: this.props.appearance,
      });
    });
  }

  renderComponentChildren = (style) => {
    const {
      title,
      subtitle,
      leftControl,
      rightControls,
      titleStyle,
      subtitleStyle,
    } = this.props;

    const isValidString = value => typeof value === 'string' && value.length > 0

    return [
      isValidString(title) && this.renderTextElement(title, [style.title, styles.title, titleStyle]),
      isValidString(subtitle) && this.renderTextElement(subtitle, [style.subtitle, styles.subtitle, subtitleStyle]),
      leftControl && this.renderActionElements(leftControl),
      rightControls && this.renderActionElements(rightControls),
    ];
  };

  render() {
    const { themedStyle, style, alignment, children, ...restProps } = this.props;

    const {
      container,
      leftControlContainer,
      titleContainer,
      rightControlsContainer,
      ...componentStyles
    } = this.getComponentStyle(themedStyle);

    const alignmentStyles = this.getAlignmentDependentStyles(alignment);

    const [
      titleElement,
      subtitleElement,
      leftControlElement,
      rightControlElements,
    ] = this.renderComponentChildren(componentStyles);

    return (
      <View
        style={[container, styles.container, alignmentStyles.container, style]}
        {...restProps}>
        <View style={[leftControlContainer, styles.leftControlContainer]}>
          {leftControlElement}
        </View>
        <View style={[titleContainer, styles.titleContainer, alignmentStyles.titleContainer]}>
          {titleElement}
          {subtitleElement}
          {children}
        </View>
        <View style={[rightControlsContainer, styles.rightControlsContainer, alignmentStyles.rightControlsContainer]}>
          {rightControlElements}
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  containerCentered: {
    justifyContent: 'space-between',
  },
  titleContainer: {},
  titleContainerCentered: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {},
  subtitle: {},
  leftControlContainer: {
    flexDirection: 'row',
    zIndex: 1,
  },
  rightControlsContainer: {
    flexDirection: 'row',
    zIndex: 1,
  },
  rightControlsContainerStart: {
    flex: 1,
    justifyContent: 'flex-end',
  },
});

export const TopNavigation = styled(TopNavigationComponent);

It's a copy from the repo, but I just added "children" to it. So, leave out title/subtitle and make your own children. Alignment etc is still the same.

Example use:

<TopNavigation
  leftControl={BackAction()}
  alignment='center'
>
  <Text>Hello world</Text>
</TopNavigation>

All 3 comments

No way in v4, meaning you need to build your own. Requested here #863, here #810 and here #777 (please do some search before posting, that would be great :) )

Resolved in v5, which is currently in review #914
Closing due to duplication.

@artyorsh I did a search but found no results. Blame github search. :) Anyway thanks for the answer!

For anyone in my position you can use this:

import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Text, styled } from '@ui-kitten/components';

export class TopNavigationComponent extends React.Component {

  static styledComponentName = 'TopNavigation';

  getAlignmentDependentStyles = (alignment) => {
    if (alignment === 'center') {
      return {
        container: styles.containerCentered,
        titleContainer: styles.titleContainerCentered,
      };
    }

    return {
      rightControlsContainer: styles.rightControlsContainerStart,
    };
  };

  getComponentStyle = (source) => {
    const {
      titleTextAlign,
      titleFontFamily,
      titleFontSize,
      titleLineHeight,
      titleFontWeight,
      titleColor,
      subtitleTextAlign,
      subtitleFontFamily,
      subtitleFontSize,
      subtitleLineHeight,
      subtitleFontWeight,
      subtitleColor,
      ...containerParameters
    } = source;


    return {
      container: containerParameters,
      titleContainer: {},
      title: {
        textAlign: titleTextAlign,
        fontFamily: titleFontFamily,
        fontSize: titleFontSize,
        lineHeight: titleLineHeight,
        fontWeight: titleFontWeight,
        color: titleColor,
      },
      subtitle: {
        textAlign: subtitleTextAlign,
        fontFamily: subtitleFontFamily,
        fontSize: subtitleFontSize,
        color: subtitleColor,
        fontWeight: subtitleFontWeight,
        lineHeight: subtitleLineHeight,
      },
      leftControlContainer: {},
      rightControlsContainer: {},
    };
  };

  renderTextElement = (text, style) => {
    return (
      <Text style={style}>
        {text}
      </Text>
    );
  };

  renderActionElements(source) {
    return React.Children.map(source, (element, index) => {
      return React.cloneElement(element, {
        key: index,
        appearance: this.props.appearance,
      });
    });
  }

  renderComponentChildren = (style) => {
    const {
      title,
      subtitle,
      leftControl,
      rightControls,
      titleStyle,
      subtitleStyle,
    } = this.props;

    const isValidString = value => typeof value === 'string' && value.length > 0

    return [
      isValidString(title) && this.renderTextElement(title, [style.title, styles.title, titleStyle]),
      isValidString(subtitle) && this.renderTextElement(subtitle, [style.subtitle, styles.subtitle, subtitleStyle]),
      leftControl && this.renderActionElements(leftControl),
      rightControls && this.renderActionElements(rightControls),
    ];
  };

  render() {
    const { themedStyle, style, alignment, children, ...restProps } = this.props;

    const {
      container,
      leftControlContainer,
      titleContainer,
      rightControlsContainer,
      ...componentStyles
    } = this.getComponentStyle(themedStyle);

    const alignmentStyles = this.getAlignmentDependentStyles(alignment);

    const [
      titleElement,
      subtitleElement,
      leftControlElement,
      rightControlElements,
    ] = this.renderComponentChildren(componentStyles);

    return (
      <View
        style={[container, styles.container, alignmentStyles.container, style]}
        {...restProps}>
        <View style={[leftControlContainer, styles.leftControlContainer]}>
          {leftControlElement}
        </View>
        <View style={[titleContainer, styles.titleContainer, alignmentStyles.titleContainer]}>
          {titleElement}
          {subtitleElement}
          {children}
        </View>
        <View style={[rightControlsContainer, styles.rightControlsContainer, alignmentStyles.rightControlsContainer]}>
          {rightControlElements}
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  containerCentered: {
    justifyContent: 'space-between',
  },
  titleContainer: {},
  titleContainerCentered: {
    ...StyleSheet.absoluteFillObject,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {},
  subtitle: {},
  leftControlContainer: {
    flexDirection: 'row',
    zIndex: 1,
  },
  rightControlsContainer: {
    flexDirection: 'row',
    zIndex: 1,
  },
  rightControlsContainerStart: {
    flex: 1,
    justifyContent: 'flex-end',
  },
});

export const TopNavigation = styled(TopNavigationComponent);

It's a copy from the repo, but I just added "children" to it. So, leave out title/subtitle and make your own children. Alignment etc is still the same.

Example use:

<TopNavigation
  leftControl={BackAction()}
  alignment='center'
>
  <Text>Hello world</Text>
</TopNavigation>
Was this page helpful?
0 / 5 - 0 ratings

Related issues

simonsankar picture simonsankar  路  3Comments

MScMechatronics picture MScMechatronics  路  3Comments

bkwhite picture bkwhite  路  3Comments

ugurozturk picture ugurozturk  路  4Comments

gimli01 picture gimli01  路  3Comments