こんにちは、アプリ開発担当のエモトです。本業は稲作で、合間に横スクロールのダンジョン攻略や、アプリ開発を行っています。
React Native で画面を作る時、ScrollView を利用する方は多いと思います。その画面でスクロールするとき、ある child だけ上部に固定させたいというシーンが出てくるかもしれません。iOS で言うと UITableView におけるセクションヘッダーに近い動きです。さて、それを React Native で実装したい場合、どうすれば良いでしょうか?
上部固定させたい
まず最初にネイティブ開発で考えると、iOS の UIScrollView にはそのような機能がないので、UITableView のセクションヘッダーをカスタマイズする方法が考えられます。
それに従うと React Native なら ScrollView から SectionList に置き換えと、手間のかかる改修が予想されました・・・が!、なんと、React Native の ScrollView 自体にその機能が既に実装してありました。stickyHeaderIndices に固定したい child の index を指定するだけです。簡単でした。
const Component: React.FC<Props> = () => { const stickyHeaderIndices = [1] return ( <ScrollView stickyHeaderIndices={stickyHeaderIndices} > <Header /> <Sticky /> <Contents /> </ScrollView> ) }
なぜ上部固定できるのか?
すでに ScrollView で組んでるコードをバラすことなく、パラメーター1つで実現できました。ただ、ここで1つの疑問が生まれます。本来ネイティブの UIScrollView ではそのよう機能がないのに、なぜ React Native の ScrollView だとできるのか?。
ここで私は、「ScrollView はセクションヘッダーを利用するため、実は UITableView なのでは?」と考えましたが、ネイティブ側に対応する RCTScrollView.h を見る限り、UIView を継承しいて、その考えは誤りでした。
次に、stickyHeaderIndices を設定すると呼ばれる ScrollViewStickyHeader.js を見ると、その答えが分かりました。
style={[..., {transform: [{translateY: this._translateY}]}, ...]}
このコンポーネントは AnimatedView で作られて、style をアニメーション制御していました。あの React Native でも力技的な・地味なコードを書いているんだなーという印象を受けました。
まとめ
私のバックボーンは iOS アプリのネイティブ開発なので、何かを作る際はまずネイティブの知識や経験を持ってきて、それを React Native に当てはめることをやるので、今回のようなネイティブではできないことが React Native では簡単にできるのは驚かされます。日々勉強です。
また、毎日使っている、便利でスマートなフレームワークは、OSS活動される皆様方たちの努力の上でなりたっているんだなと、改めて実感しました。そのフレームワークを使って、よいアプリを作っていこうと思う、良い機会でした。