🎨 UI – Views और Layouts · Lesson 16
ScrollView, CardView और Material Components
ScrollView और NestedScrollView
जब content screen से लंबा हो, उसे scroll container में रखें। NestedScrollView (AndroidX) use करें — यह collapse होने वाले toolbars और CoordinatorLayout के साथ अच्छा चलता है।
XML
<androidx.core.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<!-- exactly ONE child -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<!-- many views here: text, images, cards, buttons … -->
</LinearLayout>
</androidx.core.widget.NestedScrollView>HorizontalScrollView
XML – scroll होने वाले chips
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:singleLine="true">
<!-- chips … -->
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>MaterialCardView
XML – course card
<com.google.android.material.card.MaterialCardView
android:id="@+id/cardCourse"
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:clickable="true"
android:focusable="true"
app:cardCornerRadius="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="160dp"
android:contentDescription="@null"
android:scaleType="centerCrop"
android:src="@drawable/course_android" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="Android with Kotlin"
android:textAppearance="?attr/textAppearanceTitleLarge" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>| Style | Look |
|---|---|
| Widget.Material3.CardView.Elevated | Shadow |
| Widget.Material3.CardView.Filled | Tinted background, shadow नहीं |
| Widget.Material3.CardView.Outlined | Border |
Material buttons
XML – button styles
<!-- filled (main action) -->
<com.google.android.material.button.MaterialButton
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Enroll now" app:icon="@drawable/ic_add" />
<!-- tonal (secondary) -->
<com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Add to wishlist" />
<!-- outlined -->
<com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Syllabus" />
<!-- text button (least important) -->
<com.google.android.material.button.MaterialButton
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Share" />Floating Action Button
XML + Kotlin
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/fabEnroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:text="Enroll"
app:icon="@drawable/ic_add" />
// Kotlin – shrink to a round FAB when the user scrolls down
binding.scroll.setOnScrollChangeListener { _, _, y, _, oldY ->
if (y > oldY) binding.fabEnroll.shrink() else binding.fabEnroll.extend()
}Progress indicators
XML + Kotlin
<!-- spinner while loading -->
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/loader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
<!-- course progress bar -->
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progressCourse"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:trackCornerRadius="6dp"
app:trackThickness="10dp" />
// Kotlin
binding.progressCourse.setProgressCompat(65, true) // animate to 65%
binding.loader.isVisible = falseExample: course detail screen
आम गलतियाँ
- ScrollView में दो children → crash "ScrollView can host only one direct child"।
- ScrollView के अंदर child height
match_parent→wrap_contentuse करें (और छोटे content के लिएfillViewport)। - पुराने
android.widget.Buttonstyles को Material styles के साथ मिलाना → अलग-अलग look; हर जगह MaterialButton use करें (theme <Button> के लिए यह अपने आप करती है)।
सारांश
- लंबी screens के लिए ठीक एक child वाला NestedScrollView।
- Grouped content के लिए MaterialCardView; Material button styles importance दिखाते हैं।
- Main action के लिए FAB; loading और progress के लिए Circular/Linear progress indicators।
✅ Practice
ऊपर वाली course detail screen बनाइए: banner, title, 5 week cards, 40% पर progress bar और scroll down पर shrink होने वाला extended FAB।
अक्सर पूछे जाने वाले प्रश्न (FAQ)
ScrollView में सिर्फ़ एक child क्यों?
ScrollView एक content view को scroll करता है। उसके अंदर LinearLayout या ConstraintLayout रखें और सारे views उसी में डालें।
क्या RecyclerView को ScrollView में रखें?
बचें — RecyclerView recycling खो देता है और धीमा हो जाता है। अलग view types वाला एक RecyclerView या ConcatAdapter use करें।
CardView या MaterialCardView?
Material library का MaterialCardView use करें। यह Material 3 styles, strokes, checkable cards और theme colours support करता है।
