রিসাইক্লারভিউ গ্রিডলাউটম্যানেজার: স্প্যান গণনাটি কীভাবে স্বয়ংক্রিয়ভাবে সনাক্ত করা যায়?


110

নতুন গ্রিডলয়েটম্যানেজার ব্যবহার করুন: https://developer.android.com/references/android/support/v7/widget/GridLayoutManager.html

এটি একটি স্প্যান স্প্যান গণনা লাগে, সুতরাং সমস্যাটি এখন পরিণত হয়: আপনি কীভাবে জানবেন যে প্রতি সারিতে কত "স্প্যান" ফিট? এটি একটি গ্রিড, সর্বোপরি। পরিমাপ করা প্রস্থের উপর নির্ভর করে রিসাইক্লারভিউ যতটা ফিট করতে পারে তত স্প্যান থাকা উচিত।

GridViewপুরানোটি ব্যবহার করে আপনি কেবল "কলামউইথ" সম্পত্তি সেট করবেন এবং এটি স্বয়ংক্রিয়ভাবে সনাক্ত করতে পারে যে কয়টি কলামগুলি ফিট। এটিই মূলত আমি রিসাইক্লারভিউয়ের জন্য অনুলিপি করতে চাই:

  • onLayoutChangeListener যুক্ত করুন RecyclerView
  • এই কলব্যাকে, একটি একক 'গ্রিড আইটেম' স্ফীত করুন এবং এটি পরিমাপ করুন
  • স্প্যানকাউন্ট = রিসাইক্লারভিউউইথ / একক আইটেমউইথ;

এটি দেখতে বেশ সাধারণ ব্যবহারের মতো বলে মনে হচ্ছে, তাহলে কি এমন সহজ উপায় আছে যা আমি দেখছি না?

উত্তর:


122

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

public class GridAutofitLayoutManager extends GridLayoutManager
{
    private int columnWidth;
    private boolean isColumnWidthChanged = true;
    private int lastWidth;
    private int lastHeight;

    public GridAutofitLayoutManager(@NonNull final Context context, final int columnWidth) {
        /* Initially set spanCount to 1, will be changed automatically later. */
        super(context, 1);
        setColumnWidth(checkedColumnWidth(context, columnWidth));
    }

    public GridAutofitLayoutManager(
        @NonNull final Context context,
        final int columnWidth,
        final int orientation,
        final boolean reverseLayout) {

        /* Initially set spanCount to 1, will be changed automatically later. */
        super(context, 1, orientation, reverseLayout);
        setColumnWidth(checkedColumnWidth(context, columnWidth));
    }

    private int checkedColumnWidth(@NonNull final Context context, final int columnWidth) {
        if (columnWidth <= 0) {
            /* Set default columnWidth value (48dp here). It is better to move this constant
            to static constant on top, but we need context to convert it to dp, so can't really
            do so. */
            columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
                    context.getResources().getDisplayMetrics());
        }
        return columnWidth;
    }

    public void setColumnWidth(final int newColumnWidth) {
        if (newColumnWidth > 0 && newColumnWidth != columnWidth) {
            columnWidth = newColumnWidth;
            isColumnWidthChanged = true;
        }
    }

    @Override
    public void onLayoutChildren(@NonNull final RecyclerView.Recycler recycler, @NonNull final RecyclerView.State state) {
        final int width = getWidth();
        final int height = getHeight();
        if (columnWidth > 0 && width > 0 && height > 0 && (isColumnWidthChanged || lastWidth != width || lastHeight != height)) {
            final int totalSpace;
            if (getOrientation() == VERTICAL) {
                totalSpace = width - getPaddingRight() - getPaddingLeft();
            } else {
                totalSpace = height - getPaddingTop() - getPaddingBottom();
            }
            final int spanCount = Math.max(1, totalSpace / columnWidth);
            setSpanCount(spanCount);
            isColumnWidthChanged = false;
        }
        lastWidth = width;
        lastHeight = height;
        super.onLayoutChildren(recycler, state);
    }
}

আমি আসলেই মনে করি না কেন আমি লেআউটচিল্ডারে স্প্যান গণনা সেট করতে বেছে নিয়েছিলাম, আমি এই ক্লাসটি কিছুদিন আগে লিখেছিলাম। তবে মুল বক্তব্যটি পরিমাপ করার পরে আমাদের তা করা দরকার। যাতে আমরা এটির উচ্চতা এবং প্রস্থ পেতে পারি।

