React-native-snap-carousel: عدة عناصر نشطة في كل شاشة

تم إنشاؤها على ٢٦ يوليو ٢٠١٧  ·  44تعليقات  ·  مصدر: meliorence/react-native-snap-carousel

هل من الممكن أن يكون لديك عدة عناصر في شريحة واحدة مثل Apple Music:

screen shot 2017-07-26 at 11 38 35

هل سيكون الأسلوب الصحيح هو تغيير البيانات بحيث يتم تجميع جميع العناصر مع عنصرين في كل مجموعة ثم طباعة العنصرين جنبًا إلى جنب عند عرض كل عنصر؟

ومع ذلك ، فإن Airbnb لديها نفس الميزة حيث لا توجد عناصر نشطة ، ولكن يمكنك فقط التمرير بحيث يكون عنصرين مرئيين دائمًا. هل يمكن تحقيق نفس السلوك مع خيارات الحجم الصحيحة مع react-native-snap-carousel ؟

screen shot 2017-07-26 at 12 47 39

* feature help wanted react-native bug

التعليق الأكثر فائدة

يمكنك تصميم الرف الدائري باستخدام محتوى الدعامةContainerCustomStyle
contentContainerCustomStyle={{overflow: 'hidden', width: widthItemSlide * (numberSlide)}}
كل شيء سيكون على ما يرام

ال 44 كومينتر

فيما يتعلق بسؤالك الأول ، من الممكن أن يكون لديك عدة عناصر تمثيلية مرة واحدة ولكنها تتطلب بعض إعادة البناء الثقيلة. ليس لدي وقت للعمل عليها في الوقت الحالي ، لكنني سأضع ذلك في الاعتبار للإصدارات المستقبلية.

ونعم ، كحل بديل ، يمكنك تجميع عنصرين في شريحة واحدة لمحاكاة السلوك ، إذا:

  • التعامل مع الفهرس الخاص ليس أمرًا محظورًا بالنسبة لك
  • أنت موافق على التقاط شريحتين في كل مرة تتحرك فيها.

بخلاف ذلك ، أؤكد أنه يمكنك بسهولة إعادة إنتاج التخطيط الثاني. إليك مثال سريع على استخدام الإصدار FlatList ( activeSlideAlignment ):

react-native-snap-carousel example

const { width: viewportWidth, height: viewportHeight } = Dimensions.get('window');
const SLIDE_WIDTH = Math.round(viewportWidth / 2.6);
const ITEM_HORIZONTAL_MARGIN = 15;
const ITEM_WIDTH = SLIDE_WIDTH + ITEM_HORIZONTAL_MARGIN * 2;
const SLIDER_WIDTH = viewportWidth;

<Carousel
  sliderWidth={SLIDER_WIDTH}
  itemWidth={ITEM_WIDTH}
  activeSlideAlignment={'start'}
  inactiveSlideScale={1}
  inactiveSlideOpacity={1}
/>

مدهش! شكر! مكتبة كبيرة: - د

ومع ذلك ، يبدو أنه إذا كان لدي عدد غير متساوٍ من العناصر ، فيمكنني التمرير سريعًا إلى عنصر غير موجود مثل أنه إذا قمت بالتمرير قدر الإمكان إلى اليمين ، فسيكون العنصر الأخير في يسار الشاشة وغير العنصر الموجود يشغل الجزء الأيمن من الشاشة.

إذا كنت تتحدث عن فكرتك الأولى (شريحتان في شريحة واحدة) ، فهذا أمر متوقع لأن itemWidth هي ضعف عرض العنصر الحقيقي.

لا تنس أنك "تخترق" المكون الإضافي ؛-)

هل هناك أي سبب معروف لتبدو جميع العناصر نشطة في تطبيقي حتى أنني قمت بتعيين قيم inactiveSlide؟
مثله

    <Carousel
            data={this.props.items.toArray()}
            renderItem={this.renderItem}
            contentContainerCustomStyle={{  alignItems: 'center' }}
            inactiveSlideScale={0.8}
            inactiveSlideOpacity={0.7}
            sliderWidth={this.state.sliderWidth}
            itemWidth={this.state.itemWidth}
            enableSnap={true}
            loop={true}
            lockScrollWhileSnapping={true}
            autoplay={true}
            autoplayDelay={500}
            autoplayInterval={3000}
            />

markortiz ما هي نسختك الأصلية من هذا التعليق .

@ bd-arc أنا أستخدم حاليًا "react-native": "0.44.0",
بناء على تفسيرك. أرى القضية الآن.
ولكن في 3.1.0 لم يتم دعم الحلقة اللانهائية بعد ، أليس كذلك؟

