প্রতিক্রিয়া নেটিভ এ স্ক্রোলভিউয়ের বর্তমান স্ক্রোল অবস্থান পান


115

<ScrollView>প্রতিক্রিয়া নেটিভের কোনও উপাদানটির বর্তমান পৃষ্ঠা বা বর্তমান স্ক্রোল অবস্থান পাওয়া সম্ভব ?

সুতরাং যেমন কিছু:

<ScrollView
  horizontal={true}
  pagingEnabled={true}
  onScrollAnimationEnd={() => { 
      // get this scrollview's current page or x/y scroll position
  }}>
  this.state.data.map(function(e, i) { 
      <ImageCt key={i}></ImageCt> 
  })
</ScrollView>

প্রাসঙ্গিক: একটি গিটহাব ইস্যুতে এই তথ্য পাওয়ার সুবিধাজনক উপায় যুক্ত করার পরামর্শ দেওয়া হচ্ছে।
মার্ক অ্যামেরি

উত্তর:


207

ব্যবহার করে দেখুন।

<ScrollView onScroll={this.handleScroll} />

এবং তারপর:

handleScroll: function(event: Object) {
 console.log(event.nativeEvent.contentOffset.y);
},

5
স্ক্রোলের মান পরিবর্তিত হলে এটি সর্বদা আগুনে ছোঁবে না। উদাহরণস্বরূপ যদি স্ক্রোলভিউটি পুনরায় আকার দেওয়া হয় যার ফলে এটি এখন একবারে পুরো জিনিসটি স্ক্রিনে প্রদর্শন করতে সক্ষম হয় তবে আপনি সর্বদা কোনও অনস্ক্রোল ইভেন্ট আপনাকে বলে যাবেন বলে মনে হয় না।
টমাস পার্স্লো

19
অথবা event.nativeEvent.contentOffset.xযদি আপনি একটি অনুভূমিক স্ক্রোলভিউ পেয়ে থাকেন;) ধন্যবাদ!
টাইম

2
এটি আমরা অ্যান্ড্রয়েডেও ব্যবহার করতে পারি।
জনক পুষ্পকুমারা

4
হতাশাজনকভাবে, যদি আপনি scrollEventThrottle16 বা তার চেয়ে কম সেট না করেন (প্রতিটি একক ফ্রেমের জন্য একটি ইভেন্ট পেতে), কোনও গ্যারান্টি নেই যে এটি চূড়ান্ত ফ্রেমে অফসেটটির প্রতিবেদন করবে - এর অর্থ নিশ্চিত যে স্ক্রোলিং শেষ হওয়ার পরে আপনার সঠিক অফসেট রয়েছে, আপনার scrollEventThrottle={16}এর পারফরম্যান্স প্রভাব সেট এবং গ্রহণ করতে হবে।
মার্ক

@ ব্র্যাডহিলার: এর সর্বোচ্চ মূল্য জানা সম্ভব event.nativeEvent.contentOffset.y?
ইসহাক

55

দাবি অস্বীকার: এর পরে যা হয় তা মূলত প্রতিক্রিয়া নেটিভ ০.০৫ এ আমার নিজস্ব পরীক্ষার ফলাফল। ScrollViewডকুমেন্টেশন নিম্নোল্লিখিত আবৃত তথ্য অনেক অনুপস্থিত; উদাহরণস্বরূপ onScrollEndDragসম্পূর্ণরূপে নথিভুক্ত। যেহেতু এখানে সমস্ত কিছুই অননুমোদিত আচরণের উপর নির্ভর করে, তাই দুর্ভাগ্যক্রমে আমি কোন প্রতিশ্রুতি দিতে পারি না যে এই তথ্যটি এখন থেকে এক বছর বা এমনকি এক মাস পর্যন্ত সঠিক থাকবে।

এছাড়াও, নীচের সমস্ত কিছু খাঁটি উল্লম্ব স্ক্রোলভিউ ধরে নেয় যার ওয়াই অফসেটে আমরা আগ্রহী; এক্স অফসেটে অনুবাদ করা , যদি প্রয়োজন হয় তবে আশা করি পাঠকের পক্ষে একটি সহজ অনুশীলন।


