0
# KeyboardAwareSectionList Component
1
2
The KeyboardAwareSectionList is a SectionList component that automatically handles keyboard appearance by scrolling to keep focused TextInput fields visible. It extends React Native's SectionList with keyboard awareness capabilities, making it ideal for sectioned lists containing input fields.
3
4
## Capabilities
5
6
### Component Class
7
8
A SectionList component enhanced with keyboard awareness functionality.
9
10
```typescript { .api }
11
/**
12
* A SectionList component that automatically scrolls to keep focused TextInput fields visible
13
* when the keyboard appears. Extends SectionList with keyboard-aware behavior.
14
*/
15
export class KeyboardAwareSectionList<ItemT = any> extends React.Component<
16
KeyboardAwareSectionListProps<ItemT>,
17
KeyboardAwareState
18
> {
19
getScrollResponder(): any;
20
scrollToPosition(x: number, y: number, animated?: boolean): void;
21
scrollToEnd(animated?: boolean): void;
22
scrollForExtraHeightOnAndroid(extraHeight: number): void;
23
scrollToFocusedInput(
24
reactNode: any,
25
extraHeight?: number,
26
keyboardOpeningTime?: number
27
): void;
28
scrollIntoView(
29
element: React.ReactElement,
30
options?: ScrollIntoViewOptions
31
): Promise<void>;
32
update(): void;
33
}
34
35
interface KeyboardAwareSectionListProps<ItemT> extends KeyboardAwareProps, SectionListProps<ItemT> {}
36
```
37
38
**Usage Examples:**
39
40
```typescript
41
import React, { useState } from 'react';
42
import { View, TextInput, Text, StyleSheet } from 'react-native';
43
import { KeyboardAwareSectionList } from 'react-native-keyboard-aware-scroll-view';
44
45
interface ContactSection {
46
title: string;
47
data: Contact[];
48
}
49
50
interface Contact {
51
id: string;
52
name: string;
53
email: string;
54
phone: string;
55
}
56
57
// Basic usage with sectioned contact form
58
export function ContactForm() {
59
const [sections] = useState<ContactSection[]>([
60
{
61
title: 'Personal Contacts',
62
data: [
63
{ id: '1', name: '', email: '', phone: '' },
64
{ id: '2', name: '', email: '', phone: '' },
65
]
66
},
67
{
68
title: 'Work Contacts',
69
data: [
70
{ id: '3', name: '', email: '', phone: '' },
71
{ id: '4', name: '', email: '', phone: '' },
72
]
73
},
74
{
75
title: 'Emergency Contacts',
76
data: [
77
{ id: '5', name: '', email: '', phone: '' },
78
]
79
}
80
]);
81
82
const renderContactItem = ({ item }: { item: Contact }) => (
83
<View style={styles.contactItem}>
84
<TextInput
85
style={styles.input}
86
placeholder="Name"
87
defaultValue={item.name}
88
/>
89
<TextInput
90
style={styles.input}
91
placeholder="Email"
92
defaultValue={item.email}
93
keyboardType="email-address"
94
/>
95
<TextInput
96
style={styles.input}
97
placeholder="Phone"
98
defaultValue={item.phone}
99
keyboardType="phone-pad"
100
/>
101
</View>
102
);
103
104
const renderSectionHeader = ({ section }: { section: ContactSection }) => (
105
<View style={styles.sectionHeader}>
106
<Text style={styles.sectionTitle}>{section.title}</Text>
107
</View>
108
);
109
110
return (
111
<KeyboardAwareSectionList
112
sections={sections}
113
renderItem={renderContactItem}
114
renderSectionHeader={renderSectionHeader}
115
keyExtractor={item => item.id}
116
style={styles.container}
117
enableOnAndroid={true}
118
extraHeight={75}
119
/>
120
);
121
}
122
123
// Advanced usage with mixed content types
124
export function SettingsForm() {
125
const [settingsSections] = useState([
126
{
127
title: 'Account Settings',
128
data: [
129
{ id: 'username', type: 'input', label: 'Username', value: '' },
130
{ id: 'email', type: 'input', label: 'Email', value: '' },
131
{ id: 'bio', type: 'textarea', label: 'Bio', value: '' },
132
]
133
},
134
{
135
title: 'Preferences',
136
data: [
137
{ id: 'theme', type: 'input', label: 'Theme Color', value: '' },
138
{ id: 'language', type: 'input', label: 'Language', value: '' },
139
]
140
}
141
]);
142
143
const renderSettingItem = ({ item }: { item: any }) => (
144
<View style={styles.settingItem}>
145
<Text style={styles.settingLabel}>{item.label}</Text>
146
{item.type === 'textarea' ? (
147
<TextInput
148
style={[styles.input, styles.textarea]}
149
placeholder={`Enter ${item.label.toLowerCase()}`}
150
defaultValue={item.value}
151
multiline
152
numberOfLines={3}
153
/>
154
) : (
155
<TextInput
156
style={styles.input}
157
placeholder={`Enter ${item.label.toLowerCase()}`}
158
defaultValue={item.value}
159
/>
160
)}
161
</View>
162
);
163
164
const renderSectionHeader = ({ section }: { section: any }) => (
165
<View style={styles.sectionHeader}>
166
<Text style={styles.sectionTitle}>{section.title}</Text>
167
</View>
168
);
169
170
return (
171
<KeyboardAwareSectionList
172
sections={settingsSections}
173
renderItem={renderSettingItem}
174
renderSectionHeader={renderSectionHeader}
175
keyExtractor={item => item.id}
176
style={styles.container}
177
enableOnAndroid={true}
178
enableAutomaticScroll={true}
179
extraHeight={100}
180
extraScrollHeight={50}
181
keyboardOpeningTime={250}
182
resetScrollToCoords={{ x: 0, y: 0 }}
183
enableResetScrollToCoords={true}
184
stickySectionHeadersEnabled={true}
185
onKeyboardWillShow={(frames) => console.log('Keyboard will show', frames)}
186
/>
187
);
188
}
189
190
const styles = StyleSheet.create({
191
container: { flex: 1, backgroundColor: '#f5f5f5' },
192
sectionHeader: {
193
backgroundColor: '#e0e0e0',
194
padding: 15,
195
borderBottomWidth: 1,
196
borderBottomColor: '#ccc',
197
},
198
sectionTitle: {
199
fontSize: 16,
200
fontWeight: 'bold',
201
color: '#333',
202
},
203
contactItem: {
204
backgroundColor: 'white',
205
padding: 15,
206
borderBottomWidth: 1,
207
borderBottomColor: '#eee',
208
},
209
settingItem: {
210
backgroundColor: 'white',
211
padding: 15,
212
borderBottomWidth: 1,
213
borderBottomColor: '#eee',
214
},
215
settingLabel: {
216
fontSize: 14,
217
fontWeight: '500',
218
marginBottom: 8,
219
color: '#333',
220
},
221
input: {
222
borderWidth: 1,
223
borderColor: '#ccc',
224
padding: 10,
225
marginBottom: 10,
226
borderRadius: 5,
227
backgroundColor: '#fafafa',
228
},
229
textarea: {
230
height: 80,
231
textAlignVertical: 'top',
232
},
233
});
234
```
235
236
### Get Scroll Responder
237
238
Gets the underlying SectionList's scroll responder for advanced scroll operations.
239
240
```typescript { .api }
241
/**
242
* Get the underlying SectionList's scroll responder
243
* @returns The scroll responder instance
244
*/
245
getScrollResponder(): any;
246
```
247
248
### Scroll to Position
249
250
Programmatically scrolls to a specific position in the SectionList.
251
252
```typescript { .api }
253
/**
254
* Scroll to specific position with or without animation
255
* @param x - The x coordinate to scroll to
256
* @param y - The y coordinate to scroll to
257
* @param animated - Whether to animate the scroll (default: true)
258
*/
259
scrollToPosition(x: number, y: number, animated?: boolean): void;
260
```
261
262
### Scroll to End
263
264
Scrolls to the end of the SectionList content.
265
266
```typescript { .api }
267
/**
268
* Scroll to end with or without animation
269
* @param animated - Whether to animate the scroll (default: true)
270
*/
271
scrollToEnd(animated?: boolean): void;
272
```
273
274
**Usage Example:**
275
276
```typescript
277
import React, { useRef } from 'react';
278
import { Button } from 'react-native';
279
import { KeyboardAwareSectionList } from 'react-native-keyboard-aware-scroll-view';
280
281
export function ScrollableSectionList({ sections }: { sections: any[] }) {
282
const sectionListRef = useRef<KeyboardAwareSectionList>(null);
283
284
const scrollToTop = () => {
285
sectionListRef.current?.scrollToPosition(0, 0, true);
286
};
287
288
const scrollToEnd = () => {
289
sectionListRef.current?.scrollToEnd(true);
290
};
291
292
return (
293
<>
294
<KeyboardAwareSectionList
295
ref={sectionListRef}
296
sections={sections}
297
renderItem={({ item }) => <YourItemComponent item={item} />}
298
renderSectionHeader={({ section }) => <YourHeaderComponent section={section} />}
299
keyExtractor={item => item.id}
300
/>
301
<Button title="Scroll to Top" onPress={scrollToTop} />
302
<Button title="Scroll to End" onPress={scrollToEnd} />
303
</>
304
);
305
}
306
```
307
308
### Android Extra Height Scroll
309
310
Android-specific method for scrolling with additional height offset.
311
312
```typescript { .api }
313
/**
314
* Android-specific scroll method with extra height offset (Android only)
315
* @param extraHeight - Additional height to add to the scroll offset
316
*/
317
scrollForExtraHeightOnAndroid(extraHeight: number): void;
318
```
319
320
### Scroll to Focused Input
321
322
Scrolls to a specific focused TextInput field within a section item.
323
324
```typescript { .api }
325
/**
326
* Scroll to a specific focused input field
327
* @param reactNode - The React node handle of the input to scroll to
328
* @param extraHeight - Additional height offset (optional)
329
* @param keyboardOpeningTime - Custom keyboard opening delay (optional)
330
*/
331
scrollToFocusedInput(
332
reactNode: any,
333
extraHeight?: number,
334
keyboardOpeningTime?: number
335
): void;
336
```
337
338
### Scroll Into View
339
340
Scrolls a React element into view with customizable positioning.
341
342
```typescript { .api }
343
/**
344
* Scrolls an element into view with customizable positioning
345
* @param element - The React element to scroll into view
346
* @param options - Configuration options for scroll positioning
347
* @returns Promise that resolves when scrolling is complete
348
*/
349
scrollIntoView(
350
element: React.ReactElement,
351
options?: ScrollIntoViewOptions
352
): Promise<void>;
353
```
354
355
### Update
356
357
Manually triggers scrolling to the currently focused input field.
358
359
```typescript { .api }
360
/**
361
* Manually trigger scroll to currently focused input
362
* Useful for updating scroll position after layout changes
363
*/
364
update(): void;
365
```
366
367
## Props
368
369
The KeyboardAwareSectionList accepts all standard SectionList props plus the KeyboardAwareProps interface:
370
371
```typescript { .api }
372
interface KeyboardAwareSectionListProps<ItemT> extends KeyboardAwareProps, SectionListProps<ItemT> {
373
// Inherits all SectionList props (sections, renderItem, renderSectionHeader, etc.)
374
// Plus all KeyboardAwareProps (see main documentation)
375
}
376
```
377
378
## Common Use Cases
379
380
### User Profile Sections
381
382
```typescript
383
import React, { useState } from 'react';
384
import { View, TextInput, Text } from 'react-native';
385
import { KeyboardAwareSectionList } from 'react-native-keyboard-aware-scroll-view';
386
387
export function UserProfileSections() {
388
const [profileSections] = useState([
389
{
390
title: 'Basic Information',
391
data: [
392
{ id: 'firstName', label: 'First Name', value: '' },
393
{ id: 'lastName', label: 'Last Name', value: '' },
394
{ id: 'email', label: 'Email', value: '' },
395
]
396
},
397
{
398
title: 'Contact Details',
399
data: [
400
{ id: 'phone', label: 'Phone Number', value: '' },
401
{ id: 'address', label: 'Address', value: '' },
402
{ id: 'city', label: 'City', value: '' },
403
]
404
},
405
{
406
title: 'Additional Info',
407
data: [
408
{ id: 'bio', label: 'Bio', value: '', multiline: true },
409
{ id: 'website', label: 'Website', value: '' },
410
]
411
}
412
]);
413
414
const renderProfileItem = ({ item }: { item: any }) => (
415
<View style={{ padding: 15, backgroundColor: 'white' }}>
416
<Text style={{ marginBottom: 8, fontWeight: '500' }}>{item.label}</Text>
417
<TextInput
418
style={{
419
borderWidth: 1,
420
borderColor: '#ccc',
421
padding: 10,
422
borderRadius: 5,
423
height: item.multiline ? 80 : 40,
424
}}
425
placeholder={`Enter ${item.label.toLowerCase()}`}
426
defaultValue={item.value}
427
multiline={item.multiline}
428
textAlignVertical={item.multiline ? 'top' : 'center'}
429
/>
430
</View>
431
);
432
433
const renderSectionHeader = ({ section }: { section: any }) => (
434
<View style={{ backgroundColor: '#f0f0f0', padding: 12 }}>
435
<Text style={{ fontSize: 16, fontWeight: 'bold' }}>{section.title}</Text>
436
</View>
437
);
438
439
return (
440
<KeyboardAwareSectionList
441
sections={profileSections}
442
renderItem={renderProfileItem}
443
renderSectionHeader={renderSectionHeader}
444
keyExtractor={item => item.id}
445
enableOnAndroid={true}
446
extraHeight={100}
447
stickySectionHeadersEnabled={true}
448
/>
449
);
450
}
451
```
452
453
## Platform Support
454
455
- **iOS**: Full support for all features
456
- **Android**: Requires `enableOnAndroid={true}` and `windowSoftInputMode="adjustPan"` in AndroidManifest.xml for full functionality