مرحبًا markortiz ،

لم أدرك أنك قمت بتعديل رسالتك. نعم ، أنت على حق: لقد تم إطلاق ميزة الحلقة في الإصدار 3.3.0 .

انت لديك الاختيار:

  • البقاء مع 3.1.0 للحصول على الرسوم المتحركة للعنصر
  • التحديث إلى 3.3.0+ للحصول على ميزة التكرار الحلقي
  • قم بترقية إصدار RN للحصول على كليهما.

لا يوجد طريق سهل هنا ، آسف.

@ bd-arc كيف يمكنني حل هذه المشكلة؟

However, it seems if I have uneven number of items, I can swipe to a non-existing item such that, if I scroll as much as I can to the right, the last item is in the left of the screen and a non-existing item takes up the right part of the screen.

simulator screen shot - iphone 6 - 2017-11-08 at 16 45 05

مرحبًا donnes ،

سأحتاج إلى مزيد من المعلومات لمساعدتك في ذلك. هل يمكنك فتح إصدار جديد والتأكد من اتباع إرشادات المساهمة ؟

مرحبًا @ bd-arc
أعتقد أنه ليس من الضروري إنشاء مشكلة جديدة ، لأن المشكلة تتعلق بهذه المشكلة.

أقوم بإنشاء نسخة سناك ليكون من السهل العثور على المشكلة ، ها هو الرابط: https://snack.expo.io/ryxxwAeJG

كما قال mazing سابقًا ، باتباع

لا أعرف كيف أحل هذه المشكلة ، لقد جربت العديد من الأشياء ولكن لا يمكنني إيجاد حل.

donnes أرى ما تعنيه. لم أقدم المثال الكامل في ذلك الوقت وأدرك الآن أن الرمز من إجابتي السابقة يمكن أن يؤدي إلى مشكلات مثل إجابتك.

لقد قمت بتعديل الوجبة الخفيفة التي قدمتها لجعلها تعمل كما هو متوقع: https://snack.expo.io/Hynr0n-1z

كانت مشكلتان:

  • يلزم إضافة sliderItemHorizontalMargin كـ paddingHorizontal بدلاً من marginHorizontal نظرًا لأن الأخير سيعدل طول العنصر ويلعب تمامًا مع المكون الإضافي (وهذا يفسر حقيقة أن العرض كان يتم تمريره قليلاً المزيد إلى اليمين كل لقطة ، وانتهى به الأمر بقسم "فارغ" كبير).
  • كانت هناك حاجة إلى حاويات خارجية (صفراء) وداخلية (أرجوانية) من أجل تطبيق الهامش بشكل صحيح.

لاحظ أن المثال الرسمي للمكون الإضافي ينفذ هذين الاقتراحين.

سوف أقوم بتحديث قسم المستند ذي الصلة إلى ما يلي:

const horizontalMargin = 20;
const slideWidth = 280;

const sliderWidth = Dimensions.get('window').width;
const itemWidth = slideWidth + horizontalMargin * 2;
const itemHeight = 200;

