Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Android

एंड्रॉइड में कोटलिन का उपयोग करके ListView को ScrollView में बिना ढहाए कैसे रखें?

ScrollView के अंदर ListView का सही उपयोग

⚠️ महत्वपूर्ण चेतावनी: ScrollView के अंदर ListView (या RecyclerView) रखना एक एंटी-पैटर्न है क्योंकि दोनों स्क्रॉल करने योग्य हैं। यह प्रदर्शन समस्याओं, टच इवेंट संघर्ष और माप समस्याओं का कारण बनता है।

बेहतर विकल्प (अनुशंसित):

  • NestedScrollView + RecyclerView: nestedScrollingEnabled = false के साथ
  • सिंगल RecyclerView: हेडर/फुटर के लिए एकाधिक व्यू टाइप का उपयोग करें
  • ConstraintLayout + Guideline: लचीला लेआउट बिना नेस्टेड स्क्रॉल के

यदि आपको बिल्कुल ListView + ScrollView चाहिए (लीगेसी समर्थन):

चरण 1: नया प्रोजेक्ट बनाएं

एंड्रॉइड स्टूडियो में File → New Project चुनें।

चरण 2: लेआउट (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?> 
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:padding="16dp"
    tools:context=".MainActivity"> 
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"> 
        
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="हेडर सामग्री"
            android:textSize="18sp"
            android:textStyle="bold"
            android:padding="16dp"
            android:background="@android:color/holo_blue_light" />
        
        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" /> 
            
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:text="फुटर सामग्री"
            android:textSize="18sp"
            android:textStyle="bold"
            android:padding="16dp"
            android:background="@android:color/holo_green_light" />
            
    </LinearLayout> 
</ScrollView>

चरण 3: MainActivity.kt

import android.os.Bundle
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private val listItems = arrayOf(
        "आइटम 1", "आइटम 2", "आइटम 3", "आइटम 4", "आइटम 5",
        "आइटम 6", "आइटम 7", "आइटम 8", "आइटम 9", "आइटम 10",
        "आइटम 11", "आइटम 12", "आइटम 13", "आइटम 14", "आइटम 15"
    )
    private lateinit var listView: ListView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title = "KotlinApp"
        
        listView = findViewById(R.id.listView)
        listView.adapter = ArrayAdapter(
            this, 
            android.R.layout.simple_list_item_1, 
            listItems
        )
        
        // ListView की ऊंचाई डायनामिक रूप से सेट करें
        setListViewHeightBasedOnItems(listView)
    }
    
    // ListView की कुल ऊंचाई की गणना करें और सेट करें
    private fun setListViewHeightBasedOnItems(listView: ListView) {
        val adapter = listView.adapter ?: return
        
        var totalHeight = 0
        val desiredWidth = View.MeasureSpec.makeMeasureSpec(
            listView.width, 
            View.MeasureSpec.AT_MOST
        )
        
        for (i in 0 until adapter.count) {
            val listItem = adapter.getView(i, null, listView)
            listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED)
            totalHeight += listItem.measuredHeight
        }
        
        // डिवाइडर ऊंचाई जोड़ें
        val params = listView.layoutParams
        params.height = totalHeight + (listView.dividerHeight * (adapter.count - 1))
        listView.layoutParams = params
        listView.requestLayout()
    }
}

चरण 4: ListHelper.kt (यूटिलिटी क्लास)

import android.util.Log
import android.view.View
import android.widget.ListAdapter
import android.widget.ListView

object ListHelper {
    fun setListViewHeightBasedOnItems(listView: ListView) {
        val adapter: ListAdapter? = listView.adapter ?: return
        
        var totalHeight = 0
        val desiredWidth = View.MeasureSpec.makeMeasureSpec(
            listView.width, 
            View.MeasureSpec.AT_MOST
        )
        
        for (i in 0 until adapter.count) {
            val listItem = adapter.getView(i, null, listView)
            listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED)
            totalHeight += listItem.measuredHeight
        }
        
        val params = listView.layoutParams
        params.height = totalHeight + (listView.dividerHeight * (adapter.count - 1))
        listView.layoutParams = params
        listView.requestLayout()
        
        Log.d("ListHelper", "ListView ऊंचाई सेट: $totalHeight px")
    }
}

आधुनिक समाधान: NestedScrollView + RecyclerView