বিভিন্ন ইভেন্ট হ্যান্ডলাররা একবার ScrollViewনেবেন eventএবং আপনাকে দিয়ে বর্তমান স্ক্রোলের অবস্থানটি পেতে দিন event.nativeEvent.contentOffset.y। এর মধ্যে কয়েকটি হ্যান্ডলারের অ্যান্ড্রয়েড এবং আইওএসের মধ্যে কিছুটা আলাদা আচরণ রয়েছে, যা নীচে বিস্তারিত রয়েছে।

onScroll

অ্যান্ড্রয়েডে

ব্যবহারকারী যখন স্ক্রল করছে তখন প্রতিটি ফ্রেমে আগুন জ্বলছে, যখন স্ক্রোল ভিউটি প্রকাশের পরে চূড়ান্ত হয় যখন ব্যবহারকারীর এটি প্রকাশের পরে, চূড়ান্ত ফ্রেমে স্ক্রোল ভিউটি বিশ্রামে আসে এবং যখনই তার ফ্রেমের ফলস্বরূপ স্ক্রোল ভিউ'র অফসেট পরিবর্তন হয় পরিবর্তন হচ্ছে (যেমন ল্যান্ডস্কেপ থেকে প্রতিকৃতিতে ঘোরার কারণে)।

আইওএস-এ

যখন ব্যবহারকারী টেনে আনছে বা যখন স্ক্রোল ভিউ গ্লাইড হচ্ছে তখন অগ্নিকাণ্ডে scrollEventThrottleফ্রেম দ্বারা নির্ধারিত কিছু ফ্রিকোয়েন্সি এবং একবারে ফ্রেম প্রতি একবার scrollEventThrottle={16}যদি গ্লাইডে পর্যাপ্ত গতি থাকতে পারে ব্যবহারকারী যদি স্ক্রোল ভিউটি ছেড়ে দেয় তবে onScrollগ্লাইডিংয়ের পরে বিশ্রাম নেওয়ার পরে হ্যান্ডলারটিও ফায়ার করবে। উপরন্তু ব্যবহারকারী drags এবং তারপর স্ক্রল দৃশ্য প্রকাশ যখন এটি নিশ্চল হয়, onScrollহয় না আগুন চূড়ান্ত অবস্থান জন্য যদি না নিশ্চিত scrollEventThrottleযেমন নির্ধারণ করা হয়েছে যে onScrollদাবানল স্ক্রলিং প্রতিটি ফ্রেম।

সেটিংয়ের জন্য একটি পারফরম্যান্স ব্যয় রয়েছে scrollEventThrottle={16}যা এটিকে বড় সংখ্যায় সেট করে কমিয়ে আনা যায়। যাইহোক, এর অর্থ এটি onScrollপ্রতিটি ফ্রেমগুলিকে চালিত করবে না।

onMomentumScrollEnd

গ্লাইডিংয়ের পরে যখন স্ক্রোল ভিউ বন্ধ হয়ে যায় তখন আগুন। যদি ব্যবহারকারী স্থির থাকে এমন স্থির হয় যাতে এটি গ্লাইড করে না তবে যদি ব্যবহারকারী স্ক্রোল ভিউটি প্রকাশ করে তবে একেবারেই জ্বলবে না।

onScrollEndDrag

ব্যবহারকারী যখন স্ক্রোল ভিউটি টানা বন্ধ করে দেয় তখন আগুন লাগে - নির্বিশেষে স্ক্রোল ভিউটি স্টেশনটি ছেড়ে যায় বা গ্লাইড শুরু হয় কিনা।


আচরণে এই পার্থক্যগুলি দেওয়া, অফসেটের ট্র্যাক রাখার সর্বোত্তম উপায়টি আপনার সুনির্দিষ্ট পরিস্থিতিতে নির্ভর করে। সবচেয়ে জটিল ক্ষেত্রে (আপনার ScrollViewঘূর্ণনের কারণে ফ্রেমের পরিবর্তনগুলি সামলানো সহ অ্যান্ড্রয়েড এবং আইওএস সমর্থন করা দরকার , এবং আপনি অ্যান্ড্রয়েডে scrollEventThrottle16 এ সেট করা থেকে পারফরম্যান্সের জরিমানা গ্রহণ করতে চান না ) এবং আপনাকে পরিচালনা করতে হবে স্ক্রোল ভিউতে থাকা সামগ্রীতেও পরিবর্তন ঘটে , তবে এটি একটি ডান অভিশাপ।