const styles = Stylesheet.create({
    slide: {
        width: itemWidth,
        height: itemHeight,
        paddingHorizontal: horizontalMargin
        // other styles for your item's container
    },
    slideInnerContainer: {
        width: slideWidth,
        flex: 1
        // other styles for the visible container
    }
};

هل تعتقد أنه سيجعل الأمور واضحة بما فيه الكفاية؟

@ bd-arc أعتقد أنني لم أشرح المشكلة التي كنت أمررها بشكل صحيح.

يوجد أدناه مثال على Carousel على تطبيق Airbnb

airbnb-example

والآن المثال الذي أرسلته سابقًا (https://snack.expo.io/BJ4_VmS1M)

snap-carousel-example

بالنظر إلى الأمثلة التي أرسلتها ، يمكنك ملاحظة أنه في الصورة المتحركة الثانية ، عندما ينتهي التمرير ، توجد مسافة حمراء كما لو كانت هناك بطاقة "شبح".

أعتقد أن السلوك الصحيح هو عندما يصل التمرير إلى النهاية ، لا يتجاوز التمرير البطاقة الأخيرة. بعض من هذا القبيل:

untitled

donnes آه ، الآن أرى ما تعنيه!

لكي نكون صادقين ، قد يكون هذا صعب التنفيذ لأنه سيتطلب تعديل عرض ScrollView ومجموعة من المنطق المرتبط عندما يتم تعيين activeSlideAlignment إما على start أو end .

لكنني سأحرص على إلقاء نظرة عليها ، حيث أوافق على أن هذا سيكون أفضل من وجهة نظر تجربة المستخدم ؛-)

@ bd-arc سأقوم بإنشاء شوكة وأحاول إلقاء نظرة عليها. شكرا لك على العمل الجيد! :د

donnes لقد لعبت للتو مع الكود المصدري لأرى ما

حاليًا ، نحدد العنصر النشط عندما يقابل موضعه خطًا وهميًا مرتبطًا بقيمة activeSlideAlignment . على سبيل المثال ، مع قيمة start هذا السطر عند itemWidth / 2 . إذا لم نتمكن من التمرير إلى هذا الموضع ، فلن يتم اعتبار العناصر الأخيرة نشطة أبدًا ، مما يضعف منطق المكون الإضافي بالكامل.

و VirtualizedList عنصر يوفر scrollToIndex() طريقة التي تقبل خيارين للاهتمام: viewPosition و viewOffset . لقد حاولت سابقًا استخدام هؤلاء حيث كان من المفترض أن يسمحوا بنوع السلوك الذي تبحث عنه. لسوء الحظ ، لديهم عيوب كبيرة:

  • viewPosition عربات التي تجرها الدواب مثل الجحيم
  • viewOffset لا يعمل على Android
  • scrollToIndex() غير مسموح به حاليًا (راجع مشكلة React Native هذه ).

إذا كانت لديك أي فكرة عن كيفية تنفيذها ، فسيسعدني سماع أفكارك. لأنه يبدو أنني عالق نوعًا ما حتى يعمل Facebook على تحسين المكونات الأساسية (بالمناسبة ، يمكنك التصويت لإعلام فريقهم بذلك ؛-)).

@ bd-arc لقد حاولت سابقًا تطبيق مكون دائري بنفسي باستخدام FlatList وحصلت على هذه المشكلات أيضًا. من الواضح أن الطريقة الوحيدة هي استخدام ScrollView (لـ IOs) و ViewPagerAndroid (لنظام Android) ولكني واجهت بعض المشكلات مع أحدث إصدارات React Native (0.50+).

بالمناسبة ، سأدرس كود الريبو وأحاول بعض الحلول وأعود إذا وجدت شيئًا. وأيضًا ، سأصوت لهذه الميزات كما اقترحت.

مرة أخرى ، شكرا لك على العمل الجيد! 👍

donnes بينما يعتمد المكون الإضافي على <FlatList /> ، فهو ليس أكثر من <ScrollView /> في النهاية ؛-)

تم التفكير في المكون ViewPagerAndroid بشكل كبير لأنه يتصرف بشكل أفضل بكثير من ScrollView العادي على Android. لسوء الحظ ، لا يمكن تنفيذ تأثير المعاينة (وهو جذر المكون الإضافي) في الوقت الحالي. تمت إضافة خاصية peekEnabled مؤخرًا إليها ، وكانت توقعاتنا عالية ، لكنها لا تعمل ...

كما ترى ، لقد جربت الكثير من الأشياء لتحسين المكون الإضافي ، لكن جوهر RN دائمًا ما يعيق الطريق. سأكون سعيدًا جدًا إذا تمكنت من إيجاد حل :-)

يمكنك تصميم الرف الدائري باستخدام محتوى الدعامةContainerCustomStyle
contentContainerCustomStyle={{overflow: 'hidden', width: widthItemSlide * (numberSlide)}}
كل شيء سيكون على ما يرام

نعم ، إنها خسارة كبيرة في رأيي أيضًا.
وحدة مذهلة ولكن في هذه الحالة (عناصر متعددة) المساحة تقتل واجهة المستخدم تمامًا.

@ univers3 أنا أتفق معك بشدة وأود حقًا أن أكون قادرًا على تنفيذه بهذه الطريقة.

ولكن إذا كنت قد قرأت هذا التعليق ، فأنت تعلم بالفعل أن هذه ليست قطعة من الكعكة وأن حشد حشرات React Native تضيف طبقة أخرى من التعقيد ...

تضمين التغريدة على الرغم من أنه ليس تطبيقًا في الوحدة النمطية ولكنه بدلاً من ذلك يحد من العرض ، إلا أنه يعمل بشكل مثالي في حالتي.

للإشارة ، هذا ما فعلته:

<Carousel
    data={this.props.data}
    renderItem={this._renderItem}
    itemWidth={100}
    activeSlideAlignment={'start'}
    {/** Other props here... */}
    contentContainerCustomStyle={{
        overflow: 'hidden',
        width: 100 * this.props.data.length
    }}
/>

