Создание прозрачной сенсорной части с помощью React-Native - PullRequest
0 голосов
/ 28 октября 2019

Я хотел бы сделать часть Touchable traslucid, то есть, чтобы иметь возможность видеть фон за ним.

Возможно, взломать MaskedView и снова нарисовать мой фон внутри Touchable в качестве children реквизита MaskedView. Однако это работает только для ограниченного числа сценариев. Вот это работает:

enter image description here

Однако, как только я добавляю некоторые поля, например, вещи выходят из фазы:

enter image description here

Пара разъяснений, на всякий случай:

  • Мое настоящее намерение - использовать градиент, который идет между противоположными углами экрана. В этом случае все не работает даже в простом сценарии, который я представил.
  • Я знаю, почему этот хак не работает, но я не смог придумать что-нибудь лучше

Вот MWE, использующий вид вместо изображения, так что мне не нужно связывать файл png:

import React from 'react';
import {
    View,
    TouchableOpacity,
} from 'react-native';
import MaskedView from '@react-native-community/masked-view';
import LinearGradient from 'react-native-linear-gradient';

export default function () {
    return (
        <LinearGradient start={{x: 0, y: 0}} end={{x: 1, y: 0}}
                        colors={['red', 'blue', 'green']}
                        style={
                            {flex: 1,
                            alignItems: 'stretch',
                            justifyContent: 'center'}
                        }>
            <TouchableOpacity>
                <View style={
                    {height: 100,
                    alignItems: 'stretch',
                    justifyContent: 'center',
                    backgroundColor: 'white',
                    borderRadius: 30,
                    //marginLeft: 50, // -> if you uncomment this line, the translucid effect is ruined
                    }
                }>
                    <MaskedView
                        style={{height: '100%', backgroundColor: 'yellow',
                            alignItems: 'stretch', justifyContent: 'center',
                        }}
                        maskElement={
                            <View style={{flex: 1, backgroundColor: 'transparent',
                                alignItems: 'center', justifyContent: 'center',
                            }}>
                                <View style={{width: 300, height: '100%', backgroundColor: 'black'}}/>
                            </View>
                        }
                    >
                        <LinearGradient start={{x: 0, y: 0}} end={{x: 1, y: 0}}
                                        colors={['red', 'blue', 'green']}
                                        style={{height: '100%'}}
                        />
                     </MaskedView>
                </View>
            </TouchableOpacity>
        </LinearGradient>
    );
}

1 Ответ

1 голос
/ 30 октября 2019

Вот примерная закуска, иллюстрирующая мой комментарий: https://snack.expo.io/SkCNR7Iqr

Идея состоит в том, что вместо того, чтобы рендерить, а затем скрывать контент, просто ничего не рендерите в первую очередь. Это сделает белые концы в пределах кнопки. Оболочка использует overflow: 'hidden', чтобы гарантировать, что эффект Touchable будет появляться только в пределах ограниченного borderRadius (более заметно при TouchableHighlight), и он гарантирует, что белый цвет и любой другой контент в нем останутся в пределах ограниченного borderRadius.

import * as React from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native'
import { LinearGradient } from 'expo-linear-gradient'

export default class App extends React.Component {
  render() {
    return (
      <LinearGradient
        start={{ x: 0, y: 0 }}
        end={{ x: 1, y: 0 }}
        colors={['red', 'blue', 'green']}
        style={styles.gradient}>
        <View style={styles.wrapper}>
          <TouchableOpacity style={styles.touch}>
            <View style={styles.end} />
            <View style={styles.content} />
            <View style={styles.end} />
          </TouchableOpacity>
        </View>
      </LinearGradient>
    );
  }
}

const styles = StyleSheet.create({
  gradient: {
    flex: 1,
    justifyContent: 'center'
  },
  wrapper: {
    height: 100,
    borderRadius: 30,
    overflow: 'hidden',
    marginLeft: 50,
    flexDirection: 'row',
  },
  touch: {
    flexDirection: 'row',
    flex: 1,
  },
  end: {
    width: 50,
    backgroundColor: 'white',
    height: '100%',
  },
  content: {
    flex: 1,
  }
});
...