প্রতিটি সারির জন্য বিভিন্ন লেআউট সহ অ্যান্ড্রয়েড তালিকাভিউ


348

আমি একক তালিকাভিউ রাখার সর্বোত্তম উপায়টি নির্ধারণ করার চেষ্টা করছি যাতে প্রতিটি সারির জন্য আলাদা লেআউট থাকে। আমি জানি কিভাবে পুরো তালিকা দেখার জন্য কাস্টম সারিটি সমর্থন করতে একটি কাস্টম সারি + কাস্টম অ্যারে অ্যাডাপ্টার তৈরি করতে হয় তবে আমি কীভাবে তালিকাভিউতে বিভিন্ন সারি শৈলীর প্রয়োগ করতে পারি?


1
আপডেট: অ্যান্ড্রয়েডের রিসাইক্লারভিউ কোড 2 কনসেপ্ট.ব্লগস্পট.ইন
2015/10

উত্তর:


413

যেহেতু আপনি জানেন যে আপনার কত ধরণের লেআউট থাকবে - এই পদ্ধতিগুলি ব্যবহার করা সম্ভব।

getViewTypeCount() - এই পদ্ধতিগুলি আপনার তালিকায় কত ধরণের সারি রয়েছে তা তথ্য ফিরিয়ে দেয়

getItemViewType(int position) - অবস্থানের ভিত্তিতে আপনার কোন লেআউট প্রকারটি ব্যবহার করা উচিত তা তথ্য প্রদান করে

তারপরে আপনি লেআউটটি স্ফূরণ করবেন কেবল যদি এটি নাল হয় এবং প্রকারটি ব্যবহার করে নির্ধারণ করে getItemViewType

আরও তথ্যের জন্য এই টিউটোরিয়ালটি দেখুন ।

আপনি মন্তব্যে বর্ণিত কাঠামোর কিছু অপ্টিমাইজেশন অর্জনের জন্য আমি পরামর্শ দেব:

  • অবজেক্টে ভিউ সংরক্ষণ করা হয় ViewHolder। এটি গতি বাড়িয়ে তুলবে কারণ পদ্ধতিতে আপনাকে findViewById()প্রতিবার কল করতে হবে না getViewএপিআই ডেমোতে তালিকা 14 দেখুন ।
  • একটি জেনেরিক লেআউট তৈরি করুন যা বৈশিষ্ট্যের সমস্ত সংমিশ্রণ মেনে চলবে এবং বর্তমান অবস্থানে না থাকলে কিছু উপাদান আড়াল করবে।

আমি আশা করি যে আপনাকে সাহায্য করবে। আপনি যদি নিজের ডাটা স্ট্রাকচার এবং তথ্যটি কীভাবে সারণিতে ম্যাপ করতে চান তার সাথে কিছু এক্সএমএল স্টাব সরবরাহ করতে পারত, তবে আমি আপনাকে আরও সুনির্দিষ্ট পরামর্শ দিতে সক্ষম হব। পিক্সেল দ্বারা


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

2
আবার এটি খনন করার জন্য দুঃখিত, তবে আপনি আসলে একটি একক বৃহত লেআউট ফাইল রাখার এবং এর অংশগুলির দৃশ্যমানতা নিয়ন্ত্রণ করার পরিবর্তে পৃথক বিন্যাস ফাইল রাখার পরামর্শ দিবেন, যা getItemViewType ব্যবহার করে যথাক্রমে স্ফীত হয়?
মাকিবো

2
আপনি এটি করতে পারেন। যদিও আমি এখনও এখানে উন্মুক্ত উপায় পছন্দ। আপনি কী অর্জন করতে চান তা এটি পরিষ্কার করে দেয়।
ক্রিশ্চিয়ান

