xcarpentier / rn-tourguide

🚩Make an interactive step by step tour guide for your react-native app (a rewrite of react-native-copilot)
https://xcarpentier.github.io/rn-tourguide/
Other
711 stars 212 forks source link

Usage inside scrollview #40

Open mwerder opened 3 years ago

mwerder commented 3 years ago

Does anyone have experience with how to use it inside a scrollview?

It highlights the components outside the view. So even if I scroll down it is not visible.

I also tried a walkaround by using the handleOnStepChange() callback to stop() the animation after the first step then scroll down my view and start(step) again at the desired step. But it's very ugly and also doesn't work, the animation does not start again.

huuluan97 commented 3 years ago

Hello @xcarpentier, Can you help me to add before and after events when calling the next step. Thank you.

ZhiXiao-Lin commented 3 years ago

It's important

domlimm commented 2 years ago

Having the same issue...

xcarpentier commented 2 years ago

Hi Sorry, it's not yet handled and I'm really busy. Is that possible for someone to make some technical study first to know how to do it? thx

henrinacio commented 2 years ago

Perhaps the start function should have an optional scrollView prop just like the start from react-native-copilot: start(fromStep?: string, scrollView?: React.RefObject)

I'm studying both libs and only made it work inside ScrollView with react-native-copilot. That's how it worked:

import React from 'react'
import { ScrollView } from 'react-native'
import { copilot, walkthroughable, CopilotStep } from 'react-native-copilot'

const TourView = walkthroughable(ScrollView)

const ParentComponent = ({ start, copilotEvents }) => {
  const refScrollView = React.useRef()

  React.useEffect(() => {
    const tourTimeout = setTimeout(() => {
      start(false, refScrollView.current)
    }, 300)

    copilotEvents.on('stepChange', (step) => console.log(`Step is ${step.name}`))
    copilotEvents.on('stop', () => console.log('Tour ended'))

    return () => {
      clearTimeout(tourTimeout)
      copilotEvents.off('stepChange')
      copilotEvents.off('stop')
    }
  }, [])

  return (
    <ScrollView ref={refScrollView}>
      <CopilotStep order={1} name='step1'>
        <TourView>
          <CustomComponent1 />
        </TourView>
      </CopilotStep>
      <CopilotStep order={2} name='step1'>
        <TourView>
          <CustomComponent2 />
        </TourView>
      </CopilotStep>
    </ScrollView>
  )
}

export default copilot()(ParentComponent)
krunal-lw commented 1 year ago

Hello @xcarpentier

Please review pull request for this issue , https://github.com/xcarpentier/rn-tourguide/pull/112

christianariola commented 1 year ago

Hello @krunal-lw can you provide an example on how to use the changes you made for the scrollview?

Haseeba393 commented 1 year ago

Really thanks krunal for making this PR, this helps me to implement the scrolling and also for bottomsheet. Thanks again

Haseeba393 commented 1 year ago

the above PR must be merge as it has the scrolling handled

christianariola commented 1 year ago

Hello @Haseeba393

How did you implement it?

Haseeba393 commented 1 year ago

Brother I checked @krunal-lw PR and did all the changes he did in his PR and it's working absolutely fine. It's all about to pass the ref of your desired component down to rn-tour package and thruh ref you can do whatever you want to your component. @krunal-lw is doing same thing for scroll view

christianariola commented 1 year ago

Thank you. I'll check it out.

Haseeba393 commented 1 year ago

Your welcome, if you will need any help in implementation, then please let me know. Thanks

krunal-lw commented 1 year ago

Your welcome @Haseeba393

@christianariola - Let me know if still facing issue to implement with scroll

christianariola commented 1 year ago

Thank you @krunal-lw, I decided to switch to copilot as I needed this feature to be done asap. may package is in js not ts that's why I can't implement it base on your PR

Egehanozsoy commented 1 year ago

Can we have have this feature please, thanks

krunal-lw commented 1 year ago

@Egehanozsoy Hey buddy, you can checkout this version https://github.com/xcarpentier/rn-tourguide/pull/112,

Hope this will help to you. thanks

antoniel commented 1 year ago

Yo @krunal-lw,

Thank you for implementing the solution for this issue. I was testing it and I noticed that if the first step of the tour requires scrolling, it won't work properly because of how the ref is set in the state along with the start method. In this situation, the validation in the if (scrollRef && step) in the setCurrentStep function will fail, so will not trigger the scroll. My solution was to create a new parameter localScrollRef?: React.RefObject<any>, so in the first trigger of start we can pass ahead the _scrollRef?: React.RefObject<any>:

const setCurrentStep = async (key: string, step?: IStep, localScrollRef?: React.RefObject<any>) => {
    const actualScrollRef = scrollRef ?? localScrollRef

In the setCurrentStep we get a new variable actualScrollRef (sorry by bad naming hehehe),

  const setCurrentStep = async (key: string, step?: IStep, localScrollRef?: React.RefObject<any>) => {
    const actualScrollRef = scrollRef ?? localScrollRef
    return await new Promise<void>(async (resolve) => {
      if (actualScrollRef && step) {
       // ...

Feel free to implement this on your PR or follow a different path to fix this behavior o/

krunal-lw commented 1 year ago

@antoniel Thanks for heads up, I will implement your solution in my PR ,

Thanks once again, Appreciated

JCYDigitalinnov commented 1 year ago

@krunal-lw

I love your PR, but I encounter this problem TypeError: Cannot read property '_nativeTag' of null

This happens when I reset the navigation, and start the tour again the error occurs.

The problem is it happens sometimes. The solution I got is to restart the app to work it again

Drzaln commented 10 months ago

Hi guys, how I can use PR from @krunal-lw ? I try to patch the package but it didn't working

kjethi commented 10 months ago

@Drzaln Hey buddy, you can checkout this version https://github.com/xcarpentier/rn-tourguide/pull/112,

Hope this will help to you. thanks

Drzaln commented 9 months ago

Hi @kjethi I can't install with that version I already run yarn add rn-tourguide@xcarpentier/rn-tourguide#pull/112

but it doesn't work

krunal-lw commented 9 months ago

Hey @Drzaln , Can you please try yarn add krunal-lw/rn-tourguide I think this will work

Or add below line in your package.json file and run yarn install

"rn-tourguide": "krunal-lw/rn-tourguide",

Drzaln commented 9 months ago

Hi @krunal-lw Yep it works, I'm using this "rn-tourguide": "https://github.com/krunal-lw/rn-tourguide.git",

and also I downgrade the yarn to v1, previously using yarn v3

nihatt commented 7 months ago

hi @krunal-lw thanks for the major help it works perfectly, but i have another problem First i use it in the scrollview and it works perfectly but at step 3 i want to go outside the scrollview and use it in the sticky header which is a normal view above the scroll view and it gives me an error called

` view <RCTShadowView: 0x7fac67d90610; viewName: RCTView; reactTag: 105; frame: {{0, 0}, {234, 24}}> (tag #105) is not a descendant of <RCTShadowView: 0x7fac67b68550; viewName: RCTScrollView; reactTag: 669; frame: {{0, 108}, {390, 657}}> (tag #669)

RCTMeasureLayout RCTUIManager.m:1392 -[RCTUIManager measureLayout:relativeTo:errorCallback:callback:] __invoking___ -[NSInvocation invoke] -[NSInvocation invokeWithTarget:] -[RCTModuleMethod invokeWithBridge:module:arguments:] facebook::react::invokeInner(RCTBridge, RCTModuleData, unsigned int, folly::dynamic const&, int, (anonymous namespace)::SchedulingContext) facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int)::$_0::operator()() const invocation function for block in facebook::react::RCTNativeModule::invoke(unsigned int, folly::dynamic&&, int) _dispatch_call_block_and_release _dispatch_client_callout _dispatch_lane_serial_drain _dispatch_lane_invoke _dispatch_workloop_worker_thread _pthread_wqthread start_wqthread

`

but when i do the reverse like view -> scrollview eveything works fine , any solutions for that ?

example

<View >

    <MainHeaderBackground />
    <View style={[styles.header, { marginTop: insets.top }]}>
          <View style={{ width: '60%' }}>
          <TourGuideZone
                zone={4}
                text={mainTourValues[3].appTutorialResource.description}
                borderRadius={16}
              >
            <TouchableOpacity
              style={[styles.profileImage]}
              onPress={() => toggle()}>
              <Text style={styles.dropdownButtonTextStyle}>
                {patientDetail?.data?.fullName ?? ''}
              </Text>
              <IconBottomArrow></IconBottomArrow>
            </TouchableOpacity>
            </TourGuideZone>
          </View>
 <ScrollView
          ref={(r) => { scrollRef.current = r }}
          contentContainerStyle={{ flexGrow: 1 }}
          scrollEventThrottle={16}
          keyboardShouldPersistTaps={'always'}
          showsVerticalScrollIndicator={false}
          refreshControl={
            <RefreshControl
              refreshing={refreshing}
              onRefresh={loadDashboardDetail}
            />
          }
        >
          <View style={styles.container}>
            <View style={styles.section}>
              <TextInput
                style={styles.input}
                value={search}
                placeholder={strings.searchDasboardPlaceHolder}
                onChangeText={text => setSearch(text)}
                keyboardType="default"
                onSubmitEditing={() => {
                  navigation.navigate('SearchHospitalSectionScreen', {
                    searchText: search,
                  });
                  setSearch('');
                }}
              />
            </View>
            <View>
              <TourGuideZone
                zone={1}
                text={mainTourValues[0].appTutorialResource.title}
                borderRadius={16}
              >
                <SwiperFlatList
                  autoplay
                  autoplayDelay={3}
                  autoplayLoop
                  index={0}
                  contentContainerStyle={{ marginHorizontal: 15 }}
                  borderRadius={15}
                  showPagination
                  keyExtractor={(item, index) => index.toString()}
                  data={dashboardData?.sliderList}
                  paginationStyleItemActive={styles.paginationStyleItemActive}
                  paginationStyleItemInactive={styles.paginationStyleItemInactive}
                  paginationActiveColor={'#B1292F'}
                  paginationDefaultColor={'#F4888C'}
                  renderItem={({ item }) => (
                    <Pressable
                      key={item.key}
                      style={styles.child}
                      onPress={async () => {
                        const result = await getSliderDetailById(item.id);
                        navigation.navigate('SliderDetailScreen', {
                          item: result?.data?.sliderResource,
                        });
                      }}>
                      <Image
                        style={styles.imageStyle}
                        resizeMode="contain"
                        source={{
                          uri: item?.sliderResource?.image,
                        }}
                      />
                    </Pressable>
                  )}
                />
              </TourGuideZone>
            </View>

i want it to work that way but i am getting the specified error

navaspavil commented 7 months ago

@nihatt

Did you find any solution for this? I'm also facing the same issue.