সবচেয়ে সহজ কেসটি হ'ল যদি আপনার কেবল অ্যান্ড্রয়েড হ্যান্ডেল করা প্রয়োজন; শুধু ব্যবহার করুন onScroll:

<ScrollView
  onScroll={event => { 
    this.yOffset = event.nativeEvent.contentOffset.y
  }}
>

আইওএসকে সমর্থন করার জন্য, আপনি যদিonScroll প্রতিটি ফ্রেম হ্যান্ডলারটি সরিয়ে ফেলাতে খুশি হন এবং এর কার্য সম্পাদনের প্রভাবগুলি গ্রহণ করে এবং যদি আপনার ফ্রেম পরিবর্তনগুলি হ্যান্ডেল করার প্রয়োজন না হয় তবে এটি কিছুটা জটিলতর:

<ScrollView
  onScroll={event => { 
    this.yOffset = event.nativeEvent.contentOffset.y
  }}
  scrollEventThrottle={16}
>

আইওএসের উপরে ওভারহেডের পারফরম্যান্স হ্রাস করার জন্য এখনও এই গ্যারান্টি দিয়েছিলাম যে আমরা যে কোনও অবস্থান স্ক্রোল ভিউ স্থির করে রেকর্ড করেছি, আমরা বাড়াতে scrollEventThrottleএবং অতিরিক্তভাবে একটি onScrollEndDragহ্যান্ডলার সরবরাহ করতে পারি:

<ScrollView
  onScroll={event => { 
    this.yOffset = event.nativeEvent.contentOffset.y
  }}
  onScrollEndDrag={event => { 
    this.yOffset = event.nativeEvent.contentOffset.y
  }}
  scrollEventThrottle={160}
>

কিন্তু আমরা যদি ফ্রেম পরিবর্তন এবং / অথবা বিষয়বস্তু পরিবর্তন হ্যান্ডেল করতে (যেমন, কারণ আমরা ডিভাইস আবর্তিত হবে, স্ক্রল দৃশ্য ফ্রেমের জন্য উপলব্ধ উচ্চতা পরিবর্তন অনুমতি) চান, তাহলে আমরা অতিরিক্ত উভয় বাস্তবায়ন করতে হবে onContentSizeChangeএবং onLayoutউভয় উচ্চতা ট্র্যাক রাখতে স্ক্রোল ভিউর ফ্রেম এবং এর বিষয়বস্তুগুলি এবং তারপরে ক্রমাগত সর্বাধিক সম্ভব অফসেট এবং ইনফারার গণনা করুন যখন কোনও ফ্রেম বা সামগ্রীর আকার পরিবর্তনের কারণে অফসেটটি স্বয়ংক্রিয়ভাবে হ্রাস পেয়েছে:

<ScrollView
  onLayout={event => {
    this.frameHeight = event.nativeEvent.layout.height;
    const maxOffset = this.contentHeight - this.frameHeight;
    if (maxOffset < this.yOffset) {
      this.yOffset = maxOffset;
    }
  }}
  onContentSizeChange={(contentWidth, contentHeight) => {
    this.contentHeight = contentHeight;
    const maxOffset = this.contentHeight - this.frameHeight;
    if (maxOffset < this.yOffset) {
      this.yOffset = maxOffset;
    }
  }}
  onScroll={event => { 
    this.yOffset = event.nativeEvent.contentOffset.y;
  }}
  onScrollEndDrag={event => { 
    this.yOffset = event.nativeEvent.contentOffset.y;
  }}
  scrollEventThrottle={160}
>

হ্যাঁ, এটি বেশ ভয়াবহ। আমি এটিও 100% নিশ্চিত নই যে আপনি যেখানে স্ক্রোল ভিউর ফ্রেম এবং বিষয়বস্তু উভয়ই একই সাথে পরিবর্তন করতে পারেন সেখানে এটি সর্বদা সঠিকভাবে কাজ করবে । তবে এটি আমি সেরাটি নিয়ে আসতে পারি এবং যতক্ষণ না এই বৈশিষ্ট্যটি কাঠামোর মধ্যে যুক্ত হয় , আমি মনে করি যে এটি যে কেউই করতে পারেন এটি সেরা।


19

ব্র্যাড অয়েলারের উত্তর সঠিক। তবে আপনি কেবল একটি ইভেন্ট পাবেন। আপনার যদি স্ক্রোল অবস্থানের নিয়মিত আপডেটগুলি পেতে হয় তবে আপনার scrollEventThrottleপ্রপ সেট করা উচিত :

<ScrollView onScroll={this.handleScroll} scrollEventThrottle={16} >
  <Text>
    Be like water my friend 
  </Text>
</ScrollView>

এবং ইভেন্ট হ্যান্ডলার:

handleScroll: function(event: Object) {
  console.log(event.nativeEvent.contentOffset.y);
},

সচেতন থাকুন যে আপনি পারফরম্যান্সের সমস্যাগুলির মধ্যে চলে যেতে পারেন। সেই অনুযায়ী থ্রোটল সামঞ্জস্য করুন। 16 আপনাকে সর্বাধিক আপডেট দেয়। 0 শুধুমাত্র একটি।


12
এটি ভুল। একটির জন্য, স্ক্রোলএভেনথ্রোটল কেবলমাত্র আইওএসের জন্য কাজ করে অ্যান্ড্রয়েডের জন্য নয়। দ্বিতীয়ত, এটি শুধুমাত্র নিয়ন্ত্রণ করে যে আপনি কতবার অনস্ক্রোল কল পান। ডিফল্ট একবার ফ্রেম প্রতি হয়, একটি ইভেন্ট নয়। 1 আপনাকে আরও আপডেট দেয় এবং 16 টি আপনাকে কম দেয়। 0 ডিফল্ট। এই উত্তর সম্পূর্ণ ভুল। ফেসবুক.
github.io/react-native/docs/…

1
অ্যান্ড্রয়েডকে রিএটিভ নেটিভ দ্বারা সমর্থিত হওয়ার আগে আমি এর উত্তর দিয়েছিলাম, সুতরাং হ্যাঁ, উত্তরটি কেবল আইওএস-এ প্রয়োগ হয়। ডিফল্ট মান শূন্য, যার ফলশ্রুতি স্ক্রোল ইভেন্টটি প্রতিবার একবার দেখার জন্য একবার স্ক্রোল করা হয়।
কিউটমাচাইন

1
ফাংশনের জন্য এস 6 স্বরলিপিটি কী হবে (ইভেন্ট: অবজেক্ট)}}?
cbartondock

1
শুধু function(event) { }
কিউটমাচাইন

1
@ টিউটররা যদিও এই উত্তরটি অ্যান্ড্রয়েডকে আচ্ছাদন করে না, আপনার সমালোচনা বাকি রয়েছে সম্পূর্ণ বিভ্রান্ত। আপনাকে "কম" আপডেট scrollEventThrottle={16}দেয় না ; 1-16 ব্যাপ্তির যে কোনও সংখ্যা আপনাকে আপডেটের সর্বাধিক সম্ভাব্য হার দেয়। 0-এর ডিফল্ট আপনাকে (আইওএসে) একটি ইভেন্ট দেয় যখন ব্যবহারকারী স্ক্রোলিং শুরু করে এবং তারপরে কোনও আপডেট হয় না (যা বেশ বেহুদা এবং সম্ভবত একটি বাগ); ডিফল্টটি "একবার প্রতি ফ্রেমে" হয় না । আপনার মন্তব্যে এই দুটি ত্রুটি ছাড়াও, আপনার অন্যান্য দাবিগুলি উত্তরটি যা বলেছে তার কোনও কিছুই বিরোধিতা করে না (যদিও আপনি মনে করেন যে তারা তা করেন)।
মার্ক আমেরিকা

7