তবে একাধিক বিন্যাস কৌশলটিতে আমরা ব্যবহারকারীকে সঠিকভাবে দেখতে পারি না কারণ সেটট্যাগে কেবলমাত্র একটি ভিউ হোল্ডার থাকতে পারে এবং যখনই আবার সারি বিন্যাসটি স্যুইচ করে তখন আমাদের ফাইন্ড ভিউআইআইডি () কল করতে হবে। যা তালিকার দৃষ্টিভঙ্গিটিকে খুব কম সম্পাদন করে makes আমি ব্যক্তিগতভাবে এটি অভিজ্ঞ আপনার উপর এটি পরামর্শ কি?
পাইস 13

@ পাইস 13 আপনি একক দর্শন ধারক হিসাবে আপনি যতটা ভিউ চান হিসাবে ঘোষণা করতে পারেন এবং ভিউ ধারক হিসাবে ঘোষিত প্রতিটি দর্শন ব্যবহার করা প্রয়োজন হয় না। যদি কোনও নমুনা কোডের প্রয়োজন হয় তবে দয়া করে আমাকে জানান, আমি এটি পোস্ট করব।
আহমদ আলী নাসির

62

পুরো তালিকা দেখার জন্য কাস্টম সারিটি সমর্থন করার জন্য কীভাবে একটি কাস্টম সারি + কাস্টম অ্যারে অ্যাডাপ্টার তৈরি করতে হয় তা আমি জানি। তবে কীভাবে একটি তালিকা ভিউ বিভিন্ন সারির শৈলীর সমর্থন করতে পারে?

আপনি ইতিমধ্যে বেসিকগুলি জানেন। সারি / কার্সারের তথ্যের উপর ভিত্তি করে আলাদা লেআউট / ভিউ ফেরত পেতে আপনার কাস্টম অ্যাডাপ্টারটি পেতে হবে।

একটি ListViewকারণ এটি থেকে আহরিত একাধিক সারি শৈলী সমর্থন করতে পারে না AdapterView :

একটি অ্যাডাপ্টারভিউ এমন একটি দৃশ্য যাঁর শিশুরা কোনও অ্যাডাপ্টারের দ্বারা নির্ধারিত হয়।

আপনি যদি অ্যাডাপ্টারের দিকে তাকান , আপনি সারণ-নির্দিষ্ট দর্শনগুলি ব্যবহারের জন্য অ্যাকাউন্টগুলি এমন পদ্ধতিগুলি দেখতে পাবেন:

abstract int getViewTypeCount()
// Returns the number of types of Views that will be created ...

abstract int getItemViewType(int position)
// Get the type of View that will be created ...

abstract View getView(int position, View convertView, ViewGroup parent)
// Get a View that displays the data ...

পরবর্তী দুটি পদ্ধতি অবস্থান সরবরাহ করে যাতে আপনি এই সারিটির জন্য আপনার কী ধরণের ব্যবহার করা উচিত তা নির্ধারণ করতে এটি ব্যবহার করতে পারেন ।


অবশ্যই, আপনি সাধারণত অ্যাডাপ্টারভিউ এবং অ্যাডাপ্টার সরাসরি ব্যবহার করেন না, বরং তাদের সাবক্লাসগুলির মধ্যে একটি থেকে ব্যবহার বা প্রাপ্ত হন। অ্যাডাপ্টারের সাবক্লাসগুলি অতিরিক্ত কার্যকারিতা যুক্ত করতে পারে যা বিভিন্ন সারিগুলির জন্য কাস্টম লেআউটগুলি কীভাবে পাবেন তা পরিবর্তন করে। যেহেতু প্রদত্ত সারির জন্য ব্যবহৃত ভিউ অ্যাডাপ্টার দ্বারা চালিত হয়, কৌশলটি হ'ল অ্যাডাপ্টারকে প্রদত্ত সারির জন্য পছন্দসই দৃশ্যটি ফিরিয়ে আনতে হবে। এটি কীভাবে করবেন তা নির্দিষ্ট অ্যাডাপ্টারের উপর নির্ভর করে পৃথক।

