একটি স্ক্রোলভিউ বিন্যাসের ভিতরে লিনিয়ারলআউট পূরণ করতে একটি তালিকাআডাপ্টার ব্যবহার করা


95

আমি খুব সাধারণ সমস্যার মুখোমুখি হয়েছি: আমি একটি ক্রিয়াকলাপ প্রকাশ করেছি এবং এখন দেখা যাচ্ছে এটি এর মধ্যে কয়েকটি আইটেম প্রদর্শন করা উচিত ScrollView। এটি করার স্বাভাবিক উপায় হ'ল বিদ্যমানটি ব্যবহার করা ListAdapter, এটির সাথে সংযোগ স্থাপন করা ListViewএবং আমার কাছে আইটেমের তালিকা থাকত O

কিন্তু আপনি একটি নেস্টেড স্থাপন উচিত নয় ListViewএকটি ScrollViewএমনকি Android লিন্ট এটি সম্পর্কে অভিযোগ - এটা স্ক্রলিং আপ স্ক্রু হিসাবে।

সুতরাং এখানে আমার প্রশ্ন:

আমি কীভাবে ListAdapterএকটি LinearLayoutবা অনুরূপ কিছুতে সংযুক্ত করব ?

আমি জানি এই সমাধানটি অনেকগুলি আইটেমের জন্য স্কেল করবে না তবে আমার তালিকাগুলি খুব ছোট (<10 আইটেম) তাই ভিউগুলি পুনরায় ব্যবহারের প্রয়োজন হয় না। পারফরম্যান্স অনুসারে আমি সমস্ত দর্শন সরাসরি মধ্যে রেখেই বেঁচে থাকতে পারি LinearLayout

আমি যে সমাধানটি নিয়ে এসেছি তা হ'ল আমার বিদ্যমান ক্রিয়াকলাপের বিন্যাসটি এর শিরোনামদ্বার অংশে রাখুন ListView। তবে এটি এই প্রক্রিয়াটিকে অপব্যবহারের মতো অনুভব করে তাই আমি একটি পরিষ্কার সমাধানের সন্ধান করি।

ধারনা?

আপডেট: সঠিক দিকটি অনুপ্রাণিত করার জন্য আমি আমার সমস্যাটি দেখানোর জন্য একটি নমুনা বিন্যাস যুক্ত করেছি:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/news_detail_layout"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical"
              android:visibility="visible">


    <ScrollView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="#FFF"
            >

        <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="vertical"
                android:paddingLeft="@dimen/news_detail_layout_side_padding"
                android:paddingRight="@dimen/news_detail_layout_side_padding"
                android:paddingTop="@dimen/news_detail_layout_vertical_padding"
                android:paddingBottom="@dimen/news_detail_layout_vertical_padding"
                >

            <TextView
                    android:id="@+id/news_detail_date"
                    android:layout_height="wrap_content"
                    android:layout_width="fill_parent"
                    android:gravity="center_horizontal"
                    android:text="LALALA"
                    android:textSize="@dimen/news_detail_date_height"
                    android:textColor="@color/font_black"
                    />

            <Gallery
                    android:id="@+id/news_detail_image"
                    android:layout_height="wrap_content"
                    android:layout_width="fill_parent"
                    android:paddingTop="5dip"
                    android:paddingBottom="5dip"
                    />

            <TextView
                    android:id="@+id/news_detail_headline"
                    android:layout_height="wrap_content"
                    android:layout_width="fill_parent"
                    android:gravity="center_horizontal"
                    android:text="Some awesome headline"
                    android:textSize="@dimen/news_detail_headline_height"
                    android:textColor="@color/font_black"
                    android:paddingTop="@dimen/news_detail_headline_paddingTop"
                    android:paddingBottom="@dimen/news_detail_headline_paddingBottom"
                    />

            <TextView
                    android:id="@+id/news_detail_content"
                    android:layout_height="wrap_content"
                    android:layout_width="fill_parent"
                    android:text="Here comes a lot of text so the scrollview is really needed."
                    android:textSize="@dimen/news_detail_content_height"
                    android:textColor="@color/font_black"
                    />

            <!---
                HERE I NEED THE LIST OF ITEMS PROVIDED BY THE EXISTING ADAPTER. 
                They should be positioned at the end of the content, so making the scrollview smaller is not an option.
            ---->                        

        </LinearLayout>
    </ScrollView>
</LinearLayout>

আপডেট 2 আমি বুঝতে সহজ করার জন্য শিরোনামটি পরিবর্তন করেছি (একটি ডাউনওয়েট পেয়েছি, দোহ!)।