আপনি যদি ব্যবহারকারীকে যখনই স্ক্রোল করেন তখন এটি ট্র্যাক করার পরিবর্তে কেবলমাত্র বর্তমান অবস্থানটি (উদাহরণস্বরূপ যখন কিছু বোতাম টিপে দেওয়া হয়) পেতে চান তবে onScrollশ্রোতাকে অনুরোধ করা পারফরম্যান্স সমস্যার কারণ হতে চলেছে। কেবলমাত্র বর্তমান স্ক্রোলের অবস্থানটি পাওয়ার সবচেয়ে কার্যক্ষম উপায় হ'ল রিএ্যাক্ট-নেটিভ-ইনভোক প্যাকেজটি ব্যবহার করা। এই সঠিক জিনিসটির জন্য উদাহরণ রয়েছে তবে প্যাকেজটি একাধিক অন্যান্য কাজ করে।

এটি সম্পর্কে এখানে পড়ুন। https://medium.com/@talkol/invoke-any-native-api-directly-from-pure-javascript-in-react-native-1fb6afcdf57d#.68ls1sopd


2
আপনি কি জানেন যে অফসেটের অনুরোধ করার জন্য যদি কোনও ক্লিনার (কিছুটা কম হ্যাকি) এখন উপস্থিত থাকে, বা এটি এখনও অবগত যে এটি করার সেরা উপায়? (আমি কেন অবাক হয়েছি যে এই উত্তরটি কেন
আপত্তিজনক

1
প্যাকেজটি আর নেই, কোথাও চলেছে?
গিথুব

6

মূল প্রশ্নগুলি অনুরোধ করায় স্ক্রোলটি শেষ হওয়ার পরে এক্স / ওয়াই পেতে, সবচেয়ে সহজ উপায় সম্ভবত এটি হ'ল:

<ScrollView
   horizontal={true}
   pagingEnabled={true}
   onMomentumScrollEnd={(event) => { 
      // scroll animation ended
      console.log(e.nativeEvent.contentOffset.x);
      console.log(e.nativeEvent.contentOffset.y);
   }}>
   ...content
</ScrollView>

-1; onMomentumScrollEndকেবল তখনই ট্রিগার করা হয় যখন ব্যবহারকারী যখন এটিকে যেতে দেয় তখন স্ক্রোল ভিউটিতে কিছু গতি থাকে। যদি এগুলি প্রকাশিত হয় যখন স্ক্রোল ভিউটি চলমান না থাকে তবে আপনি কখনই গতির কোনও ইভেন্ট পাবেন না।
মার্ক

1
আমি মোমেন্টামস্ক্রোলএন্ডে পরীক্ষা করেছি এবং এটি ট্রিগার না করা আমার পক্ষে অসম্পূর্ণ ছিল, আমি বিভিন্ন উপায়ে স্ক্রোলিংয়ের চেষ্টা করেছি, যখন স্ক্রোলটি চূড়ান্ত অবস্থানে ছিল তখন আমি স্পর্শটি ছাড়ানোর চেষ্টা করেছি এবং এটিও ট্রিগার হয়েছিল। সুতরাং এই উত্তরটি যতদূর আমি এটি পরীক্ষা করতে পারলাম সঠিক।
ফেরম্মে

6

উপরে উত্তর বলতে বিভিন্ন API ব্যবহার করে অবস্থান পেতে কিভাবে, onScroll, onMomentumScrollEndইত্যাদি; আপনি যদি পৃষ্ঠা সূচকটি জানতে চান তবে আপনি অফসেট মানটি ব্যবহার করে এটি গণনা করতে পারেন।

 <ScrollView 
    pagingEnabled={true}
    onMomentumScrollEnd={this._onMomentumScrollEnd}>
    {pages}
 </ScrollView> 

  _onMomentumScrollEnd = ({ nativeEvent }: any) => {
   // the current offset, {x: number, y: number} 
   const position = nativeEvent.contentOffset; 
   // page index 
   const index = Math.round(nativeEvent.contentOffset.x / PAGE_WIDTH);

   if (index !== this.state.currentIndex) {
     // onPageDidChanged
   }
 };

এখানে চিত্র বর্ণনা লিখুন

আইওএস-এ, স্ক্রোলভিউ এবং দৃশ্যমান অঞ্চলের মধ্যে সম্পর্কটি নিম্নরূপ: ছবিটি https://www.objc.io/issues/3-views/scrol-view/ থেকে এসেছে

রেফ: https://www.objc.io/issues/3-views/scrol-view/


আপনি যদি বর্তমান আইটেমটির "সূচক" পেতে চান তবে এটি সঠিক উত্তর। আপনি ইভেন্ট.nativeEvent.contentOffset.x / deviceWidth নিয়ে যান take আপনার সাহায্যের জন্য ধন্যবাদ!
সারা ইনস ক্যাল্ডেরন

1

এভাবেই বর্তমান স্ক্রোল অবস্থানটি ভিউ থেকে লাইভ পাওয়া শেষ। আমি যা করছি তা হ'ল অন স্ক্রোল ইভেন্ট শ্রোতা এবং স্ক্রোলএভেন্টথ্রোটল ব্যবহার করছে। তারপরে আমি এটিকে আমার তৈরি প্রযোজ্য স্ক্রোল ফাংশনটি পরিচালনা করার জন্য ইভেন্ট হিসাবে পাস করছি এবং আমার প্রপসগুলি আপডেট করছি।

 export default class Anim extends React.Component {
          constructor(props) {
             super(props);
             this.state = {
               yPos: 0,
             };
           }

        handleScroll(event){
            this.setState({
              yPos : event.nativeEvent.contentOffset.y,
            })
        }

        render() {
            return (
          <ScrollView onScroll={this.handleScroll.bind(this)} scrollEventThrottle={16} />
    )
    }
    }

পারফরম্যান্স বিবেচনা করে অনস্ক্রোলের স্থিতি আপডেট করা কি ভাল?
হৃষি

1

অনস্ক্রোলের ব্যবহার অনন্ত লুপে প্রবেশ করে। onMomentumScrolEnd বা oncrolEndDrag এর পরিবর্তে ব্যবহার করা যেতে পারে


0

পৃষ্ঠার হিসাবে, আমি একটি উচ্চতর অর্ডার উপাদান নিয়ে কাজ করছি যা মূলত এটি করতে উপরের পদ্ধতিগুলি ব্যবহার করে। আপনি প্রাথমিক লেআউট এবং বিষয়বস্তু পরিবর্তনের মতো সূক্ষ্মতায় নেমে আসলে এটিকে কিছুটা সময় নেয়। আমি এটি 'সঠিকভাবে' করেছেন বলে দাবি করব না, তবে কিছুটা অর্থে আমি উপাদানটি ব্যবহারের সঠিক উত্তরটি বিবেচনা করব যা এটি সতর্কতার সাথে এবং ধারাবাহিকভাবে করে।

দেখুন: নেটিভ-পেজড-স্ক্রোল-দর্শনটির প্রতিক্রিয়া । প্রতিক্রিয়াটি পছন্দ করবে, এমনকি যদি এটি আমি সমস্ত ভুল করে ফেলেছি!


1
এটা সত্যিই দারুন. এটি করার জন্য আপনাকে ধন্যবাদ। আমি এখনই এটি খুব দরকারী খুঁজে পেয়েছি।
মার্টি কর্টেজ

খুব আনন্দিত! সত্যিই প্রতিক্রিয়া প্রশংসা!

1
একটি অ্যাপোলোজেটিক -১, যেহেতু প্রকল্পটি প্রকাশ্যে স্বীকার করে যে এটি অবিস্মরণীয় এবং উপাদানটিতে "একটি দম্পতি কুৎসিত বাগ আছে"
মার্ক অ্যামেরি

প্রতিক্রিয়াটির জন্য ধন্যবাদ_মার্কএমেরি :) মুক্ত উত্সের জন্য সময় সন্ধান করা সহজ নয়।

-3

আমার বিশ্বাস আমি contentOffsetউপরের-বাম স্ক্রোলটি অফসেটযুক্ত একটি বস্তু সরবরাহ করব:

http://facebook.github.io/react-native/docs/scrollview.html#contentoffset


4
এটা কি সেটার নয়, গেটর নয়?
অ্যারন ওয়াং

1
-1 এটি বাজে কথা; আপনি যে ডকুমেন্টেশনটির সাথে লিঙ্ক করেছেন সেটি কোনও জেএসএক্স প্রোপের জন্য, কোনও জাভাস্ক্রিপ্ট সম্পত্তি নয়, এবং কেবলমাত্র একটি অফসেট সেট করতে ব্যবহার করা যেতে পারে , এটি পাওয়ার জন্য নয়।
মার্ক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.