উদাহরণস্বরূপ, অ্যারেএডাপ্টার ব্যবহার করতে ,

  • getView()প্রদত্ত অবস্থানের জন্য কাঙ্ক্ষিত দৃশ্যকে স্ফীত করতে, পপুলেট করতে এবং ফিরে পেতে ওভাররাইড করুন । getView()পদ্ধতির মাধ্যমে মতামত পুনঃব্যবহারের একটি সুযোগ রয়েছে convertViewপ্যারামিটার।

তবে কার্সরএডাপ্টারের ডেরিভেটিভগুলি ব্যবহার করতে ,

  • ওভাররাইড newView(), ফোলান উল্লেখ করুন ও বর্তমান কার্সার রাষ্ট্র জন্য পছন্দসই দৃশ্য (অর্থাত বর্তমান "সারি") ফিরে যাওয়ার [আপনার কাছে ওভাররাইড করতে প্রয়োজন bindViewযাতে উইজেট মতামত পুনরায় ব্যবহার করতে পারেন]

তবে সিম্পল কার্সর অ্যাডাপ্টার ব্যবহার করতে ,

  • প্রদত্ত সারি (বর্তমান কার্সার অবস্থা) এবং ডেটা "কলাম" এর জন্য কাঙ্ক্ষিত ভিউটি স্ফীত করতে, পপুলেট করতে এবং প্রত্যাবর্তনের জন্য SimpleCursorAdapter.ViewBinderএকটি setViewValue()পদ্ধতির সাথে সংজ্ঞা দিন । পদ্ধতিটি কেবল "বিশেষ" দর্শনগুলি সংজ্ঞায়িত করতে পারে এবং "সাধারণ" বাইন্ডিংয়ের জন্য সিম্পল কার্সার অ্যাডাপ্টারের মানক আচরণকে স্থগিত করতে পারে।

আপনি যে ধরণের অ্যাডাপ্টারটি ব্যবহার করে শেষ করেন তার জন্য নির্দিষ্ট উদাহরণ / টিউটোরিয়াল সন্ধান করুন।


অ্যাডাপ্টারের নমনীয় বাস্তবায়নের জন্য কোন অ্যাডাপ্টারের ধরণের কোনও ধারণা সবচেয়ে ভাল? আমি এর জন্য বোর্ডে আরও একটি প্রশ্ন যুক্ত করছি।
অ্যান্ড্রয়েডার

1
@ অ্যান্ড্রয়েডার - "নমনীয় জন্য সেরা" খুব উন্মুক্ত - এখানে কোনও শেষ নেই, সর্বব্যাপী শ্রেণি যা প্রতিটি চাহিদা পূরণ করবে; এটি একটি সমৃদ্ধ শ্রেণিবিন্যাস - এটি আপনার উদ্দেশ্যে কার্যকর যে সাবক্লাসে কার্যকারিতা রয়েছে কিনা তা নীচে নেমে আসে। যদি তা হয় তবে সেই সাবক্লাস দিয়ে শুরু করুন; যদি না হয়, উপরে যান BaseAdapter। বেসএডাপ্টার থেকে ডেরাইভিং সর্বাধিক "নমনীয়" হবে তবে কোড পুনরায় ব্যবহার এবং পরিপক্কতার ক্ষেত্রে এটি সবচেয়ে খারাপ হবে কারণ এটি ইতিমধ্যে অন্যান্য অ্যাডাপ্টারে অন্তর্ভুক্ত জ্ঞান এবং পরিপক্কতার সুযোগ নেয় না। BaseAdapterঅ-মানক প্রসঙ্গে যেখানে অন্যান্য অ্যাডাপ্টারগুলি ফিট করে না।
বার্ট এফ

3
মধ্যে জরিমানা পার্থক্য জন্য +1 CursorAdapterএবং SimpleCursorAdapter
জিউলিও পিয়ানোস্টেলি

1
এছাড়াও লক্ষ্য করুন যে আপনি যদি ওভাররাইড ArrayAdapterকরে থাকেন তবে আপনি কনস্ট্রাক্টরটিকে কোন লেআউট দেবেন তাতে কিছু যায় আসে না, যতক্ষণ না getView()
ইনফ্লেট করে

1
এটি লক্ষ করা উচিত যে getViewTypeCount()আপনি একবার কল করলে ListView.setAdapter()প্রতিবারের জন্য একবারেই ট্রিগার হয় Adapter.notifyDataSetChanged()
হিদ্রো

43

নীচের কোডে একবার দেখুন।

প্রথমত, আমরা কাস্টম লেআউটগুলি তৈরি করি। এই ক্ষেত্রে, চার ধরণের।

even.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ff500000"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/white"
        android:layout_width="match_parent"
        android:layout_gravity="center"
        android:textSize="24sp"
        android:layout_height="wrap_content" />

 </LinearLayout>

odd.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ff001f50"
    android:gravity="right"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/white"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="28sp"
        android:layout_height="wrap_content"  />

 </LinearLayout>

white.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ffffffff"
    android:gravity="right"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/black"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="28sp"
        android:layout_height="wrap_content"   />

 </LinearLayout>

black.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#ff000000"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/text"
        android:textColor="@android:color/white"
        android:layout_width="wrap_content"
        android:layout_gravity="center"
        android:textSize="33sp"
        android:layout_height="wrap_content"   />

 </LinearLayout>

তারপরে, আমরা তালিকার আইটেমটি তৈরি করি। আমাদের ক্ষেত্রে, একটি স্ট্রিং এবং একটি প্রকারের সাথে।

public class ListViewItem {
        private String text;
        private int type;

        public ListViewItem(String text, int type) {
            this.text = text;
            this.type = type;
        }

        public String getText() {
            return text;
        }

        public void setText(String text) {
            this.text = text;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

    }

এর পরে, আমরা একটি ভিউ ধারক তৈরি করি। এটি দৃ strongly়ভাবে সুপারিশ করা হয়েছে কারণ অ্যান্ড্রয়েড ওএস আপনার আইটেমটি অদৃশ্য হয়ে যায় এবং যখন এটি স্ক্রিনে ফিরে আসে তখন পুনরায় ব্যবহার করার জন্য বিন্যাসের রেফারেন্স রাখে। আপনি যদি এই পদ্ধতির ব্যবহার না করেন তবে আপনার আইটেমটি স্ক্রিন অ্যান্ড্রয়েড ওএসে প্রদর্শিত হবে এমন প্রতিটি সময়ই একটি নতুন তৈরি করবে এবং আপনার অ্যাপ্লিকেশনটিকে মেমরি ফাঁস করবে।

public class ViewHolder {
        TextView text;

        public ViewHolder(TextView text) {
            this.text = text;
        }

        public TextView getText() {
            return text;
        }

        public void setText(TextView text) {
            this.text = text;
        }

    }

অবশেষে, আমরা আমাদের কাস্টম অ্যাডাপ্টারের ওভাররাইডিং ভিভটাইপ টাইপকাউন্ট () এবং গেটআইটেমটাইপ টাইপ (ইন পজিশন) তৈরি করি।

public class CustomAdapter extends ArrayAdapter {

        public static final int TYPE_ODD = 0;
        public static final int TYPE_EVEN = 1;
        public static final int TYPE_WHITE = 2;
        public static final int TYPE_BLACK = 3;

        private ListViewItem[] objects;

        @Override
        public int getViewTypeCount() {
            return 4;
        }

        @Override
        public int getItemViewType(int position) {
            return objects[position].getType();
        }

        public CustomAdapter(Context context, int resource, ListViewItem[] objects) {
            super(context, resource, objects);
            this.objects = objects;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            ViewHolder viewHolder = null;
            ListViewItem listViewItem = objects[position];
            int listViewItemType = getItemViewType(position);


            if (convertView == null) {

                if (listViewItemType == TYPE_EVEN) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_even, null);
                } else if (listViewItemType == TYPE_ODD) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_odd, null);
                } else if (listViewItemType == TYPE_WHITE) {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_white, null);
                } else {
                    convertView = LayoutInflater.from(getContext()).inflate(R.layout.type_black, null);
                }

                TextView textView = (TextView) convertView.findViewById(R.id.text);
                viewHolder = new ViewHolder(textView);

                convertView.setTag(viewHolder);

            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            viewHolder.getText().setText(listViewItem.getText());

            return convertView;
        }

    }

