تم نقل repo إلى https://github.com/react-navigation/react-navigation/tree/main/packages/react-niater-tab-view. يرجى فتح المشكلات وسحب الطلبات هناك.
مكون عرض علامة التبويب عبر المنصات لـ React Native. تم تنفيذها باستخدام react-native-pager-view على Android & IOS ، و Panresponder على الويب و MacOS و Windows.
لاستخدام هذه المكتبة ، تحتاج إلى التأكد من أنك تستخدم الإصدار الصحيح من React Native. إذا كنت تستخدم إصدارًا من React Native أقل من 0.63 ، فستحتاج إلى ترقية ذلك قبل محاولة استخدام هذه المكتبة.
react-native-tab-view إصدار | مطلوب رد فعل React الأصلي |
|---|---|
2.xx | < 0.63 |
3.xx | >= 0.63 |
افتح محطة في جذر المشروع وتشغيله:
yarn add react-native-tab-view الآن نحتاج إلى تثبيت عرض react-native-pager-view إذا كنت تخطط لدعم iOS و Android.
إذا كنت تستخدم Expo ، لضمان حصولك على الإصدارات المتوافقة من المكتبات ، قم بتشغيل:
expo install react-native-pager-viewإذا كنت لا تستخدم Expo ، فقم بتشغيل ما يلي:
yarn add react-native-pager-viewلقد انتهينا! يمكنك الآن إنشاء التطبيق وتشغيله على جهازك/جهاز المحاكاة.
import * as React from 'react' ;
import { View , useWindowDimensions } from 'react-native' ;
import { TabView , SceneMap } from 'react-native-tab-view' ;
const FirstRoute = ( ) => (
< View style = { { flex : 1 , backgroundColor : '#ff4081' } } />
) ;
const SecondRoute = ( ) => (
< View style = { { flex : 1 , backgroundColor : '#673ab7' } } />
) ;
const renderScene = SceneMap ( {
first : FirstRoute ,
second : SecondRoute ,
} ) ;
export default function TabViewExample ( ) {
const layout = useWindowDimensions ( ) ;
const [ index , setIndex ] = React . useState ( 0 ) ;
const [ routes ] = React . useState ( [
{ key : 'first' , title : 'First' } ,
{ key : 'second' , title : 'Second' } ,
] ) ;
return (
< TabView
navigationState = { { index , routes } }
renderScene = { renderScene }
onIndexChange = { setIndex }
initialLayout = { { width : layout . width } }
/>
) ;
}جرب هذا المثال على الوجبة الخفيفة
تقوم الحزمة بتصدير مكون TabView وهو العنصر الذي تستخدمه لتقديم عرض علامة التبويب ، ومكون TabBar وهو تطبيق شريط علامة التبويب الافتراضي.
TabViewمكون الحاوية المسؤول عن تقديم وإدارة علامات التبويب. يتبع أنماط تصميم المواد بشكل افتراضي.
الاستخدام الأساسي يبدو هكذا:
< TabView
navigationState = { { index , routes } }
onIndexChange = { setIndex }
renderScene = { SceneMap ( {
first : FirstRoute ,
second : SecondRoute ,
} ) }
/> navigationState ( required )حالة عرض علامة التبويب. يجب أن تحتوي الدولة على الخصائص التالية:
index : رقم يمثل فهرس المسار النشط في مجموعة routesroutes : صفيف يحتوي على قائمة كائنات الطريق المستخدمة لتقديم علامات التبويبيجب أن يحتوي كل كائن مسار على الخصائص التالية:
key : مفتاح فريد لتحديد المسار (مطلوب)title : عنوان المسار لعرضه في شريط علامة التبويبicon : أيقونة الطريق لعرضها في شريط علامة التبويبaccessibilityLabel : تسمية إمكانية الوصول لزر علامة التبويبtestID : معرف الاختبار لزر علامة التبويبمثال:
{
index : 1 ,
routes : [
{ key : 'music' , title : 'Music' } ,
{ key : 'albums' , title : 'Albums' } ,
{ key : 'recents' , title : 'Recents' } ,
{ key : 'purchased' , title : 'Purchased' } ,
]
} TabView هو مكون يتم التحكم فيه ، مما يعني أنه يجب تحديث index عبر رد الاتصال onIndexChange .
onIndexChange ( required )رد الاتصال الذي تم استدعاؤه في تغيير علامة التبويب ، يتلقى فهرس علامة التبويب الجديدة كوسيطة. يجب تحديث حالة التنقل عند استدعاءها ، وإلا يتم إسقاط التغيير.
renderScene ( required )رد الاتصال الذي يعيد عنصر React لتقديمه كصفحة لعلامة التبويب. يتلقى كائن يحتوي على المسار كوسيطة:
const renderScene = ( { route , jumpTo } ) => {
switch ( route . key ) {
case 'music' :
return < MusicRoute jumpTo = { jumpTo } /> ;
case 'albums' :
return < AlbumsRoute jumpTo = { jumpTo } /> ;
}
} ; تحتاج إلى التأكد من أن مساراتك الفردية تنفذ shouldComponentUpdate لتحسين الأداء. لتسهيل تحديد المكونات ، يمكنك استخدام مساعد SceneMap .
يأخذ SceneMap كائنًا مع تعيين route.key لتفاعل المكونات وإرجاع وظيفة لاستخدامها مع Prop renderScene .
import { SceneMap } from 'react-native-tab-view' ;
...
const renderScene = SceneMap ( {
music : MusicRoute ,
albums : AlbumsRoute ,
} ) ; يعد تحديد المكونات بهذه الطريقة أسهل ويعتني بتنفيذ طريقة shouldComponentUpdate .
يتلقى كل مشهد الدعائم التالية:
route : المسار الحالي الذي يقدمه المكونjumpTo : طريقة للقفز إلى علامات تبويب أخرى ، تأخذ route.keyposition : عقدة الرسوم المتحركة التي تمثل الموضع الحالي يمكن استخدام طريقة jumpTo للانتقال إلى علامات التبويب الأخرى برمجيًا:
this . props . jumpTo ( 'albums' ) ; يتم تحسين جميع المشاهد التي يتم تقديمها باستخدام SceneMap باستخدام React.PureComponent ولا تعيد إعادة تقديمها عندما تتغير الدعائم أو الحالات للوالدين. إذا كنت بحاجة إلى مزيد من التحكم في كيفية تحديث المشاهد الخاصة بك (على سبيل المثال - يؤدي تشغيل إعادة تقديم حتى لو لم يتغير navigationState ) ، فاستخدم renderScene مباشرة بدلاً من استخدام SceneMap .
هام: لا تقم بتمرير وظائف مضمّنة إلى SceneMap ، على سبيل المثال ، لا تفعل ما يلي:
SceneMap ( {
first : ( ) => < FirstRoute foo = { this . props . foo } /> ,
second : SecondRoute ,
} ) ;حدد دائمًا مكوناتك في مكان آخر في المستوى العلوي من الملف. إذا قمت بتمرير وظائف مضمنة ، فسوف تقوم بإعادة إنشاء المكون كل عرض ، مما سيؤدي إلى إلغاء كل تغيير وإعادة تشغيله. إنه أمر سيء للغاية بالنسبة للأداء وسيؤدي أيضًا إلى فقدان أي دولة محلية.
إذا كنت بحاجة إلى تمرير الدعائم الإضافية ، فاستخدم وظيفة renderScene المخصصة:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'first' :
return < FirstRoute foo = { this . props . foo } /> ;
case 'second' :
return < SecondRoute /> ;
default :
return null ;
}
} ; renderTabBarرد الاتصال الذي يرجع عنصر رد فعل مخصص لاستخدامه في شريط علامات التبويب:
import { TabBar } from 'react-native-tab-view' ;
...
< TabView
renderTabBar = { props => < TabBar { ... props } /> }
. . .
/ >إذا لم يتم تحديد ذلك ، يتم تقديم شريط علامة التبويب الافتراضي. تقوم بتمرير هذه الدعائم لتخصيص شريط علامة التبويب الافتراضي ، أو توفير شريط علامات التبويب الخاصة بك ، أو تعطيل شريط علامة التبويب بالكامل.
< TabView
renderTabBar = { ( ) => null }
. . .
/ > tabBarPosition موضع شريط علامة التبويب في عرض علامة التبويب. القيم الممكنة هي 'top' و 'bottom' . الإعدادات الافتراضية إلى 'top' .
lazyالوظيفة التي تأخذ كائنًا مع المسار الحالي ويعيد منطقية للإشارة إلى ما إذا كان سيتم عرض المشاهد بشكل كسول.
بشكل افتراضي ، يتم تقديم جميع المشاهد لتوفير تجربة انتقاد أكثر سلاسة. ولكن قد ترغب في تأجيل عرض المشاهد غير المركزة حتى يراها المستخدم. لتمكين تقديم كسول لمشهد معين ، ارجع true من getLazy لهذا route :
< TabView
lazy = { ( { route } ) => route . name === 'Albums' }
. . .
/ > عند تمكين عرض كسول للشاشة ، فإنه عادة ما يستغرق بعض الوقت لتقديمه عندما يتحول إلى التركيز. يمكنك استخدام دعامة renderLazyPlaceholder لتخصيص ما يراه المستخدم خلال هذه الفترة القصيرة.
يمكنك أيضًا تمرير منطقية لتمكين كسول لجميع المشاهد:
< TabView
lazy
/> lazyPreloadDistance عندما يتم تمكين lazy ، يمكنك تحديد عدد الطرق المجاورة التي يجب تحميلها مسبقًا مع هذا الدعامة. هذه القيمة الافتراضية إلى 0 مما يعني أن الصفحات البطيئة يتم تحميلها عند دخولها إلى منفذ العرض.
renderLazyPlaceholder رد الاتصال الذي يعيد عنصر رد فعل مخصص لتقديمه للطرق التي لم يتم تقديمها بعد. يتلقى كائن يحتوي على المسار كوسيطة. يجب أيضًا تمكين الدعامة lazy .
عادةً ما يتم عرض هذا العرض فقط للثانية المقسمة. تبقيها خفيفة الوزن.
بشكل افتراضي ، هذا يجعل null .
keyboardDismissModeسلسلة تشير إلى ما إذا كان يتم رفض لوحة المفاتيح استجابة لإيماءة السحب. القيم الممكنة هي:
'auto' (افتراضي): يتم رفض لوحة المفاتيح عندما يتغير الفهرس.'on-drag' : يتم رفض لوحة المفاتيح عندما يبدأ السحب.'none' : Drags لا ترفض لوحة المفاتيح. swipeEnabled منطقية تشير إلى ما إذا كان لتمكين إيماءات التمرير. يتم تمكين إيماءات التمرير بشكل افتراضي. سيقوم تمرير false بتعطيل الإيماءات المنقحة ، ولكن لا يزال بإمكان المستخدم تبديل علامات التبويب عن طريق الضغط على شريط علامة التبويب.
animationEnabledتمكين الرسوم المتحركة عند تغيير علامة التبويب. بشكل افتراضي ، هذا صحيح.
onSwipeStartرد الاتصال الذي يسمى عند بدء إيماءة التمرير ، أي المستخدم يلمس الشاشة ويحركها.
onSwipeEndرد الاتصال الذي يسمى عندما تنتهي إيماءة التمرير ، أي المستخدم يرفع إصبعه من الشاشة بعد لفتة التمرير.
initialLayoutكائن يحتوي على الارتفاع الأولي وعرض الشاشات. تمرير هذا سيؤدي إلى تحسين أداء العرض الأولي. بالنسبة لمعظم التطبيقات ، هذا افتراضي جيد:
< TabView
initialLayout = { { width : Dimensions . get ( 'window' ) . width } }
. . .
/ > sceneContainerStyleنمط لتطبيق على عرض لف كل شاشة. يمكنك تمرير هذا لتجاوز بعض الأنماط الافتراضية مثل قطع الفائض:
pagerStyleنمط لتطبيق على عرض Pager لف جميع المشاهد.
styleنمط لتطبيق على حاوية عرض علامة التبويب.
TabBar تصميم المواد تحت عنوان Tab. لتخصيص شريط علامة التبويب ، ستحتاج إلى استخدام Prop renderTabBar of TabView لتقديم TabBar وتمرير الدعائم الإضافية.
على سبيل المثال ، لتخصيص لون المؤشر ولون خلفية شريط علامات التبويب ، يمكنك تمرير indicatorStyle ودعائم style إلى TabBar على التوالي:
const renderTabBar = props => (
< TabBar
{ ... props }
indicatorStyle = { { backgroundColor : 'white' } }
style = { { backgroundColor : 'pink' } }
/>
) ;
//...
return (
< TabView
renderTabBar = { renderTabBar }
. . .
/ >
);getLabelText الوظيفة التي تأخذ كائنًا مع المسار الحالي وإرجاع نص التسمية لعلامة التبويب. يستخدم route.title افتراضيًا.
< TabBar
getLabelText = { ( { route } ) => route . title }
. . .
/ > getAccessible الوظيفة التي تأخذ كائنًا مع المسار الحالي ويعيد منطقية للإشارة إلى ما إذا كان سيتم وضع علامة على علامة تبويب accessible . الافتراضات إلى true .
getAccessibilityLabel الوظيفة التي تأخذ كائنًا مع المسار الحالي وإرجاع ملصق إمكانية الوصول لزر علامة التبويب. يستخدم route.accessibilityLabel افتراضيًا إذا تم تحديده ، وإلا فإنه يستخدم عنوان الطريق.
< TabBar
getAccessibilityLabel = { ( { route } ) => route . accessibilityLabel }
. . .
/ > getTestID الوظيفة التي تأخذ كائنًا مع المسار الحالي وإرجاع معرف اختبار لزر علامة التبويب لتحديد زر علامة التبويب هذا في الاختبارات. يستخدم route.testID افتراضيًا.
< TabBar
getTestID = { ( { route } ) => route . testID }
. . .
/ > renderIconالوظيفة التي تأخذ كائنًا مع المسار الحالي ، والحالة المركزة واللون ، وإرجاع عنصر رد فعل مخصص لاستخدامه كرمز.
< TabBar
renderIcon = { ( { route , focused , color } ) => (
< Icon
name = { focused ? 'albums' : 'albums-outlined' }
color = { color }
/>
) }
. . .
/ > renderLabelالوظيفة التي تأخذ كائنًا مع المسار الحالي ، والحالة المركزة واللون ، وإرجاع عنصر رد فعل مخصص لاستخدامه كتسمية.
< TabBar
renderLabel = { ( { route , focused , color } ) => (
< Text style = { { color , margin : 8 } } >
{ route . title }
</ Text >
) }
. . .
/ > renderTabBarItem الوظيفة التي تأخذ كائن TabBarItemProps وإرجاع عنصر رد فعل مخصص لاستخدامه كزر علامة تبويب.
renderIndicatorالوظيفة التي تأخذ كائنًا مع المسار الحالي وإرجاع عنصر رد فعل مخصص لاستخدامه كمؤشر لتبويب.
renderBadgeالوظيفة التي تأخذ كائنًا مع المسار الحالي وإرجاع عنصر رد فعل مخصص لاستخدامه كشارة.
onTabPressوظيفة للتنفيذ في علامة التبويب اضغط. يتلقى المشهد لعلامة التبويب المضغوط ، مفيدة لأشياء مثل التمرير إلى الأعلى.
بشكل افتراضي ، تبديل علامة التبويب أيضًا تبديل علامة التبويب. لمنع هذا السلوك ، يمكنك استدعاء preventDefault :
< TabBar
onTabPress = { ( { route , preventDefault } ) => {
if ( route . key === 'home' ) {
preventDefault ( ) ;
// Do something else
}
} }
. . .
/ > onTabLongPressوظيفة للتنفيذ في علامة التبويب Long Press ، استخدم لأشياء مثل عرض قائمة بمزيد من الخيارات
activeColorلون مخصص للأيقونة والتسمية في علامة التبويب النشطة.
inactiveColorلون مخصص للأيقونة والتسمية في علامة التبويب غير النشطة.
pressColorلون تموج المواد (Android> = 5.0 فقط).
pressOpacityعتامة علامة التبويب المضغوط (iOS و Android <5.0 فقط).
scrollEnabledمنطقية تشير إلى ما إذا كان يجب جعل شريط علامة التبويب قابل للتمرير.
إذا قمت بتعيين scrollEnabled على true ، فيجب عليك أيضًا تحديد width في tabStyle لتحسين العرض الأولي.
bouncesمنطقية تشير إلى ما إذا كان شريط علامة التبويب يرتد عند التمرير.
tabStyleنمط لتطبيق على عناصر علامة التبويب الفردية في شريط علامة التبويب.
بشكل افتراضي ، تتناول جميع عناصر TAB نفس العرض المحسوب مسبقًا بناءً على عرض الحاوية. إذا كنت تريد منهم أن يأخذوا عرضهم الأصلي ، فيمكنك تحديد width: 'auto' في tabStyle .
indicatorStyleنمط لتطبيق على المؤشر النشط.
indicatorContainerStyleنمط لتطبيق على عرض الحاوية للمؤشر.
labelStyleالنمط لتطبيق على تسمية عنصر علامة التبويب.
contentContainerStyleنمط لتطبيق على الحاوية الداخلية لعلامات التبويب.
styleنمط لتطبيق على حاوية شريط التبويب.
gapتحديد التباعد بين علامات التبويب.
testIDمعرف الاختبار ل tabbar. يمكن استخدامها لتمرير شريط علامة التبويب في الاختبارات
إذا كنت ترغب في دمج عرض علامة التبويب مع نظام الملاحة الخاص بـ React Navigation ، على سبيل المثال ، تريد أن تكون قادرًا على الانتقال إلى علامة تبويب باستخدام navigation.navigate .
لاحظ أن بعض الوظائف غير متوفرة مع تكامل React Navigation 4 بسبب القيود في التنقل في React. على سبيل المثال ، من الممكن تغيير علامات التبويب المقدمة ديناميكيًا.
تسمى وظيفة renderScene في كل مرة يتغير فيها الفهرس. إذا كانت وظيفة renderScene مكلفة ، فمن الجيد أن تنقل كل مسار إلى مكون منفصل إذا لم يعتمدوا على الفهرس ، واستخدموا shouldComponentUpdate أو React.memo في مكونات طريقك لمنع إعادة البيع غير الضرورية.
على سبيل المثال ، بدلاً من:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
default :
return null ;
}
} ;افعل ما يلي:
const renderScene = ( { route } ) => {
switch ( route . key ) {
case 'home' :
return < HomeComponent /> ;
default :
return null ;
}
} ; حيث يكون <HomeComponent /> عبارة عن مكون PureComponent إذا كنت تستخدم مكونات الفصل:
export default class HomeComponent extends React . PureComponent {
render ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
} أو ، ملفوفة في React.memo إذا كنت تستخدم مكونات الوظائف:
function HomeComponent ( ) {
return (
< View style = { styles . page } >
< Avatar />
< NewsFeed />
</ View >
) ;
}
export default React . memo ( HomeComponent ) ;نحتاج إلى قياس عرض الحاوية وبالتالي تحتاج إلى الانتظار قبل تقديم بعض العناصر على الشاشة. إذا كنت تعرف العرض الأولي مقدمًا ، فيمكنك تمريره ولن نحتاج إلى انتظار قياسه. معظم الوقت ، إنه مجرد عرض النافذة.
على سبيل المثال ، تمرير initialLayout التالي إلى TabView :
const initialLayout = {
height : 0 ,
width : Dimensions . get ( 'window' ) . width ,
} ;ستظل طريقة عرض علامة التبويب تتفاعل مع التغييرات في البعد وتكيف وفقًا لذلك لاستيعاب أشياء مثل تغيير الاتجاه.
إذا كان لديك عدد كبير من الطرق ، وخاصة الصور ، فيمكن أن يبطئ الرسوم المتحركة كثيرًا. يمكنك بدلاً من ذلك تقديم عدد محدود من الطرق.
على سبيل المثال ، قم بما يلي لتقديم طريقين فقط على كل جانب:
const renderScene = ( { route } ) => {
if ( Math . abs ( index - routes . indexOf ( route ) ) > 2 ) {
return < View /> ;
}
return < MySceneComponent route = { route } /> ;
} ; إن تعشيش TabView داخل ScrollView العمودي سيقوم بتعطيل التحسينات في مكونات FlatList المقدمة داخل TabView . لذا تجنب القيام بذلك إن أمكن.
lazy و renderLazyPlaceholder لتقديم الطرق حسب الحاجة يتم تعطيل الخيار lazy افتراضيًا لتوفير تجربة تبديل علامة تبويب أكثر سلاسة ، ولكن يمكنك تمكينها وتوفير مكون من العناصر النائبة لتجربة تحميل كسول أفضل. إن تمكين lazy يمكن تحسين أداء الحمل الأولي عن طريق تقديم الطرق فقط عند عرضها. راجع مرجع الدعامة لمزيد من التفاصيل.
أثناء التطوير ، يمكنك تشغيل تطبيق المثال لاختبار التغييرات الخاصة بك.
تأكد من أن الكود الخاص بك يمرر TypeScript و ESLINT. قم بتشغيل ما يلي للتحقق:
yarn typescript
yarn lintلإصلاح أخطاء التنسيق ، قم بتشغيل ما يلي:
yarn lint -- --fixتذكر إضافة اختبارات للتغيير إذا أمكن.