<!-- activity_main_modern.xml -->
<?xml version="1.0" encoding="utf-8"?> 
<androidx.core.widget.NestedScrollView 
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"> 
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"> 
        
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="हेडर"
            android:textSize="20sp"
            android:padding="16dp"
            android:background="?attr/colorPrimary"
            android:textColor="@android:color/white" />
        
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:nestedScrollingEnabled="false"
            app:layout_constraintTop_toBottomOf="@id/header" /> 
            
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="फुटर"
            android:textSize="20sp"
            android:padding="16dp"
            android:background="?attr/colorSecondary"
            android:textColor="@android:color/white" />
            
    </LinearLayout> 
</androidx.core.widget.NestedScrollView>
// ModernActivity.kt
class ModernActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main_modern)
        
        val recyclerView = findViewById(R.id.recyclerView)
        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.isNestedScrollingEnabled = false // महत्वपूर्ण!
        recyclerView.adapter = MyAdapter(items)
    }
}

सर्वोत्तम अभ्यास: एकाधिक व्यू टाइप के साथ सिंगल RecyclerView

sealed class ListItem {
    data class Header(val title: String) : ListItem()
    data class Content(val text: String) : ListItem()
    data class Footer(val text: String) : ListItem()
}

class UnifiedAdapter(private val items: List) : 
    RecyclerView.Adapter() {
    
    companion object {
        const val TYPE_HEADER = 0
        const val TYPE_CONTENT = 1
        const val TYPE_FOOTER = 2
    }
    
    override fun getItemViewType(position: Int) = when (items[position]) {
        is ListItem.Header -> TYPE_HEADER
        is ListItem.Content -> TYPE_CONTENT
        is ListItem.Footer -> TYPE_FOOTER
    }
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = 
        when (viewType) {
            TYPE_HEADER -> HeaderHolder(LayoutInflater.from(parent.context)
                .inflate(R.layout.item_header, parent, false))
            TYPE_CONTENT -> ContentHolder(LayoutInflater.from(parent.context)
                .inflate(R.layout.item_content, parent, false))
            TYPE_FOOTER -> FooterHolder(LayoutInflater.from(parent.context)
                .inflate(R.layout.item_footer, parent, false))
        }
    
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (val item = items[position]) {
            is ListItem.Header -> (holder as HeaderHolder).bind(item.title)
            is ListItem.Content -> (holder as ContentHolder).bind(item.text)
            is ListItem.Footer -> (holder as FooterHolder).bind(item.text)
        }
    }
    
    override fun getItemCount() = items.size
}
  1. Android ListView में फुटर (Footer) कैसे जोड़ें? Android ListView में फुटर (Footer) कैसे जोड़ें?

    Android ListView में कस्टम फुटर व्यू जोड़ना ListView के अंत में एक फुटर व्यू (जैसे सूची समाप्त संदेश) जोड़ने का तरीका सीखें। चरण 1: नया प्रोजेक्ट बनाएं Android Studio में File → New Project से प्रोजेक्ट बनाएं। चरण 2: मेन लेआउट में ListView res/layout/activity_main.xml: <RelativeLayout xmlns:and

  1. Android में ListView को ScrollView में बिना ढहे कैसे डालें? Android में ListView को ScrollView में बिना ढहे कैसे डालें?

    Android में ScrollView के अंदर ListView को सही ऊंचाई के साथ दिखाने का गाइड यह ट्यूटोरियल दिखाता है कि कैसे ListView को ScrollView के अंदर रखकर उसके सभी आइटम दिखाए जाएं, क्योंकि डिफ़ॉल्ट रूप से ListView ScrollView में संकुचित (collapse) हो जाता है। समस्या ListView और ScrollView दोनों स्क्रॉल करने यो

  1. Android में ScrollView के अंत का पता कैसे लगाएं? Android में ScrollView के अंत का पता कैसे लगाएं?

    ScrollView स्क्रॉल अंत पहचान यह उदाहरण दर्शाता है कि ViewTreeObserver.OnScrollChangedListener का उपयोग करके ScrollView के शीर्ष या अंत तक पहुंचने का पता कैसे लगाएं। चरण 1: नया प्रोजेक्ट बनाएं Android Studio में File → New Project चुनें। चरण 2: लेआउट में ScrollView और WebView (activity_main.xml) &l