এবং আমাদের ক্রিয়াকলাপটি এরকম কিছু:

private ListView listView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main); // here, you can create a single layout with a listview

        listView = (ListView) findViewById(R.id.listview);

        final ListViewItem[] items = new ListViewItem[40];

        for (int i = 0; i < items.length; i++) {
            if (i == 4) {
                items[i] = new ListViewItem("White " + i, CustomAdapter.TYPE_WHITE);
            } else if (i == 9) {
                items[i] = new ListViewItem("Black " + i, CustomAdapter.TYPE_BLACK);
            } else if (i % 2 == 0) {
                items[i] = new ListViewItem("EVEN " + i, CustomAdapter.TYPE_EVEN);
            } else {
                items[i] = new ListViewItem("ODD " + i, CustomAdapter.TYPE_ODD);
            }
        }

        CustomAdapter customAdapter = new CustomAdapter(this, R.id.text, items);
        listView.setAdapter(customAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView adapterView, View view, int i, long l) {
                Toast.makeText(getBaseContext(), items[i].getText(), Toast.LENGTH_SHORT).show();
            }
        });

    }
}

এখন এর মতো mainactivity.xml এর ভিতরে একটি তালিকা ভিউ তৈরি করুন

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.shivnandan.gygy.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <ListView
        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:id="@+id/listView"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"


        android:layout_marginTop="100dp" />

</android.support.design.widget.CoordinatorLayout>

<লেআউটটি অন্তর্ভুক্ত করুন = "@ লেআউট / সামগ্রী_মিনে" /> এটি কোথা থেকে আসছে
nyxee

আমার কেবল (রূপান্তর ভিউ == নাল) ধারা প্রয়োজন। কোনও 'ভিউহোল্ডার' দরকার নেই
জোম্মে

14

আপনার কাস্টম অ্যারে অ্যাডাপ্টারে আপনি সম্ভবত ভিউ () পদ্ধতিটি ওভাররাইড করবেন with তারপরে আপনাকে যা করতে হবে তা হ'ল ভিউ পদ্ধতিতে পাস হওয়া অবস্থানের আর্গুমেন্টের উপর নির্ভর করে একটি নির্দিষ্ট কাস্টম ভিউ ফেরত দিতে একটি স্যুইচ স্টেটমেন্ট বা একটি বিবৃতি ব্যবহার করতে হবে। অ্যান্ড্রয়েড এতে চালাক যে এটি আপনাকে কেবল আপনার অবস্থান / সারিটির জন্য উপযুক্ত ধরণের রূপান্তর ভিউ দেবে; আপনার এটি পরীক্ষা করার দরকার নেই সঠিক ধরণের। আপনি getItemViewType () এবং getViewTypeCount () পদ্ধতিগুলিকে যথাযথভাবে ওভাররাইড করে এর সাথে অ্যান্ড্রয়েডকে সহায়তা করতে পারেন।


4

যদি আমাদের তালিকা-ভিউতে বিভিন্ন ধরণের ভিউ দেখাতে হয় তবে ভিউ ভিউ.জোন এবং দেখুন দেখুন টগল করার পরিবর্তে অ্যাডাপ্টারে getViewTypeCount () এবং getItemViewType () ব্যবহার করা ভাল get তালিকা স্ক্রোল প্রভাবিত।

অ্যাডাপ্টারে getViewTypeCount () এবং getItemViewType () ব্যবহারের জন্য দয়া করে এটি পরীক্ষা করুন।

লিঙ্ক: -র-ব্যবহার -র-ভিউ-ভিটিপ্যাক্ট


1

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

আপনি যা যা খুঁজছেন তা করতে পুনর্ব্যবহারযোগ্য ভিউ কীভাবে ব্যবহার করতে হয় তার এই টিউটোরিয়ালটি দেখুন ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.