شكرا @ FoxInFlame phithu! أريد ملاحظة أنه في أجهزة Android 9 عندما يتم كسر Carousel عنصر واحد فقط من خلال تعيين width في contentContainerCustomStyle مما يؤدي إلى فارغة Carousel. لذلك أنا لا أحدد العرض في هذه الحالة

const NUMBER_WHICH_CAUSES_BUG_ON_ANDROID_9 = 1;
contentContainerCustomStyle={{
            overflow: 'hidden',
            width:
            // workaround for case when 1 item 
              connectedItems.length === NUMBER_WHICH_CAUSES_BUG_ON_ANDROID_9
                ? undefined
                : this.itemWidth * connectedItems.length,
          }}

@ bd-arc كيف يمكنني حل هذه المشكلة؟

However, it seems if I have uneven number of items, I can swipe to a non-existing item such that, if I scroll as much as I can to the right, the last item is in the left of the screen and a non-existing item takes up the right part of the screen.

simulator screen shot - iphone 6 - 2017-11-08 at 16 45 05

أنا فقط أستخدم أداة snap-carousel مؤخرًا وأواجه هذه المشكلة أيضًا من أجل "المساحة الفارغة الصحيحة". حصلت على الحل ولكني أحتاج إلى إضافة بعض التعليمات البرمجية الإضافية في Carousel.js
نحتاج أولاً إلى إضافة خاصية إضافية lastItemOffsetWidth: PropTypes.number لمعرفة العرض المتبقي على اليمين الذي نريده مثل الهامش 10 أو 20.

أخيرًا ، في الوظيفة:

_initPositionsAndInterpolators (props = this.props) {
        const { data, itemWidth, itemHeight, scrollInterpolator, vertical, activeSlideAlignment, loop, sliderWidth, lastItemOffsetWidth } = props;
       ...
        this._getCustomData(props).forEach((itemData, index) => {
            ...
            if(this._getCustomData(props).length-1 == index && activeSlideAlignment=='start' && !loop){
                var offset=lastItemOffsetWidth;
                if(offset==undefined) offset=0;
                this._positions[index] = {
                    start: index * sizeRef - (sliderWidth - (sizeRef + offset)),
                    end: index * sizeRef - (sliderWidth - (sizeRef + offset)) + sizeRef
                };
            }else{
                this._positions[index] = {
                    start: index * sizeRef,
                    end: index * sizeRef + sizeRef
                };
            }
...

يجب أن تفعل الحيلة.

مرحبًا @ t-vc ،

شكرا على مشاركتك فكرتك!

هل ستعمل مع جميع قيم activeSlideAlignment ( start ، center ، end )؟ إذا كانت الإجابة بنعم ، فهل تمانع في إنشاء علاقات عامة لذلك ومشاركة مقطع فيديو سريع لكودك أثناء العمل؟

هل لديك أي تحديث على هذا؟ كنت أبحث عن حل أيضا

مرحبًا ، آسف لم أدرك الرد حتى تعليق @ kristoff2016 الأخير.
@ bd-arc أركز فقط على activeSlideAlignment start لتجنب تحطيم الآخرين.
سأشاركها معكم يا رفاق بعد 3 كانون الأول (ديسمبر) حيث لا يمكنني الوصول إلى ملفاتي حتى الآن.

@ t-vc آمل أن تتمكن من مشاركة الحل كيف يمكنك إزالة المساحة البيضاء الصحيحة. شكرا مقدما :)

if(this._getCustomData(props).length-1 == index && activeSlideAlignment=='start' && !loop){
    var offset=lastItemOffsetWidth;
    if(offset==undefined) offset=0;
    this._positions[index] = {
        start: index * sizeRef - (sliderWidth - (sizeRef + offset)),
        end: index * sizeRef - (sliderWidth - (sizeRef + offset)) + sizeRef
    };
}else{
    this._positions[index] = {
        start: index * sizeRef,
        end: index * sizeRef + sizeRef
    };
}

إذا لاحظت الكود الأصلي ، فإن this._position [index] يقوم في الواقع بحساب كل عنصر (بدءًا من الأول إلى الأخير) ، فأنا فقط أضف عبارة IF لتغيير نقطة المفاجئة للعنصر الأخير ، هذا كل شيء.

شكرًا لمشاركة تغيير الملف الذي يجب أن أغيره أو أفعله؟ أو الذهاب لتغيير الملف الأصلي في هذه المكتبة؟ هل يمكنك المساعدة في نصيحتي؟ شكرا لكم مقدما

فقط قم بتعديل الملف الأصلي Carousel.js

نعم ، إنها تعمل بشكل جيد الآن. آسف لسؤال آخر هل يجب أن أنقل هذا lib إلى مشروعي الأصلي؟ إذا قمت بتشغيل npm install مرة أخرى؟ شكرا مقدما

أخشى أنه سيتعين عليك القيام بذلك حتى يتبنى المؤلف هذا الحل في آخر تحديث له.

هل رفعت هذه العلاقات العامة إلى المؤلف؟ أعتقد أنه سيكون من الرائع أن تتمكن من مساعدة المؤلف في هذه المشكلة أن هناك العديد من المستخدمين الذين يستخدمونك كما أعتقد.

في الواقع أنا لست على دراية بـ جيثب. لقد سجلت للتو لمشاركة الحل الخاص بي. إذا كنت تستطيع فعل ذلك فسيكون رائعًا.

حسنًا ، سأفعل ذلك!

شكرًا جزيلًا ، على الرغم من أنه لا يزال هناك بعض اللمسات التي يجب القيام بها لجعلها مثالية ، لكنني متأكد من أن المؤلف يمكنه تحسينها.

في انتظار مراجعة المؤلف للكود والموافقة عليه

شكرا @ kristoff2016!

الآن نحتاج فقط إلى جعل بعض الأشخاص يختبرونها والتأكد من أنها لا تكسر أي شيء. لقد توخت الحذر بعد دمج بعض العلاقات العامة التي كان لها الكثير من الآثار الجانبية السلبية لبعض المستخدمين ...

مرحبًا ، @ bd-arc أود أن أقول إنه لا يوجد أي تأثير في هذه العلاقات العامة التي اختبرتها جميعًا في إصدار IOS و Android في جهاز حقيقي. لكن نعم ، بالتأكيد قد نحتاج إلى بعض الأشخاص لاختباره والتأكد من أنه لن يؤثر على أي شيء ، على أي حال ، شكرًا جزيلاً لك على البرنامج المساعد الرائع جدًا.

هل يمكن لأحد أن يرسل لي رابطًا https://github.com/archriss/react-native-snap-carousel/tree/flatlist لا يمكنني الوصول إليه @ bd-arc

مرحباً يا رفاق ، لدي بعض المشاكل
ذكري المظهر:
gif
وفي نظام iOS ، إنه مثالي
Sep-27-2020 15-11-07

مرحباً يا رفاق ، لدي بعض المشاكل
ذكري المظهر:
gif
وفي نظام iOS ، إنه مثالي
2020年9月27日15-11-07

وحلقة غير قادر

مرحباً يا رفاق ، لدي بعض المشاكل
ذكري المظهر:
gif
وفي نظام iOS ، إنه مثالي
2020年9月27日15-11-07

هذا هو الكود
1. https://github.com/hejun041/react-native-snap-carousel/blob/6f199d37be8d9c959830e8619e6ac84e72e18c59/src/utils/animations.js#L37-L43
2.https: //github.com/hejun041/react-native-snap-carousel/blob/6f199d37be8d9c959830e8619e6ac84e72e18c59/src/carousel/Carousel.js#L536-L537
3.https: //github.com/hejun041/react-native-snap-carousel/blob/6f199d37be8d9c959830e8619e6ac84e72e18c59/src/carousel/Carousel.js#L616-L622

ثم استخدمه على هذا النحو

    return <Carousel
      data={data}
      renderItem={this._renderItem.bind(this)}
      sliderWidth={deviceWidth}
      sliderHeight={pxToDp(296)}
      itemWidth={width1}
      inactiveSlideScale={0.842}
      loop hasParallaxImages has2Item
      inactiveSlideOpacity={1}
      activeAnimationType={'decay'}
      activeSlideAlignment={'custom'}
      customMargin={width1}
      slideStyle={styles.imageContainer}
      lockScrollWhileSnapping removeClippedSubviews
    />
      <TouchableOpacity activeOpacity={0.8} key={index}>
        <ParallaxImage
          source={{ uri: 'https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1906469856,4113625838&fm=26&gp=0.jpg' }} showSpinner={false}
          containerStyle={styles.imageContainer}
          style={styles.image}
          parallaxFactor={0}
          dimensions={{ width: pxToDp(177), height: pxToDp(256) }}
          {...parallaxProps}
        />
      </TouchableOpacity>

مرحباً يا رفاق ، لدي بعض المشاكل
ذكري المظهر:
gif
وفي نظام iOS ، إنه مثالي
Sep-27-2020 15-11-07

لقد حللت هذه المشكلة
https://github.com/archriss/react-native-snap-carousel/compare/master...hejun041:master

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات