react中竖直轮播滚动_用水平滚动视图React本地轮播

本文介绍了如何在React中实现竖直轮播滚动效果,参考自https://medium.com/@rossbulat/react-native-carousels-with-horizontal-scroll-views-60b0587a670c,探讨了在React项目中利用水平滚动视图创建本地竖直轮播的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

react中竖直轮播滚动

ScrollView:可以全部统治一个组件吗? (ScrollView: One component to rule them all?)

ScrollView is one of the most fundamental components of a React Native app, that can act as a standalone component as well as a dependency for a range of other more complex components.

ScrollView是React Native应用程序的最基本组件之一,它既可以充当独立组件,又可以作为一系列其他更复杂组件的依赖项。

It is impressive thinking about its wide-ranging use-cases. It can be used as a standalone vertical scrolling solution, automatically making your content suitable for any screen height. Other more complex components, like SectionList and FlatList, rely on ScrollView and its props, whereas community driven components like KeyboardAwareScrollView expand upon ScrollView’s functionality to solve complicated UX problems with the virtual keyboard.

关于其广泛的用例,令人印象深刻。 它可以用作独立的垂直滚动解决方案,自动使您的内容适合任何屏幕高度。 其他更复杂的组件(如SectionListFlatList )依赖于ScrollView及其道具,而社区驱动的组件(如KeyboardAwareScrollView扩展了ScrollView的功能来解决虚拟键盘的复杂UX问题。

And these use cases just entail vertical scrolling. ScrollView also supports horizontal scrolling and pinch to zoom — that tracks the current magnification with the zoomScale prop, along with others to limit its minimum, maximum and zoom behaviour. This makes ScrollView ideal for panning around maps-based applications, or apps with large canvases like boardgames.

这些用例仅需要垂直滚动。 ScrollView还支持水平滚动和收缩缩放-使用zoomScale道具跟踪当前的放大倍率,并限制其最小,最大和缩放行为。 这使ScrollView非常适合在基于地图的应用程序或带有大型画布的应用程序(如棋盘游戏)之间平移。

The particular use-case this article focusses on, however, is that of a horizontal-only scrollable carousel component that allows the user to swipe through a range of items (or intervals). This is a very common feature in apps today, being utilised to display and structure a range of data:

但是,本文关注的特定用例是只允许用户在一系列项目(或间隔)中滑动的仅水平可滚动轮播组件。 这是当今应用程序中非常常见的功能,可用于显示和构造一系列数据:

Image for post
Common use cases carousels are used in apps
应用中使用了常见用例轮播

We’ll explore a range of props and event handlers ScrollView offers to make this happen, as well as custom logic for handling carousel state. The demo project referenced in this article is also available on Github, where two styles of carousel are showcased.

我们将探究ScrollView提供的各种道具和事件处理程序,以实现此目标,以及用于处理轮播状态的自定义逻辑。 Github上也提供本文引用的演示项目,其中展示了两种样式的轮播。

带有ScrollView的轮播如何工作 (How Carousels with ScrollView Work)

Utilising ScrollView to create carousels works extremely well, maintaining a native and fluid feel to your app, while keeping the doors open for customisability of the look and behaviour of the carousel itself.

利用ScrollView创建轮播效果非常好,可以为您的应用程序保持原生和流畅的感觉,同时保持开门状态,以实现轮播本身的外观和行为的可定制性。

First and foremost, a ScrollView component must be configured to horizontally structure content rather than vertically. By setting the horizontal prop to true, the ScrollView will automatically arrange its child components in columns rather than rows.

首先,必须将ScrollView组件配置为水平结构而不是垂直结构。 通过将horizontal prop设置为trueScrollView将自动将其子组件按列而不是行进行排列。

This sets us up nicely to endeavour into other props to optimise the behaviour of the view (more on props in the next section).

这很好地设置了我们来尝试其他道具以优化视图的行为(在下一节中将对道具进行更多介绍)。

<轮播/>组件结构 (<Carousel /> Component Structure)

In order to visualise how the ScrollView component is used with other components to form a carousel, consider the following illustration:

为了可视化ScrollView组件与其他组件一起形成轮播的方式,请考虑以下插图:

Image for post

There is a 3 component foundational setup here:

这里有3个组件的基础设置:

  • The <ScrollView /> is housed within a <Container /> component that defines the visible area of the carousel. This is where borders, background colours, etc, can be styled, giving some context to the scrollable area.

    <ScrollView />位于定义<Container />轮播可见区域的<Container />组件中。 在这里可以设置边框,背景色等的样式,从而为可滚动区域提供一些上下文。

  • The <ScrollView /> itself. It is important to mention at this stage that the <ScrollView /> itself needs a pre-defined width in its contentContainerStyle prop. Without the width pre-defined, we would not be able to scroll through the ScrollView — we’ll explore some code further down to calculate the width based on how many intervals the carousel holds, as well as snapping to the beginning of each interval when scrolling.

    <ScrollView />本身。 重要的是在此阶段要提到<ScrollView />本身在contentContainerStyle道具中需要预定义的width 。 如果没有预先定义的宽度,我们将无法滚动浏览ScrollView我们将进一步探索一些代码,以根据轮播持有的间隔时间来计算宽度,并在出现以下情况时捕捉到每个间隔的开始滚动。

Height does not matter so much — it can be set as a fixed value or be automatic based on the carousel content, depending on your design.

高度无关紧要-可以将其设置为固定值,也可以根据轮播内容自动设置高度,具体取决于您的设计。

  • Each <Item />, representing one item of the carousel. This is where your displayable content will be housed, such as a row of stats, an app introduction slide, etc. Depending on your design, one <Item /> may span 100% of the <Container /> width, or it may span a half or even a third of the viewable area — this will be considered in the code further down.

    每个<Item /> ,代表一个轮播项目。 这是可显示内容的存放位置,例如一排统计信息,应用程序介绍幻灯片等。根据您的设计,一个<Item />可能跨越<Container />宽度的100% ,或者可能跨越可视区域的一半甚至三分之一-在下面的代码中将予以考虑。

A <Item /> is not tied to a carousel interval E.g. one item per swipe. There could be multiple items tied into one interval, such as displaying multiple statistics or graphs in one view. This is carousels should be designed, and is considered in the demos further down.

<Item /> 不依赖于转盘间隔每轻扫例如一个项目。 可能有多个项目捆绑在一起,例如在一个视图中显示多个统计信息或图形。 这是轮播应该设计的,并在演示中进一步考虑。

The above represents a basic component setup to get the carousel working, but is by no means a complete solution.

以上是启动轮播的基本组件设置,但绝不是完整的解决方案。

Based on scroll events, however, we can introduce more UX to compliment the carousel state such as bullet points fixed below the carousel representing each interval with the active interval bullet point being a darker shade. These additional UX components are often placed outside the <ScrollView /> itself, not being subject to scroll events or swipe-able content:

但是,基于滚动事件,我们可以引入更多的UX来补充圆盘传送带状态,例如固定在圆盘传送带下方的子弹点,代表每个间隔,而活动间隔子弹点则为较暗的阴影。 这些附加的UX组件通常放置在<ScrollView />本身之外,不受滚动事件或可滑动内容的影响:

// carousel component hierarchy pseudo code<Container>
<ScrollView>
<Item />
<Item />
<Item />
--- next interval
<Item />
<Item />
<Item />
</ScrollView><Bullets />
<Container />

Notice where the next interval is — or the point that will snap to the start of the carousel to separate its stages, that is calculated separately from the Item widths.

请注意,下一个间隔在哪里-或将与圆盘传送带的起点对齐以分离其各个阶段的点,该点是与 Item 宽度 分开计算的

Let’s dive into some of the critical props of ScrollView next, before utilising some of the event handlers to calculate vital carousel information.

接下来,在利用一些事件处理程序计算重要的轮播信息之前,让我们深入了解ScrollView一些关键道具。

ScrollView道具和滚动事件 (ScrollView Props and Scroll Events)

There are a couple of key props at our disposal to configure a ScrollView to be a paginated, horizontal scroller.

我们可以使用几个关键道具来将ScrollView配置为分页的水平滚动条。

Examine the following example that highlights key props:

检查以下示例,其中重点介绍了主要道具:

// props for a horizontal, paginated ScrollView<ScrollView
horizontal={true}
contentContainerStyle={{ width: `${100 * intervals}%` }}
showsHorizontalScrollIndicator={false}
scrollEventThrottle={200}
decelerationRate="fast"
pagingEnabled
>
{/* Items */}
</ScrollView>

In the above code we are assuming that each <Item /> takes up 100% width of the carousel area, therefore the width of the ScrollView will be 100% multiplied by the amount of items.

在上面的代码中,我们假设每个 <Item /> 占用轮播区域的100%宽度,因此 ScrollView 的宽度 乘以 100% 乘以 项目的数量。

The top two props have already been covered, aligning horizontal content within the Scroll View, as well as defining its width in contentContainerStyle. Breaking down the others:

上面的两个道具已经被覆盖,它们可以在Scroll View中对齐horizontal内容,并在contentContainerStyle定义其宽度。 分解其他:

  • The showHorizontalScrollIndicator set to false hides the scroll bar — the horizontal bar that shows up as the user is scrolling to give context to the current scroll position. This bar is not too necessary in a carousel environment, and can be replaced with the aforementioned bullet point mechanism instead.

    showHorizontalScrollIndicator设置为false隐藏滚动条,即在用户滚动以将上下文提供给当前滚动位置时显示的水平条。 在圆盘传送带环境中,该杆不是太必要,可以改为使用上述的项目符号机制。

  • scrollEventThrottle will become important further down for optimising scroll event performance, setting a delay between scroll events being fired. For carousels at least, it is not required to maintain an accurate scroll position — the data derived from these scroll events will determine which interval the carousel is showing only, which can be calculated with some latency without having an impact on user experience.

    对于优化滚动事件性能,设置触发滚动事件之间的延迟, scrollEventThrottle将变得越来越重要。 至少对于轮播来说,不需要保持准确的滚动位置-从这些滚动事件中得出的数据将确定轮播仅显示哪个间隔,可以在不影响用户体验的情况下以一定的等待时间进行计算。

  • The pagingEnabled prop acts as a snapping shortcut, that stops the Scroll View at multiples of its size when scrolling. This is what effectively separates the scroll view into sections, intelligently snapping the scroll position to the nearest threshold as the user swipes.

    pagingEnabled用作捕捉快捷方式,在滚动时会以其大小的倍数停止Scroll View。 这就是有效地将滚动视图分为多个部分的功能,可以在用户滑动时智能地将滚动位置捕捉到最近的阈值。

  • decelerationRate defines the speed at which the scroll stops after the user lifts their finger. It is recommended to use fast for carousel purposes, shortening the time it takes to transition to the interval in question’s snap position.

    decelerationRate定义了用户抬起手指后滚动停止的速度。 建议fast用于轮播,以缩短过渡到相关问题的快照位置间隔所需的时间。

ScrollView的其他捕捉道具 (Other snapping props of ScrollView)

The pagingEnabled prop is a very useful shortcut for defining the interval logic for the Scroll View, but it is worth noting that there are a number of other props that can refine this pagination, or snapping, behaviour.

pagingEnabled是定义Scroll View的时间间隔逻辑的非常有用的快捷方式,但是值得注意的是,还有许多其他属性可以改进此分页或捕捉行为。

For example, pagingEnabled can also be achieved with the snapToStart, snapToOffsets, snapToInterval and snapToAlignment props, that can be used together to define custom Scroll View pagination. snapToInterval is also a shortcut in place of defining an array of numbers with snapToOffsets.

例如, pagingEnabled也可以使用snapToStartsnapToOffsetssnapToIntervalsnapToAlignment道具来实现,它们可以一起使用来定义自定义Scroll View分页。 snapToInterval也是一种使用snapToOffsets定义数字数组的快捷方式。

snapToStart and snapToOffsets={[0]} achieve the same result.

snapToStart snapToOffsets={[0]} 达到相同的结果。

snapToAlignment is also an interesting prop, that snaps the view to the start, end, or center of a snapping interval. Think of a scenario where multiple Scroll View <Item />’s are on show simultaneously. Setting snapToAlignment to center will automatically snap the active interval to be at the center of the scroll area, consequently giving precedence to the current item being at the center of the view. snapToAlignment can be used with snap props and pagingEnabled.

snapToAlignment也是一个有趣的道具,它可以将视图捕捉到捕捉间隔的startendcenter 。 考虑一下同时显示多个Scroll View <Item />的情况。 将snapToAlignment设置为center将自动将活动间隔捕捉到滚动区域的中心,因此优先于当前项位于视图的中心。 snapToAlignment可以与snap道具和pagingEnabled

It is worth studying and experimenting with these props to get a more unique feel to a carousel, if you need to deliver a bespoke carousel experience. For the examples discussed in this article, pagingEnabled alone works very well and keeps syntax to a minimum.

如果您需要提供定制的轮播体验,则值得研究和尝试使用这些道具以获得更独特的轮播感觉。 对于本文讨论的示例,单独使用pagingEnabled可以很好地工作,并将语法降至最低。

With ScrollView configuration now understood, lets next implement a <Carousel /> component, and introduce scroll events that will aid in carousel state and further UX additions.

现在已经了解了ScrollView配置,接下来让我们实现<Carousel />组件,并引入滚动事件,这些事件将有助于轮播状态和进一步的UX添加。

ScrollView的轮播实现 (Carousel Implementation with ScrollView)

In this section we will walk though creating a fully functional <Carousel /> component, separating the implementation into two steps before importing and using it.

在本节中,我们将逐步创建一个功能齐全的<Carousel />组件,在导入和使用该组件之前将实现分为两个步骤。

Within the Carousel component, ScrollView events will be used to trigger component state updates and initialisation in the following order:

Carousel组件内,将使用ScrollView事件按以下顺序触发组件状态更新和初始化:

  • Step 1: Initialising the carousel within the onContentSizeChange event, that will calculate how many intervals (carousel “pages”) there are, as well as its width.

    步骤1:在onContentSizeChange事件中初始化轮播,它将计算有多少间隔(轮播“页面”)及其宽度。

  • Step 2: Calculating the currently active interval with the onScroll event, and reflecting that in surrounding UX.

    步骤2:使用onScroll事件计算当前活动间隔,并将其反映在周围的UX中。

A gist will be presented for the first step, and the final project with the full solution will be linked at the end of the article. To look at this project now, it is available hereon Github. Here is a screencast of the demo, showcasing two styles of carousel:

第一步将提出要点,而带有完整解决方案的最终项目将在本文结尾处链接。 现在来看这个项目,可以在Github上找到 。 这是演示的截屏,展示了两种旋转木马风格:

Image for post

Both these carousels are derived from the same <Carousel /> component, but render different components for their items, based on a style prop we will be passing into it.

这两个转盘均来自相同的<Carousel />组件,但根据我们将传递给它的style道具,为其商品渲染不同的组件。

导入轮播组件及其道具 (Importing Carousel component and its props)

To understand the <Carousel /> component, let’s firstly examine how we want to embed the component within JSX — and what props it requires:

要了解<Carousel />组件,首先让我们检查一下我们如何将组件嵌入JSX中-以及它需要哪些道具:

// importing and using `Carousel`import Carousel from './Carousel';export const App = () => ( 
<View style={styles.container}> <Carouselstyle="slides"itemsPerInterval={1}items={[{
title: 'Welcome, swipe to continue.',
}, {
title: 'About feature X.',
}, {
title: 'About feature Y.',
}]}
/>
</View>
);

As we can see from above, <Carousel /> supports 3 props, that each play a role in configuring the function and content of the carousel:

从上方可以看到, <Carousel />支持3个道具,每个道具在配置轮播的功能和内容时都起作用:

  • style defines what type of <item /> component we will use for each item displayed in the carousel. In the demo project we have two components that represent a carousel item — Stat and Slide. Within the carousel itself is a switch statement that renders the component corresponding to the style prop, acting as a simple mechanism to change the look or type of carousel to render.

    style定义轮播中显示的每个项目将使用的<item />组件类型。 在演示项目中,我们有两个代表轮播项目的组件StatSlide 。 轮播本身中包含一个switch语句,该语句用于渲染与样式道具相对应的组件,作为一种简单的机制来更改要渲染的轮播的外观或类型。

  • itemsPerInterval allows us to configure how many of the <Item /> component to display on one swipe-able area of the carousel — or how many items are displayed at one time. The value passed in here is used within the component to determine how many swipe-able sections the carousel holds. For the slides style, only 1 item per interval is required. For the stats style however, 3 items per interval is required, with each Stat consuming 33% width.

    itemsPerInterval允许我们配置要在轮播的一个可滑动区域上显示多少<Item />组件,或者一次显示多少个项。 此处传递的值在组件内用于确定圆盘传送带可容纳多少可滑动部分。 对于slides样式,每个间隔仅需要一项。 但是对于stats样式,每个间隔需要3项,每个Stat占用33%的宽度。

  • items is an array of objects consisting of the data of each carousel item. The structure of the objects need to be consistent and conform to the <Item /> component‘s data requirements. A Slide component here only requires a title, keeping the item requirements simple.

    items是由每个轮播项目的数据组成的对象数组。 对象的结构需要一致并符合<Item />组件的数据要求。 此处的Slide组件仅需要一个标题,从而使项目要求保持简单。

These props are dealt with at the top of Carousel:

这些道具在Carousel的顶部处理:

// extracting Carousel propsconst { items, style } = props;
const itemsPerInterval = props.itemsPerInterval === undefined
? 1
: props.itemsPerInterval;

From here we can initialise the carousel.

从这里我们可以初始化轮播。

轮播初始化 (Carousel initialisation)

The initialisation of the carousel is carried out in one of its ScrollView event handlers, onContentSizeChange. This event is actually fired when the Scroll View first renders, allowing us to embed initialisation logic:

轮播的初始化是在其ScrollView事件处理程序之一onContentSizeChange 。 实际上,在Scroll View首次渲染时会触发此事件,从而允许我们嵌入初始化逻辑:

// calling init() within `onContentSizeChange`...
return (
<View style={styles.container}>
<ScrollView
...onContentSizeChange={(w, h) => init(w)} >
...
</ScrollView>
</View>
)

In the event your Scroll View changes size based on a responsive design, onContentSizeChange will fire again, and keep the carousel dimensions in sync with init().

如果您的Scroll View根据响应式设计更改大小,则 onContentSizeChange 将再次触发,并使轮播尺寸与 init() 保持同步

onContentSizeChange gives us the width and height of the carousel as callback arguments, the width of which is then passed into Carousel’s init() method. init() is responsible for defining the carousel width, along with how many intervals will be present:

onContentSizeChange为我们提供轮播的宽度和高度作为回调参数,然后将其宽度传递到Carousel的init()方法中。 init()负责定义轮播宽度以及将出现多少个间隔:

// init() implementationconst [intervals, setIntervals] = React.useState(1);
const [width, setWidth] = React.useState(0);const init = (width: number) => {// initialise width
setWidth(width); // get total items present
const totalItems = items.length; // initialise total intervals setIntervals(Math.ceil(totalItems / itemsPerInterval));
}

By utilising useState hooks and a simple calculation to determine how many intervals are needed based on how many items the carousel holds, the carousel now has context about its width and snapping intervals required for it to function.

通过使用useState挂钩和简单的计算来确定所需的间隔时间,该间隔取决于传送带所容纳的物品数量,传送带现在具有有关其宽度和功能所需的捕捉间隔的上下文。

The following Gist outlines the <Carousel /> component at this initialisation stage:

以下要点概述了此初始化阶段的<Carousel />组件:

介绍电流间隔计算 (Introducing current interval calculation)

To calculate the current carousel interval (also thought of as the carousel “page”), a bit more logic needs to be introduced into the <Carousel /> component. Firstly, an additional useState hook to store the current interval, as a default value of 1:

要计算当前轮播间隔(也称为轮播“页面”),需要在<Carousel />组件中引入更多逻辑。 首先,附加的useState钩子存储当前间隔,默认值为1:

const [interval, setInterval] = React.useState(1);

In order to calculate the active interval, we rely on ScrollView’s onScroll event handler. When it fires we will call another method, getInterval(), to determine the current interval based on the ScrollView’s current offset:

为了计算活动间隔,我们依靠ScrollViewonScroll事件处理程序。 当它触发时,我们将调用另一个方法getInterval() ,以根据ScrollView的当前偏移量确定当前间隔:

// defining onScroll event and getInterval()const getInterval = (offset: any) => {
for (let i = 1; i <= intervals; i++) {
if (offset < (width / intervals) * i) {
return i;
}
if (i == intervals) {
return i;
}
}
}...<ScrollView
...onScroll={data => {
setInterval(getInterval(data.nativeEvent.contentOffset.x));
}}scrollEventThrottle={200}
>
...
</ScrollView>

getInterval() is simply a for loop with a couple of conditional statements inside it, checking if the current scroll offset falls between certain interval thresholds. The scrollEventThrottle prop limits the scroll event to fire every 200 milliseconds, not to put too much of a burden on performance.

getInterval()只是一个for循环,其中包含几个条件语句,用于检查当前滚动偏移量是否在某些间隔阈值之间。 scrollEventThrottle道具限制了滚动事件每200毫秒触发一次,而不会对性能造成太大负担。