সম্পাদনা 1: ভুলভাবে স্প্যান গণনা সেট করার কারণে কোডে ত্রুটি ঠিক করা। ব্যবহারকারী এলিইস আবৌডাকে ধন্যবাদ জানানোর জন্য এবং সমাধানটির পরামর্শ দেওয়ার জন্য ।

সম্পাদনা 2: ম্যানুয়াল ওরিয়েন্টেশন হ্যান্ডলিংয়ের সাথে কিছু ছোট রিফ্যাক্টরিং এবং ফিক্স এজ প্রান্ত। ব্যবহারকারীকে ধন্যবাদ এবং রিপোর্টটি সমাধানের পরামর্শ দেওয়ার জন্য @tatarize


8
এই গৃহীত উত্তর হওয়া উচিত, এটা LayoutManagerএর আউট শিশুদের রাখা এবং কাজ না RecyclerViews 'এর
mewa

3
@ এস.ম্যাকস: মানে অ্যাডাপ্টারে পাস করা ডেটার উপর নির্ভর করে কলামউইথ পৃথক হবে th বলুন, যদি চারটি অক্ষরের শব্দ পাস করা হয় তবে এটির ক্ষেত্রে একটানা চারটি আইটেমের সমন্বয় করা উচিত যদি 10 বর্ণের শব্দের সাথে পাস করা হয় তবে এটি একটি সারিতে কেবল 2 টি আইটেম সংযোজন করতে সক্ষম হওয়া উচিত।
শুভ

2
আমার জন্য, ডিভাইসটি ঘোরানোর সময়, এটি 20 ডিপি সঙ্কুচিত করে গ্রিডের আকারটি কিছুটা পরিবর্তন করছে। এই সম্পর্কে কোন তথ্য আছে? ধন্যবাদ।
আলেকজান্দ্রে

3
ভিউ তৈরি হওয়ার আগে কখনও কখনও getWidth()বা getHeight()0 হয়, যা একটি ভুল স্প্যানকাউন্ট পাবে (যেহেতু মোট স্পেসটি <= 0)। আমি যা যুক্ত করেছি তা এই ক্ষেত্রে সেটস্প্যান অ্যাকাউন্টকে উপেক্ষা করছে। ( onLayoutChildrenপরে আবার বলা হবে)
এলিস আবৌদা

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

29

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

mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(
            new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    mRecyclerView.getViewTreeObserver().removeOnGLobalLayoutListener(this);
                    int viewWidth = mRecyclerView.getMeasuredWidth();
                    float cardViewWidth = getActivity().getResources().getDimension(R.dimen.cardview_layout_width);
                    int newSpanCount = (int) Math.floor(viewWidth / cardViewWidth);
                    mLayoutManager.setSpanCount(newSpanCount);
                    mLayoutManager.requestLayout();
                }
            });

2
আমি এই ব্যবহার করা হয় এবং পেয়েছিলাম ArrayIndexOutOfBoundsException( android.support.v7.widget.GridLayoutManager.layoutChunk (GridLayoutManager.java:361) এ ) যখন স্ক্রলিং RecyclerView
fikr4n

সেটস্প্যানকাউন্ট () এর পরে এমএলআউটআমনেজ.আরকোয়েস্টলয়আউট () যুক্ত করুন এবং এটি কাজ করে
alvinmeimoun

2
দ্রষ্টব্য: removeGlobalOnLayoutListener()এপিআই লেভেল 16 এ অবচয় করা হয়েছে removeOnGlobalLayoutListener()instead পরিবর্তে ব্যবহার করুন। ডকুমেন্টেশন
পেজ

টাইপ অপসারণ ওএনজিওবালালআউটলাইস্টেনার সরানো উচিতঅ্যানগ্লোবাল লেআউটলিস্টনার
থিও

17

ঠিক আছে, এটি আমি ব্যবহার করেছি, মোটামুটি বেসিক, তবে আমার জন্য কাজটি হয়ে যায়। এই কোডটি মূলত স্ক্রিনের প্রস্থকে ডিপসে দেয় এবং তারপরে 300 দিয়ে বিভক্ত হয় (বা আপনি আপনার অ্যাডাপ্টারের বিন্যাসের জন্য যে প্রস্থটি ব্যবহার করছেন)। 300-500 ডিপ প্রস্থ সহ ছোট ফোনগুলি কেবলমাত্র একটি কলাম, ট্যাবলেটগুলি 2-3 কলামগুলি প্রদর্শন করে Simple

Display display = getActivity().getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);

float density  = getResources().getDisplayMetrics().density;
float dpWidth  = outMetrics.widthPixels / density;
int columns = Math.round(dpWidth/300);
mLayoutManager = new GridLayoutManager(getActivity(),columns);
mRecyclerView.setLayoutManager(mLayoutManager);

1
কেন রিসাইক্লিউউ'র প্রস্থের পরিবর্তে পর্দার প্রস্থ ব্যবহার করবেন? এবং হার্ডকোডিং 300 খারাপ অভ্যাস (এটি আপনার এক্সএমএল লেআউটের সাথে সুসংগত রাখা প্রয়োজন)
foo64

@ foo64 xML এ আপনি কেবল আইটেমটিতে ম্যাচ_পিতা সেট করতে পারেন। তবে হ্যাঁ, এটি এখনও কুরুচিপূর্ণ;)
ফিলিপ গিউলিয়ানী

15

আমি রিসাইক্লার ভিউ প্রসারিত করেছি এবং onMeasure পদ্ধতিতে ওভাররড করেছি।

আমি 1 এর ডিফল্ট দিয়ে যত তাড়াতাড়ি সম্ভব আইটেমের প্রস্থ (সদস্য ভেরিয়েবল) সেট করেছি configuration এটি কনফিগারেশনের আপডেটও পরিবর্তন হয়েছে। এতে এখন পোর্ট্রেট, ল্যান্ডস্কেপ, ফোন / ট্যাবলেট ইত্যাদিতে যতগুলি সারি লাগানো যাবে will

@Override
protected void onMeasure(int widthSpec, int heightSpec) {
    super.onMeasure(widthSpec, heightSpec);
    int width = MeasureSpec.getSize(widthSpec);
    if(width != 0){
        int spans = width / mItemWidth;
        if(spans > 0){
            mLayoutManager.setSpanCount(spans);
        }
    }
}

12
+1 চিউ-কি চানের একটি ব্লগ পোস্ট রয়েছে যা এই পদ্ধতির রূপরেখা এবং এটির জন্য একটি নমুনা প্রকল্পও রয়েছে
কমন্সওয়্যার

7

আমার ক্ষেত্রে যেমন কেউ অদ্ভুত কলামের প্রস্থ পান তখনই আমি এটি পোস্ট করছি।

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

private int checkedColumnWidth(Context context, int columnWidth)
{
    if (columnWidth <= 0)
    {
        /* Set default columnWidth value (48dp here). It is better to move this constant
        to static constant on top, but we need context to convert it to dp, so can't really
        do so. */
        columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
                context.getResources().getDisplayMetrics());
    }

    else
    {
        columnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, columnWidth,
                context.getResources().getDisplayMetrics());
    }
    return columnWidth;
}

প্রদত্ত কলামের প্রস্থকে ডিপিতে রূপান্তরিত করে সমস্যাটি স্থির করে।


2

এস-চিহ্নের উত্তরে ওরিয়েন্টেশন পরিবর্তনের জন্য , আমি প্রস্থ পরিবর্তনের উপর একটি চেক যুক্ত করেছি (getWidth থেকে প্রস্থ () কলামের প্রশস্ততা নয়)।

private boolean mWidthChanged = true;
private int mWidth;


@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)
{
    int width = getWidth();
    int height = getHeight();

    if (width != mWidth) {
        mWidthChanged = true;
        mWidth = width;
    }

    if (mColumnWidthChanged && mColumnWidth > 0 && width > 0 && height > 0
            || mWidthChanged)
    {
        int totalSpace;
        if (getOrientation() == VERTICAL)
        {
            totalSpace = width - getPaddingRight() - getPaddingLeft();
        }
        else
        {
            totalSpace = height - getPaddingTop() - getPaddingBottom();
        }
        int spanCount = Math.max(1, totalSpace / mColumnWidth);
        setSpanCount(spanCount);
        mColumnWidthChanged = false;
        mWidthChanged = false;
    }
    super.onLayoutChildren(recycler, state);
}

2

আপভোডেড সমাধানটি ভাল, তবে আগত মানগুলিকে পিক্সেল হিসাবে পরিচালনা করে, যা আপনি ডিপি পরীক্ষার জন্য এবং ধরে নেওয়ার জন্য হার্ডকোডিং করছেন যদি আপনাকে ট্রিপ করতে পারে। গ্রিডআউটফিটলআউটআউট ম্যানেজারটি কনফিগার করার সময় কলামের প্রস্থকে একটি মাত্রায় রাখা এবং এটি পড়ার সম্ভবত সহজ উপায় হ'ল ডিপিকে স্বয়ংক্রিয়ভাবে পিক্সেলের মানকে রূপান্তর করবে:

new GridAutofitLayoutManager(getActivity(), (int)getActivity().getResources().getDimension(R.dimen.card_width))

হ্যাঁ, এটি আমাকে লুপের জন্য ফেলেছিল। সত্যিই এটি কেবল উত্স নিজেই গ্রহণ করা হবে। আমি বোঝাতে চাইছি এটি আমরা যা করবো তা সর্বদাই।
টাটারাইজ

2
  1. ইমেজভিউর ন্যূনতম স্থির প্রস্থ সেট করুন (উদাহরণস্বরূপ 144 ডিপি x 144dp)
  2. আপনি গ্রিডলআউটআউট ম্যানেজারটি তৈরি করার সময়, আপনার ন্যূনতম আকারের চিত্রের সাথে কতগুলি কলাম হবে তা জানতে হবে:

    WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE); //Получаем размер экрана
    Display display = wm.getDefaultDisplay();
    
    Point point = new Point();
    display.getSize(point);
    int screenWidth = point.x; //Ширина экрана
    
    int photoWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 144, this.getResources().getDisplayMetrics()); //Переводим в точки
    
    int columnsCount = screenWidth/photoWidth; //Число столбцов
    
    GridLayoutManager gridLayoutManager = new GridLayoutManager(this, columnsCount);
    recyclerView.setLayoutManager(gridLayoutManager);
  3. এর পরে আপনার যদি কলামে স্থান থাকে তবে আপনাকে অ্যাডাপ্টারে চিত্রের ভিউটির আকার পরিবর্তন করতে হবে। আপনি নতুন আইজামভিউসাইজ পাঠাতে পারেন তবে সেখানে স্ক্রিন এবং কলামের গণনা গণনা করে ক্রিয়াকলাপ থেকে অ্যাডাপ্টারটি ইনসিলাইজ করতে পারেন:

    @Override //Заполнение нашей плитки
    public void onBindViewHolder(PhotoHolder holder, int position) {
       ...
       ViewGroup.LayoutParams photoParams = holder.photo.getLayoutParams(); //Параметры нашей фотографии
    
       int newImageViewSize = screenWidth/columnsCount; //Новый размер фотографии
    
       photoParams.width = newImageViewSize; //Установка нового размера
       photoParams.height = newImageViewSize;
       holder.photo.setLayoutParams(photoParams); //Установка параметров
       ...
    }

এটি উভয় অভিযোজনে কাজ করে। উল্লম্বভাবে আমার 2 টি কলাম এবং অনুভূমিক - 4 কলাম রয়েছে। ফলাফল: https://i.stack.imgur.com/WHvyD.jpg



1

রিসাইক্লারভিউ নিজেই আকার পরিবর্তন করার জন্য এটি একটি সামান্য ফিক্স সহ s.maks এর শ্রেণি। যেমন আপনি যখন অরিয়েন্টেশনটির সাথে ডিল করেন তখন নিজেকে পরিবর্তন করেন (ম্যানিফেস্টে android:configChanges="orientation|screenSize|keyboardHidden"), বা অন্য কোনও কারণে রিসাইক্লারভিউটি এমক্লোনউইথ উইথথ পরিবর্তন না করে আকার পরিবর্তন করতে পারে। আমি আকারের রিসোর্স হিসাবে বিবেচিত int মানটিও পরিবর্তন করেছি এবং কোনও সংস্থার নির্মাতাকে তারপরে কলামউইনথ সেট করে নিজেই অনুমতি দিয়েছি।

public class GridAutofitLayoutManager extends GridLayoutManager {
    private Context context;
    private float mColumnWidth;

    private float currentColumnWidth = -1;
    private int currentWidth = -1;
    private int currentHeight = -1;


    public GridAutofitLayoutManager(Context context) {
        /* Initially set spanCount to 1, will be changed automatically later. */
        super(context, 1);
        this.context = context;
        setColumnWidthByResource(-1);
    }

    public GridAutofitLayoutManager(Context context, int resource) {
        this(context);
        this.context = context;
        setColumnWidthByResource(resource);
    }

    public GridAutofitLayoutManager(Context context, int resource, int orientation, boolean reverseLayout) {
        /* Initially set spanCount to 1, will be changed automatically later. */
        super(context, 1, orientation, reverseLayout);
        this.context = context;
        setColumnWidthByResource(resource);
    }

    public void setColumnWidthByResource(int resource) {
        if (resource >= 0) {
            mColumnWidth = context.getResources().getDimension(resource);
        } else {
            /* Set default columnWidth value (48dp here). It is better to move this constant
            to static constant on top, but we need context to convert it to dp, so can't really
            do so. */
            mColumnWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 48,
                    context.getResources().getDisplayMetrics());
        }
    }

    public void setColumnWidth(float newColumnWidth) {
        mColumnWidth = newColumnWidth;
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        recalculateSpanCount();
        super.onLayoutChildren(recycler, state);
    }

    public void recalculateSpanCount() {
        int width = getWidth();
        if (width <= 0) return;
        int height = getHeight();
        if (height <= 0) return;
        if (mColumnWidth <= 0) return;
        if ((width != currentWidth) || (height != currentHeight) || (mColumnWidth != currentColumnWidth)) {
            int totalSpace;
            if (getOrientation() == VERTICAL) {
                totalSpace = width - getPaddingRight() - getPaddingLeft();
            } else {
                totalSpace = height - getPaddingTop() - getPaddingBottom();
            }
            int spanCount = (int) Math.max(1, Math.floor(totalSpace / mColumnWidth));
            setSpanCount(spanCount);
            currentColumnWidth = mColumnWidth;
            currentWidth = width;
            currentHeight = height;
        }
    }
}

-1

একটি বৃহত সংখ্যায় স্প্যানকাউন্ট সেট করুন (যা কলামের সর্বাধিক সংখ্যা) এবং গ্রিডলাউটম্যানেজারে একটি কাস্টম স্প্যানসাইজলুকআপ সেট করুন।

mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int i) {
        return SPAN_COUNT / (int) (mRecyclerView.getMeasuredWidth()/ CELL_SIZE_IN_PX);
    }
});

এটি কিছুটা কুৎসিত, তবে এটি কার্যকর।

আমি মনে করি অটোস্প্যানগ্রিডলআউটম্যানেজারের মতো কোনও পরিচালক সবচেয়ে ভাল সমাধান হবে তবে আমি এর মতো কিছুই পাইনি।

সম্পাদনা: একটি বাগ রয়েছে, কিছু ডিভাইসে এটি ডানদিকে ফাঁকা স্থান যোগ করে


ডানদিকে স্থানটি কোনও বাগ নয়। যদি স্প্যান গণনাটি 5 হয় এবং getSpanSize3 টি ফেরত দেয় তবে একটি স্পেস থাকবে কারণ আপনি স্প্যানটি পূরণ করছেন না।
নিকোলাস টাইলার

-6

স্প্যান গণনাটি স্বতঃ-সনাক্ত করতে আমি ব্যবহৃত একটি মোড়কের প্রাসঙ্গিক অংশগুলি এখানে। আপনি এটিকে আর.লেআউটআমি_গ্রিড_এইটিএম রেফারেন্সের setGridLayoutManagerসাথে কল করে সূচনা করেন এবং এটি প্রতিটি সারিতে কতগুলি ফিট করতে পারে তা নির্ধারণ করে।

public class AutoSpanRecyclerView extends RecyclerView {
    private int     m_gridMinSpans;
    private int     m_gridItemLayoutId;
    private LayoutRequester m_layoutRequester = new LayoutRequester();

    public void setGridLayoutManager( int orientation, int itemLayoutId, int minSpans ) {
        GridLayoutManager layoutManager = new GridLayoutManager( getContext(), 2, orientation, false );
        m_gridItemLayoutId = itemLayoutId;
        m_gridMinSpans = minSpans;

        setLayoutManager( layoutManager );
    }

    @Override
    protected void onLayout( boolean changed, int left, int top, int right, int bottom ) {
        super.onLayout( changed, left, top, right, bottom );

        if( changed ) {
            LayoutManager layoutManager = getLayoutManager();
            if( layoutManager instanceof GridLayoutManager ) {
                final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
                LayoutInflater inflater = LayoutInflater.from( getContext() );
                View item = inflater.inflate( m_gridItemLayoutId, this, false );
                int measureSpec = View.MeasureSpec.makeMeasureSpec( 0, View.MeasureSpec.UNSPECIFIED );
                item.measure( measureSpec, measureSpec );
                int itemWidth = item.getMeasuredWidth();
                int recyclerViewWidth = getMeasuredWidth();
                int spanCount = Math.max( m_gridMinSpans, recyclerViewWidth / itemWidth );

                gridLayoutManager.setSpanCount( spanCount );

                // if you call requestLayout() right here, you'll get ArrayIndexOutOfBoundsException when scrolling
                post( m_layoutRequester );
            }
        }
    }

    private class LayoutRequester implements Runnable {
        @Override
        public void run() {
            requestLayout();
        }
    }
}

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