4
আপনি কি কখনও এই সমস্যার সুন্দর পরিষ্কার সমাধান খুঁজে পেয়েছেন? আমি দেখতে পাচ্ছি গুগল তাদের প্লে স্টোরে পর্যালোচনার জন্য এটি ব্যবহার করে। কেউ জানেন কীভাবে তারা এটা করে?
Zapnologica

উত্তর:


96

আপনার সম্ভবত সম্ভবত নিজের আইটেমগুলিতে ম্যানুয়ালি যুক্ত করা উচিত LinearLayout:

LinearLayout layout = ... // Your linear layout.
ListAdapter adapter = ... // Your adapter.

final int adapterCount = adapter.getCount();

for (int i = 0; i < adapterCount; i++) {
  View item = adapter.getView(i, null, null);
  layout.addView(item);
}

সম্পাদনা : যখন আমি প্রায় 200 অ-তুচ্ছ তালিকার আইটেমগুলি প্রদর্শন করার দরকার পড়েছিলাম তখন আমি এই পদ্ধতিটি প্রত্যাখ্যান করেছি, এটি খুব ধীর - নেক্সাস 4 আমার "তালিকা" প্রদর্শন করতে প্রায় 2 সেকেন্ডের প্রয়োজন ছিল, এটি অগ্রহণযোগ্য ছিল। সুতরাং আমি শিরোলেখগুলির সাথে ফ্লোর পদ্ধতির দিকে ফিরলাম। এটি অনেক দ্রুত কাজ করে কারণ যখন ব্যবহারকারী স্ক্রোল করে তখন ভিউ তৈরি হওয়ার সময় তালিকার ভিউগুলি চাহিদা অনুযায়ী তৈরি করা হয়।

পুনঃসূচনা: বিন্যাসে দর্শনগুলির ম্যানুয়াল সংযোজন কোড করা সহজ (সুতরাং সম্ভাব্যভাবে কম চলমান অংশ এবং বাগগুলি) তবে পারফরম্যান্স সমস্যা থেকে ভোগেন, সুতরাং আপনার যদি 50 টি মতামত বা তার বেশি পছন্দ হয় তবে আমি হেডার পদ্ধতির ব্যবহারের পরামর্শ দিই।

উদাহরণ। মূলত ক্রিয়াকলাপ (বা টুকরা) লেআউটটি এমন কিছুতে রূপান্তরিত হয় (কোনও স্ক্রোলভিউয়ের দরকার নেই):

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/my_top_layout"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"/>

তারপরে onCreateView()(আমি একটি খণ্ডের সাথে উদাহরণ ব্যবহার করব) আপনাকে একটি শিরোনাম দর্শন যোগ করতে হবে এবং তারপরে একটি অ্যাডাপ্টার সেট করতে হবে (আমি অনুমান করি শিরোনাম সংস্থান আইডিটি রয়েছে header_layout):

ListView listView = (ListView) inflater.inflate(R.layout.my_top_layout, container, false);
View header = inflater.inflate(R.layout.header_layout, null);
// Initialize your header here.
listView.addHeaderView(header, null, false);

BaseAdapter adapter = // ... Initialize your adapter.
listView.setAdapter(adapter);

// Just as a bonus - if you want to do something with your list items:
view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    // You can just use listView instead of parent casted to ListView.
    if (position >= ((ListView) parent).getHeaderViewsCount()) {
      // Note the usage of getItemAtPosition() instead of adapter's getItem() because
      // the latter does not take into account the header (which has position 0).
      Object obj = parent.getItemAtPosition(position);
      // Do something with your object.
    }
  }
});

হ্যাঁ, এটি আমার কাছে দ্বিতীয় ধারণা ছিল তবে আমি নিশ্চিত ছিলাম না ListAdapterএবং ListViewপর্দার পিছনে আরও যাদু করা হয় যা আমি নিজে নিজেই করি না।
স্টিফান হথ

অবশ্যই তালিকাভিউ কিছু জাদু করে, কমপক্ষে উপাদানগুলির মধ্যে বিভাজকগুলি, আপনাকে সেগুলি ম্যানুয়ালি যুক্ত করতে হবে, আমার ধারণা। লিস্টএডাপ্টার (যদি এটি সঠিকভাবে প্রয়োগ করা হয়) এর জন্য আর কোনও যাদু করা উচিত নয়।
ধূমপান

4
এটি আমার পক্ষে ডাউন ভোট। স্মৃতি কারও ইস্যু করে? আমরা অ্যাডাপ্টারগুলি ব্যবহার করার একটি কারণ রয়েছে ...
কেভিন পার্কার

4
অ্যাডাপ্টারের notifyDataSetChangedপদ্ধতিটি ব্যবহার করে অন্য কারও মতামত আপডেট করার ক্ষেত্রে সমস্যা আছে ? এটি আমি আলাদাভাবে অ্যাডাপ্টারের ListViewজন্য দুর্দান্ত কাজ করে তবে মনে হয় না যে আমি এটি পর্যন্ত যেটির সাথে কাজ করেছি তার সাথে এটি কাজ করছে LinearLayout
জকিফ

4
এটি অ্যান্ড্রয়েডকে ঘৃণা করার একটি কারণ। আপনাকে কেন জটিল সমাধানগুলি প্রয়োগ করতে হবে, বা কর্মক্ষমতা সমস্যার কারণে ভুগতে হবে তা আমি দেখতে পাচ্ছি না।
আইআরআই

6

আমি শিরোনাম দর্শন সমাধান দিয়ে থাকি। এটিতে কোনও ভুল নেই। এই মুহূর্তে আমি ঠিক একই পদ্ধতির ব্যবহার করে একটি ক্রিয়াকলাপ বাস্তবায়ন করছি।

স্পষ্টতই "আইটেম অংশ" স্ট্যাটিকের চেয়ে বেশি গতিশীল (আইটেম গণনা বনাম। ফিক্স আইটেম কাউন্ট ইত্যাদি) অন্যথায় আপনি কোনও অ্যাডাপ্টার ব্যবহার করার বিষয়ে ভাবেন না। সুতরাং আপনার যখন অ্যাডাপ্টারের প্রয়োজন হয় তারপরে তালিকার ভিউটি ব্যবহার করুন।

অ্যাডাপ্টার থেকে লিনিয়ারলআউটকে জনপ্রিয় করে তোলে এমন একটি সমাধান কার্যকর করা শেষ পর্যন্ত কাস্টম বিন্যাসের সাথে তালিকাভিউ নির্মাণ করা ছাড়া আর কিছুই নয়।

শুধু আমার 2 সেন্ট।


এই পদ্ধতির একটি অপূর্ণতা হ'ল আপনাকে প্রায় সম্পূর্ণ কার্যকলাপের লেআউটটিকে (উপরে দেখুন) অন্য একটি লেআউটে স্থানান্তর করতে হবে যাতে আপনি এটিকে একটি তালিকাহাইডারভিউ হিসাবে উল্লেখ করতে পারেন এবং কেবলমাত্র একটি লেআউট সহ একটি অন্য বিন্যাস তৈরি করতে পারেন ListView। নিশ্চিত না যে আমি এই প্যাচটির কাজটি পছন্দ করি।
স্টিফান হথ

4
হ্যাঁ আমি আপনাকে কী বলতে চাই তা জানি, আমি এই পদ্ধতির ব্যবহার শুরু করার আগে আমার ক্রিয়াকলাপের বিন্যাসটি একাধিক ফাইলে বিভক্ত করার ধারণাটিও আমি পছন্দ করি না। তবে যখন আমি দেখলাম যে সামগ্রিক বিন্যাসটি আমি প্রত্যাশা করেছিলাম ঠিক তেমনি এই বিচ্ছেদ সম্পর্কে কোনও আপত্তি নেই কারণ এটি কেবলমাত্র দুটি ফাইলে বিভক্ত। একটি বিষয় যা আপনাকে অবশ্যই সচেতন করতে হবে, তালিকাভিউতে অবশ্যই খালি ভিউ থাকতে হবে না কারণ কোনও তালিকার আইটেম নেই যখন এটি আপনার তালিকা শিরোনামটি আড়াল করবে।
ফ্লোর

4
এছাড়াও, আপনি যদি কোনও পৃষ্ঠায় একাধিক তালিকা রাখতে চান তবে এটি সত্যিই কাজ করে না। কারও কাছে কি কাস্টম অ্যাডাপ্টার ভিউয়ের উদাহরণ রয়েছে যা "ফ্ল্যাট" তালিকায় আইটেমগুলি আউটপুট দেয়, অর্থাত্ স্ক্রোল না করে এমন একটি।
মুরতুজা

0

আপনার দর্শনটি main.xML onCreate এ সেট করুন, তারপরে সারি.এক্সএমএল থেকে স্ফীত করুন

main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="450dp" >

        <ListView
            android:id="@+id/mainListView"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_above="@+id/size"
            android:layout_below="@+id/editText1"
            android:gravity="fill_vertical|fill_horizontal"
            android:horizontalSpacing="15dp"
            android:isScrollContainer="true"
            android:numColumns="1"
            android:padding="5dp"
            android:scrollbars="vertical"
            android:smoothScrollbar="true"
            android:stretchMode="columnWidth" >

</ListView>

    <TextView
        android:id="@+id/size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:background="#ff444444"
        android:gravity="center"
        android:text="TextView"
        android:textColor="#D3D3D3"
        android:textStyle="italic" />

    </EditText>

</RelativeLayout> 

row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent" 
  android:paddingTop="3dp">

<TextView
  android:id="@+id/rowTextView"
  android:layout_width="0dip"
  android:layout_height="41dp"
  android:layout_margin="4dp"
  android:layout_weight="2.83"
  android:ellipsize="end"
  android:gravity="center_vertical"
  android:lines="1"
  android:text="John Doe"
  android:textColor="@color/color_white"
  android:textSize="23dp" >
</TextView>

</LinearLayout>

আমার মনে হয় আপনি প্রশ্নটি বুঝতে পেরেছেন। তিনি লিনিয়ারলআউটগুলি সহ কোনও তালিকা তৈরি করতে চান না।
ফ্লো

"আমি কীভাবে একটি লিনিয়ারআলআউট বা এর অনুরূপ কোনও লিস্টএডাপ্টারকে সংযুক্ত করব?" শুধু উত্তর কি ওপি জিজ্ঞাসা
fasheikh

4
না তিনি কোনও তালিকাভিউ ব্যবহার করতে চান না। তিনি কেবল একটি অ্যাডাপ্টার ব্যবহার করতে চান এবং এন্ট্রি সহ লিনিয়ারলআউটকে জনপ্রিয় করতে ব্যবহার করতে চান।
ফ্লো

আপনার উত্তরের জন্য ধন্যবাদ তবে @ ফ্লো সঠিক। আমি একটি তালিকাভিউ ব্যবহার করতে পারি না কারণ বাহ্যিক বিন্যাসটি ইতিমধ্যে একটি স্ক্রোলভিউ। আমার পাঠ্য এবং নমুনা বিন্যাস পরীক্ষা করুন।
স্টিফান হোথ

কেন এই স্ক্রোলভিউ প্রয়োজন?
ফারশেখ

0

আমি নিম্নলিখিত কোডগুলি ব্যবহার করি যা অ্যাডাপ্টারের কার্যকারিতা ViewGroupএবং এর সাথে প্রতিলিপি করে TabLayout। এ সম্পর্কে ভাল বিষয় হ'ল আপনি যদি নিজের তালিকাকে পরিবর্তন করে আবার বাঁধেন তবে এটি কেবল পরিবর্তিত আইটেমগুলিকেই প্রভাবিত করবে:

ব্যবহার:

val list = mutableListOf<Person>()
layout.bindChildren(list, { it.personId }, { bindView(it) }, {d, t ->bindView(d, t)})
list.removeAt(0)
list+=newPerson
layout.bindChildren(list, { it.personId }, { bindView(it) }, {d, t ->bindView(d, t)})

এর জন্য ViewGroups:

fun <Item, Key> ViewGroup.bindChildren(items: List<Item>, id: (Item) -> Key, view: (Item) -> View, bind: (Item, View) -> Unit) {
    val old = children.map { it.tag as Key }.toList().filter { it != null }
    val new = items.map(id)

    val add = new - old
    val remove = old - new
    val keep = new.intersect(old)

    val tagToChildren = children.associateBy { it.tag as Key }
    val idToItem = items.associateBy(id)

    remove.forEach { tagToChildren[it].let { removeView(it) } }
    keep.forEach { bind(idToItem[it]!!, tagToChildren[it]!!) }
    add.forEach { id -> view(idToItem[id]!!).also { it.tag = id }.also { addView(it, items.indexOf(idToItem[id])) } }
}

কারণ TabLayoutআমার কাছে এটি রয়েছে:

fun <Item, Key> TabLayout.bindTabs(items: List<Item>, toKey: (Item) -> Key, tab: (Item) -> TabLayout.Tab, bind: (Item, TabLayout.Tab) -> Unit) {
    val old = (0 until tabCount).map { getTabAt(it)?.tag as Key }
    val new = items.map(toKey)

    val add = new - old
    val remove = old - new
    val keep = new.intersect(old)

    val tagToChildren = (0 until tabCount).map { getTabAt(it) }.associateBy { it?.tag as Key }
    val idToItem = items.associateBy(toKey)

    remove.forEach { tagToChildren[it].let { removeTab(it) } }
    keep.forEach { bind(idToItem[it]!!, tagToChildren[it]!!) }
    add.forEach { key -> tab(idToItem[key]!!).also { it.tag = key }.also { addTab(it, items.indexOf(idToItem[key])) } }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.