添加补充用户体验 (Adding supplemental UX)

With the knowledge of knowing what interval the carousel is now on, we can now introduce UX such as bullet points as visual aids to the currently selected interval.

了解了轮播的当前间隔后,我们现在可以将UX(例如项目符号点)引入当前所选间隔作为视觉辅助。

To construct the bullet points dynamically, another for loop can be used to build the correct amount of bullets based on the number of intervals:

为了动态构造项目符号点,可以使用另一个for循环根据间隔数来构建正确数量的项目符号:

// constructing bullet pointslet bullets = [];
for (let i = 1; i <= intervals; i++) {
bullets.push(
<Text
key={i}
style={{
...styles.bullet,
opacity: interval=== i ? 0.5 : 0.1
}}
>
&bull;
</Text>
);
}

Each bullet point is wrapped within a native Text component, with the currently selected interval having a less intense opacity. Once constructed, the bullets array can simply be embedded in JSX:

每个项目符号点都包装在一个本机Text组件中,当前选择的interval具有较小的不透明性。 一旦构建完成, bullets数组就可以简单地嵌入JSX中:

// inserting bullets after ScrollView
...
</ScrollView>
<View style={styles.bullets}>{bullets}
</View>
</View>
)

The full implementation of Carousel can be found here.

可以在此处找到Carousel的完整实现。

综上所述 (In Summary)

This wraps up the base implementation of the horizontal carousel, giving a solid foundation with the hope developers can build upon to achieve more unique styles and behaviours.

这样就构成了水平轮播的基本实现,为开发人员可以基于此实现更多独特的样式和行为奠定了坚实的基础。

This article has demonstrated how to create native feeling carousels with ScrollView, and how to build the surrounding carousel logic around the component. We have also looked into how to structure a standalone <Carousel /> component that supports various stage styles with particular components, such as Stat and Slide.

本文演示了如何使用ScrollView创建具有ScrollView感觉的轮播,以及如何在组件周围构建周围的轮播逻辑。 我们还研究了如何构建一个独立的<Carousel />组件,该组件支持具有特定组件(例如StatSlide各种舞台样式。

The demo project ultimately attempts to abstract key logic and styling for the developer to decide, not being tied down to any particular size or layout of a carousel item.

该演示项目最终尝试抽象出关键逻辑和样式,以供开发人员决定,而不是受限于轮播项目的任何特定大小或布局。

The project can be viewed or cloned here on Github, with the playable demo showcasing both the statistics and slideshow styled carousels.

您可以在Github上查看或克隆该项目,可播放的演示同时展示统计数据和幻灯片样式的轮播。

翻译自: https://medium.com/@rossbulat/react-native-carousels-with-horizontal-scroll-views-60b0587a670c

react中竖直轮播滚动

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值