Learn to create complete user interfaces that both display information effectively and collect user input seamlessly, building the foundation for interactive mobile apps.
Great mobile interfaces follow a natural flow:
Perfect for lesson content with mixed media:
import { ScrollView, Text, View, StyleSheet } from 'react-native';
const LessonViewer = () => {
const [readingProgress, setReadingProgress] = useState(0);
const handleScroll = (event) => {
const { contentOffset, contentSize, layoutMeasurement } = event.nativeEvent;
const progress = (contentOffset.y / (contentSize.height - layoutMeasurement.height)) * 100;
setReadingProgress(Math.min(100, Math.max(0, progress)));
};
return (
<ScrollView
onScroll={handleScroll}
scrollEventThrottle={16}
contentContainerStyle={styles.lessonContainer}
>
<Text style={styles.title}>Chapter 3: Variables</Text>
<Text style={styles.content}>
Variables are like labeled boxes where we store data...
</Text>
</ScrollView>
);
};
Efficiently display lists of items:
const TopicBrowser = ({ onTopicSelect }) => {
const topics = [
{ id: '1', name: 'Variables', completed: true, score: 95 },
{ id: '2', name: 'Functions', completed: false, score: 0 },
];
const renderTopic = ({ item }) => (
<TouchableOpacity
style={[styles.topicCard, item.completed && styles.completedCard]}
onPress={() => onTopicSelect(item)}
>
<Text style={styles.topicName}>{item.name}</Text>
{item.completed && <Text style={styles.score}>✓ {item.score}%</Text>}
</TouchableOpacity>
);
return (
<FlatList
data={topics}
renderItem={renderTopic}
keyExtractor={item => item.id}
refreshing={refreshing}
onRefresh={onRefresh}
/>
);
};
Group content by categories:
const CourseCurriculum = () => {
const curriculum = [
{
title: 'Week 1: Getting Started',
data: [
{ id: '1', lesson: 'Welcome to Mobile Development', completed: true },
{ id: '2', lesson: 'Your First App', completed: false },
]
}
];
const renderLesson = ({ item, index }) => (
<TouchableOpacity style={styles.lessonRow}>
<Text style={[styles.lessonTitle, item.completed && styles.completedText]}>
{index + 1}. {item.lesson}
</Text>
{item.completed && <Text style={styles.checkmark}>✓</Text>}
</TouchableOpacity>
);
const renderWeekHeader = ({ section }) => (
<View style={styles.weekHeader}>
<Text style={styles.weekTitle}>{section.title}</Text>
</View>
);
return (
<SectionList
sections={curriculum}
renderItem={renderLesson}
renderSectionHeader={renderWeekHeader}
keyExtractor={item => item.id}
/>
);
};
Transition smoothly from displaying questions to collecting answers:
const InteractiveQuiz = () => {
const [currentQuestion, setCurrentQuestion] = useState(0);
const [answers, setAnswers] = useState({});
const questions = [
{
id: '1',
question: 'What component is best for long lists?',
type: 'multiple-choice',
options: ['ScrollView', 'FlatList', 'View', 'Text'],
correct: 1
}
];
const renderMultipleChoice = (question) => (
<View style={styles.questionContainer}>
<Text style={styles.questionText}>{question.question}</Text>
{question.options.map((option, index) => (
<TouchableOpacity
key={index}
style={[
styles.optionButton,
answers[question.id] === index && styles.selectedOption
]}
onPress={() => setAnswers({...answers, [question.id]: index})}
>
<View style={styles.radioCircle}>
{answers[question.id] === index && <View style={styles.radioDot} />}
</View>
<Text style={styles.optionText}>{option}</Text>
</TouchableOpacity>
))}
</View>
);
return (
<View style={styles.container}>
<View style={styles.progressHeader}>
<Text style={styles.progressText}>
Question {currentQuestion + 1} of {questions.length}
</Text>
</View>
<ScrollView>
{renderMultipleChoice(questions[currentQuestion])}
</ScrollView>
<TouchableOpacity style={styles.nextButton}>
<Text style={styles.buttonText}>Next</Text>
</TouchableOpacity>
</View>
);
};
Create forms that guide users and provide feedback:
const StudentProfileForm = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
learningStyle: 'visual'
});
const [errors, setErrors] = useState({});
const validate = () => {
const newErrors = {};
if (!formData.name.trim()) newErrors.name = 'Name is required';
if (!formData.email.includes('@')) newErrors.email = 'Valid email required';
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
return (
<KeyboardAvoidingView style={styles.container}>
<ScrollView contentContainerStyle={styles.formContainer}>
<Text style={styles.title}>Create Your Learning Profile</Text>
<View style={styles.inputGroup}>
<Text style={styles.label}>Full Name</Text>
<TextInput
style={[styles.input, errors.name && styles.inputError]}
value={formData.name}
onChangeText={(text) => setFormData({...formData, name: text})}
placeholder="Enter your full name"
/>
{errors.name && <Text style={styles.errorText}>{errors.name}</Text>}
</View>
<View style={styles.inputGroup}>
<Text style={styles.label}>Learning Style</Text>
{['visual', 'auditory', 'kinesthetic'].map((style) => (
<TouchableOpacity
key={style}
style={styles.radioOption}
onPress={() => setFormData({...formData, learningStyle: style})}
>
<View style={styles.radioCircle}>
{formData.learningStyle === style && <View style={styles.radioDot} />}
</View>
<Text>{style.charAt(0).toUpperCase() + style.slice(1)}</Text>
</TouchableOpacity>
))}
</View>
<TouchableOpacity style={styles.submitButton} onPress={validate}>
<Text style={styles.submitText}>Create Profile</Text>
</TouchableOpacity>
</ScrollView>
</KeyboardAvoidingView>
);
};
Combine data display with real-time filtering:
const SearchableLessonList = () => {
const [searchQuery, setSearchQuery] = useState('');
const [filteredLessons, setFilteredLessons] = useState([]);
useEffect(() => {
const filtered = lessons.filter(lesson =>
lesson.title.toLowerCase().includes(searchQuery.toLowerCase())
);
setFilteredLessons(filtered);
}, [searchQuery]);
return (
<View style={styles.container}>
<TextInput
style={styles.searchInput}
value={searchQuery}
onChangeText={setSearchQuery}
placeholder="Search lessons..."
/>
<FlatList
data={filteredLessons}
renderItem={({ item }) => <LessonCard lesson={item} />}
keyExtractor={item => item.id}
/>
</View>
);
};
Build a complete learning interface featuring:
This foundation prepares you for building comprehensive mobile learning applications!