rn-tourguide icon indicating copy to clipboard operation
rn-tourguide copied to clipboard

Usage inside scrollview

Open mwerder opened this issue 4 years ago • 30 comments
trafficstars

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.

mwerder avatar Mar 08 '21 08:03 mwerder

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

huuluan97 avatar Mar 08 '21 10:03 huuluan97

It's important

ZhiXiao-Lin avatar Jul 05 '21 13:07 ZhiXiao-Lin

Having the same issue...

domlimm avatar Jul 31 '21 03:07 domlimm

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

xcarpentier avatar Sep 02 '21 12:09 xcarpentier

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:

  • wrap desired components to highlight inside another ScrollView;
  • pass ref from ScrollView to start function;
  • setTimeout to prevent highlighting outside of the component when mount.
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)

henrinacio avatar Apr 12 '22 19:04 henrinacio

Hello @xcarpentier

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

krunal-lw avatar Aug 30 '22 10:08 krunal-lw

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

christianariola avatar Nov 13 '22 12:11 christianariola

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

Haseeba393 avatar Nov 13 '22 19:11 Haseeba393

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

Haseeba393 avatar Nov 13 '22 20:11 Haseeba393

Hello @Haseeba393

How did you implement it?

christianariola avatar Nov 14 '22 05:11 christianariola

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

Haseeba393 avatar Nov 14 '22 07:11 Haseeba393

Thank you. I'll check it out.

christianariola avatar Nov 14 '22 08:11 christianariola

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

Haseeba393 avatar Nov 14 '22 13:11 Haseeba393

Your welcome @Haseeba393

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

krunal-lw avatar Nov 14 '22 15:11 krunal-lw

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

christianariola avatar Nov 15 '22 13:11 christianariola

Can we have have this feature please, thanks

Egehanozsoy avatar Jan 28 '23 00:01 Egehanozsoy

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

Hope this will help to you. thanks

krunal-lw avatar Jan 28 '23 01:01 krunal-lw

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/

antoniel avatar Feb 06 '23 16:02 antoniel

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

Thanks once again, Appreciated

krunal-lw avatar Feb 06 '23 16:02 krunal-lw

@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

JCYDigitalinnov avatar May 10 '23 14:05 JCYDigitalinnov

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

Drzaln avatar Sep 01 '23 13:09 Drzaln

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

Hope this will help to you. thanks

kjethi avatar Sep 03 '23 09:09 kjethi

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

Drzaln avatar Oct 10 '23 09:10 Drzaln

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",

krunal-lw avatar Oct 10 '23 10:10 krunal-lw

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

Drzaln avatar Oct 10 '23 10:10 Drzaln

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

nihatt avatar Nov 29 '23 09:11 nihatt

@nihatt

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

navaspavil avatar Dec 21 '23 05:12 navaspavil