অ্যান্ড্রয়েড পুনর্ব্যবহারযোগ্য গ্রিডলাউটম্যানেজার কলামের ব্যবধান


251

গ্রিডলাউটম্যানেজার ব্যবহার করে আপনি কীভাবে একটি রিসাইক্লিউউয়ের সাথে কলামের ব্যবধান সেট করবেন? আমার লেআউটের ভিতরে মার্জিন / প্যাডিং সেট করার কোনও প্রভাব নেই।


আপনি কি সাবক্লাসিং GridLayoutManagerএবং ওভাররাইডিং generateDefaultLayoutParams()এবং আত্মীয়তার চেষ্টা করেছেন ?
কমন্সওয়্যার

আমার নেই, আমি ভেবেছিলাম এমন একটি পদ্ধতি থাকত যা আমি ঠিক অনুরূপ গ্রিড ভিউ সেট করার জন্য দেখছিলাম না। আমি চেষ্টা করব
hitch.united


উত্তর:


348

রিসাইক্লারভিউস আইটেমডেকোরেশন ধারণাকে সমর্থন করে : প্রতিটি উপাদানকে ঘিরে বিশেষ অফসেট এবং অঙ্কন। এই উত্তর হিসাবে দেখা যায় , আপনি ব্যবহার করতে পারেন

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
  private int space;

  public SpacesItemDecoration(int space) {
    this.space = space;
  }

  @Override
  public void getItemOffsets(Rect outRect, View view, 
      RecyclerView parent, RecyclerView.State state) {
    outRect.left = space;
    outRect.right = space;
    outRect.bottom = space;

    // Add top margin only for the first item to avoid double space between items
    if (parent.getChildLayoutPosition(view) == 0) {
        outRect.top = space;
    } else {
        outRect.top = 0;
    }
  }
}

তারপরে এটি যুক্ত করুন

mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
int spacingInPixels = getResources().getDimensionPixelSize(R.dimen.spacing);
mRecyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels));

3
'আউটআরেক্ট.টপ = স্পেস' ব্যবহার করুন এবং 'আউটআরেক্ট.বটম' মুছে ফেলুন যদি আপনি 'যদি প্রথম অবস্থানে থাকেন তবে' গণ্ডগোল করতে চান না। ; -]
Amio.io

2
@ জাটজিকি - হ্যাঁ, আপনি যদি ইতিমধ্যে আপনার RecyclerView(এবং ব্যবহারের clipToPadding="false") অংশ হিসাবে শীর্ষ এবং নীচের প্যাডিং ব্যবহার করেন তবে আপনি কিছুটা পুনর্গঠন করতে পারেন। আপনি যদি তা না করেন তবে আপনি চেকটি সর্বশেষবারের মতো সরাতে চাইছেন (যেহেতু আপনি এখনও শেষ আইটেমের নীচে প্যাডিং চান)।
ianhanniballake

18
@ianhanniballake, যখন এটি একক স্প্যান বিন্যাস ব্যবস্থাপক ব্যবহার করার সময় কাজ করে, এটি বহু-স্প্যান লেআউট ম্যানেজারের জন্য ব্যর্থ হয়।
অবিনাশ আর

4
আপনি যদি গ্রিডলআউটম্যানেজার দিয়ে এইভাবে করেন - ২ য়, তৃতীয় ... নবম কলামের সমস্ত প্রথম আইটেম শীর্ষে আটকে থাকবে (কারণ কোনও স্থান নেই)। সুতরাং আমি মনে করি .টপ = স্পেস / 2 এবং। নীচে = স্পেস / 2. করা ভাল
ইয়ারোস্লাভ

1
এই উত্তরটি মূল প্রশ্নের উত্তর দেয় না। প্রশ্ন জোর জোর দেওয়া হয় GridLayoutManager । উত্তরটি বহু-কলাম / সারি বিন্যাসে কাজ করবে না
hch

428

নিম্নলিখিত কোডটি ভালভাবে কাজ করে এবং প্রতিটি কলামে একই প্রস্থ রয়েছে:

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int spacing;
    private boolean includeEdge;

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view); // item position
        int column = position % spanCount; // item column

        if (includeEdge) {
            outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
            outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

            if (position < spanCount) { // top edge
                outRect.top = spacing;
            }
            outRect.bottom = spacing; // item bottom
        } else {
            outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
            outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
            if (position >= spanCount) {
                outRect.top = spacing; // item top
            }
        }
    }
}

ব্যবহার

1. কোন প্রান্ত

এখানে চিত্র বর্ণনা লিখুন

int spanCount = 3; // 3 columns
int spacing = 50; // 50px
boolean includeEdge = false;
recyclerView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));

2. প্রান্ত সহ

এখানে চিত্র বর্ণনা লিখুন

int spanCount = 3; // 3 columns
int spacing = 50; // 50px
boolean includeEdge = true;
recyclerView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));

12
শিরোনামের মতো বিভিন্ন স্প্যানযুক্ত আইটেম না থাকলে কাজ করে।
ম্যাথু

8
দুর্দান্ত উত্তর; একটি টিপ: স্পেসিংটি পিএক্সে রয়েছে (যাতে আপনি ম্যাথ.াউন্ড ব্যবহার করে ডিপিকে পিএক্সে রূপান্তর করতে পারেন (someDpValue * getResource ()। getDisplayMetrics ()। ঘনত্ব))
কেভিন লি

1
এটি ঠিকঠাক কাজ করছে তবে আমার সমস্যা হচ্ছে, আমি স্প্যানকাউন্ট 2 (ডিফল্ট) সহ গ্রিডলাউটম্যানেজারটি ব্যবহার করছি তবে ব্যবহারকারী স্প্যানকাউন্ট পরিবর্তন করতে পারে তাই যখন ডিফল্ট অবস্থান থেকে স্প্যানকাউন্ট পরিবর্তন হয় সেখানে কিছু পজিশনে আরও অনেক বেশি দৃশ্যমান প্যাডিং থাকে যেমন স্প্যানকাউন্ট 3 এর চেয়ে 3 হবে প্যাডিং / মার্জিন 2,3 8,9 12,13 ইত্যাদিতে
হরিস কুরেশি

2
দুর্দান্ত কাজ! তবে স্ট্যাজগ্রিডগ্রিডলআউটআউট ম্যানেজারে আমার কিছু সমস্যা আছে। imgur.com/XVutH5u অনুভূমিক মার্জিন কখনও কখনও পৃথক হয়।
উফকোকু

2
যখন লেআউটটি আরটিএল হবে (2 কলাম বা আরও বেশি কলামের জন্য) এটি কাজ করে না। আরটিএল মোডে থাকা অবস্থায় বর্তমানে কলামগুলির মধ্যে স্থান ঠিক নেই। আপনি প্রতিস্থাপন করতে হবে: যখন rtl হয় তখন outRect.left এর সাথে outRect.left le
মাসউদ মোহাম্মদী

83

আপনি যদি আইটেম এবং সমান আইটেমের আকারগুলির চারপাশে সমান ব্যবধান চান তবে নিম্নলিখিত ধাপে ধাপে সহজ সমাধানটি দেওয়া হল।

ItemOffsetDecoration

public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {

    private int mItemOffset;

    public ItemOffsetDecoration(int itemOffset) {
        mItemOffset = itemOffset;
    }

    public ItemOffsetDecoration(@NonNull Context context, @DimenRes int itemOffsetId) {
        this(context.getResources().getDimensionPixelSize(itemOffsetId));
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
            RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        outRect.set(mItemOffset, mItemOffset, mItemOffset, mItemOffset);
    }
}

বাস্তবায়ন

আপনার উত্স কোডে, ItemOffsetDecorationআপনার RecyclerView. আইটেমের অফসেট মানটি আইটেমগুলির মধ্যে স্থান হিসাবে যুক্ত করতে চান এমন প্রকৃত মানের অর্ধেক আকার হওয়া উচিত।

mRecyclerView.setLayoutManager(new GridLayoutManager(context, NUM_COLUMNS);
ItemOffsetDecoration itemDecoration = new ItemOffsetDecoration(context, R.dimen.item_offset);
mRecyclerView.addItemDecoration(itemDecoration);

এছাড়াও, আইটেমের অফসেট মান এর প্যাডিং হিসাবে সেট করুন RecyclerViewএবং নির্দিষ্ট করুন android:clipToPadding=false

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerview_grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:padding="@dimen/item_offset"/>

নিখুঁত, এটি সহজ এবং কার্যকর।
বিশ্রুতি

28

এটা চেষ্টা কর. এটি চারপাশে সমান ব্যবধানের যত্ন নেবে। তালিকা, গ্রিড এবং স্ট্যাজার্ডার্ড গ্রিড উভয়ই কাজ করে।

সম্পাদিত

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

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

public class ListSpacingDecoration extends RecyclerView.ItemDecoration {

  private static final int VERTICAL = OrientationHelper.VERTICAL;

  private int orientation = -1;
  private int spanCount = -1;
  private int spacing;
  private int halfSpacing;


  public ListSpacingDecoration(Context context, @DimenRes int spacingDimen) {

    spacing = context.getResources().getDimensionPixelSize(spacingDimen);
    halfSpacing = spacing / 2;
  }

  public ListSpacingDecoration(int spacingPx) {

    spacing = spacingPx;
    halfSpacing = spacing / 2;
  }

  @Override
  public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

    super.getItemOffsets(outRect, view, parent, state);

    if (orientation == -1) {
        orientation = getOrientation(parent);
    }

    if (spanCount == -1) {
        spanCount = getTotalSpan(parent);
    }

    int childCount = parent.getLayoutManager().getItemCount();
    int childIndex = parent.getChildAdapterPosition(view);

    int itemSpanSize = getItemSpanSize(parent, childIndex);
    int spanIndex = getItemSpanIndex(parent, childIndex);

    /* INVALID SPAN */
    if (spanCount < 1) return;

    setSpacings(outRect, parent, childCount, childIndex, itemSpanSize, spanIndex);
  }

  protected void setSpacings(Rect outRect, RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    outRect.top = halfSpacing;
    outRect.bottom = halfSpacing;
    outRect.left = halfSpacing;
    outRect.right = halfSpacing;

    if (isTopEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
        outRect.top = spacing;
    }

    if (isLeftEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
        outRect.left = spacing;
    }

    if (isRightEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
        outRect.right = spacing;
    }

    if (isBottomEdge(parent, childCount, childIndex, itemSpanSize, spanIndex)) {
        outRect.bottom = spacing;
    }
  }

  @SuppressWarnings("all")
  protected int getTotalSpan(RecyclerView parent) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
        return ((GridLayoutManager) mgr).getSpanCount();
    } else if (mgr instanceof StaggeredGridLayoutManager) {
        return ((StaggeredGridLayoutManager) mgr).getSpanCount();
    } else if (mgr instanceof LinearLayoutManager) {
        return 1;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getItemSpanSize(RecyclerView parent, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
        return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanSize(childIndex);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
        return 1;
    } else if (mgr instanceof LinearLayoutManager) {
        return 1;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getItemSpanIndex(RecyclerView parent, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
        return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanIndex(childIndex, spanCount);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
        return childIndex % spanCount;
    } else if (mgr instanceof LinearLayoutManager) {
        return 0;
    }

    return -1;
  }

  @SuppressWarnings("all")
  protected int getOrientation(RecyclerView parent) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof LinearLayoutManager) {
        return ((LinearLayoutManager) mgr).getOrientation();
    } else if (mgr instanceof GridLayoutManager) {
        return ((GridLayoutManager) mgr).getOrientation();
    } else if (mgr instanceof StaggeredGridLayoutManager) {
        return ((StaggeredGridLayoutManager) mgr).getOrientation();
    }

    return VERTICAL;
  }

  protected boolean isLeftEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

        return spanIndex == 0;

    } else {

        return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex);
    }
  }

  protected boolean isRightEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

        return (spanIndex + itemSpanSize) == spanCount;

    } else {

        return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex);
    }
  }

  protected boolean isTopEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

        return (childIndex == 0) || isFirstItemEdgeValid((childIndex < spanCount), parent, childIndex);

    } else {

        return spanIndex == 0;
    }
  }

  protected boolean isBottomEdge(RecyclerView parent, int childCount, int childIndex, int itemSpanSize, int spanIndex) {

    if (orientation == VERTICAL) {

        return isLastItemEdgeValid((childIndex >= childCount - spanCount), parent, childCount, childIndex, spanIndex);

    } else {

        return (spanIndex + itemSpanSize) == spanCount;
    }
  }

  protected boolean isFirstItemEdgeValid(boolean isOneOfFirstItems, RecyclerView parent, int childIndex) {

    int totalSpanArea = 0;
    if (isOneOfFirstItems) {
        for (int i = childIndex; i >= 0; i--) {
            totalSpanArea = totalSpanArea + getItemSpanSize(parent, i);
        }
    }

    return isOneOfFirstItems && totalSpanArea <= spanCount;
  }

  protected boolean isLastItemEdgeValid(boolean isOneOfLastItems, RecyclerView parent, int childCount, int childIndex, int spanIndex) {

    int totalSpanRemaining = 0;
    if (isOneOfLastItems) {
        for (int i = childIndex; i < childCount; i++) {
            totalSpanRemaining = totalSpanRemaining + getItemSpanSize(parent, i);
        }
    }

    return isOneOfLastItems && (totalSpanRemaining <= spanCount - spanIndex);
  }
}

আশা করি এটা সাহায্য করবে.


1
আমি প্রথম লাইনের আইটেমের পরে ডাবল স্প্যান পেয়েছি। এটি ঘটে কারণ প্যারেন্ট.জেটচিল্ড কাউন্ট () প্রথম আইটেমের জন্য 1, দ্বিতীয়টির জন্য 2 এবং আরও কিছু দেয়। সুতরাং, আমি উপরের প্রান্তের আইটেমগুলিতে স্থান যুক্ত করার পরামর্শ দিচ্ছি যেমন: আউটআরেক্ট.টপ = চাইল্ড ইনডেক্স <স্প্যানকাউন্ট? স্পেসিংআইনপিক্সেল: 0; এবং প্রতিটি আইটেমের জন্য নীচে স্থান যুক্ত করুন: outRect.bottom = স্পেসিংআইনপিক্সেল;
ইভানপি 24'15

রিসাইকেলার ভিউ স্ক্রোল করার সময়, ব্যবধান পরিবর্তন করা হয়েছিল।
যুগেশ

3
আমি মনে করি প্যারেন্ট.গেটচিল্ড কাউন্ট () "প্যারেন্ট.গেটলাউটম্যানেজার ()। GetItemCount ()" এ পরিবর্তন করা উচিত। এছাড়াও, isBottomEdge ফাংশনটি "রিটার্ন চাইল্ডইন্ডেক্স> = চাইল্ডকাউন্ট - স্প্যানকাউন্ট + স্প্যানআইডেক্স" এ পরিবর্তন করা দরকার। এগুলি পরিবর্তনের পরে, আমি সমান ব্যবধান পেয়েছি। তবে দয়া করে নোট করুন যে স্প্যান গণনাটি 2 এর চেয়ে বেশি হলে এই সমাধানটি আমাকে সমান আইটেমের আকার দেয় না কারণ অবস্থানের উপর নির্ভর করে অফসেট মান পৃথক is
yqritc

1
@ ইয়াক্রিটকে পিতা-মাতা.গীতচিল্ড কাউন্ট () নিবন্ধ দেওয়ার জন্য ধন্যবাদ। আমি পিতামাতার ব্যবহারের জন্য আমার উত্তর আপডেট করেছি getগেটলয়েটম্যানেজার ()) getItemCount ()
পীরদাদ সখিজাদা

2
এটি ভেরিয়েবল স্প্যান, অভিনন্দন এবং ধন্যবাদ সহ বক্সের বাইরে খুব ভাল কাজ করেছে!
পিয়েরে-লাক পাওর

21

নীচের কোডটি স্ট্যাগগ্রেডগ্রিডলআউটআউট ম্যানেজার, গ্রিডলাউটম্যানেজার এবং লিনিয়ারলআউটআউট ম্যানেজার পরিচালনা করবে।

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {

    private int halfSpace;

    public SpacesItemDecoration(int space) {
        this.halfSpace = space / 2;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

        if (parent.getPaddingLeft() != halfSpace) {
            parent.setPadding(halfSpace, halfSpace, halfSpace, halfSpace);
            parent.setClipToPadding(false);
        }

        outRect.top = halfSpace;
        outRect.bottom = halfSpace;
        outRect.left = halfSpace;
        outRect.right = halfSpace;
    }
}

তারপরে এটি ব্যবহার করুন

mRecyclerView.addItemDecoration(new SpacesItemDecoration(mMargin));

1
এটি সবচেয়ে সহজ এক। একটি গুরুত্বপূর্ণ বিষয় হ'ল আপনি এক্সএমএলে প্যারেন্টে প্যাডিং যুক্ত করতে পারেন। আমার ক্ষেত্রে এটি কাজ করে। ধন্যবাদ।
সমীর

SpaceItemDecorationআসলে পিতা বা মাতা (recycler দৃশ্য) থেকে প্যাডিং যোগ করা হয়েছে।
মার্ক হিথারিংটন

আমি কেবল halfSpaceপ্যাডিং হাজির (ডানদিকে) যখন আমি এক্সএমএলে প্যারেন্টের কাছে প্যাডিং সেট না করেছিলাম
সমীর

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

ঠিক আছে আমার এক্সএমএলে কোনও প্যাডিং সেট নেই।
সমীর

11

এখানে এমন একটি সমাধান রয়েছে যাতে "স্প্যানকাউন্ট" (কলামগুলির সংখ্যা) প্রয়োজন হয় না কারণ আমি গ্রিডআউটফিটলয়আউট ম্যানেজার ব্যবহার করি (প্রয়োজনীয় সেল আকার অনুযায়ী কলামগুলির সংখ্যা গণনা করে)

(সাবধান থাকুন যে এটি কেবল গ্রিডলাউটম্যানেজারে কাজ করবে )

public class GridSpacesItemDecoration extends RecyclerView.ItemDecoration {
    private final boolean includeEdge;
    private int spacing;


    public GridSpacesItemDecoration(int spacing, boolean includeEdge) {
        this.spacing = spacing;
        this.includeEdge = includeEdge;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        if (parent.getLayoutManager() instanceof GridLayoutManager) {
            GridLayoutManager layoutManager = (GridLayoutManager)parent.getLayoutManager();
            int spanCount = layoutManager.getSpanCount();
            int position = parent.getChildAdapterPosition(view); // item position
            int column = position % spanCount; // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }

        }

    }
}

এখানে GridAutofitLayoutManager কেউ আগ্রহী হয় হয়:

public class GridAutofitLayoutManager extends GridLayoutManager {
    private int mColumnWidth;
    private boolean mColumnWidthChanged = true;

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

    public GridAutofitLayoutManager(Context context,int unit, int columnWidth)
    {
        /* Initially set spanCount to 1, will be changed automatically later. */
        super(context, 1);
        int pixColumnWidth = (int) TypedValue.applyDimension(unit, columnWidth, context.getResources().getDisplayMetrics());
        setColumnWidth(checkedColumnWidth(context, pixColumnWidth));
    }

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

    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());
        }
        return columnWidth;
    }

    public void setColumnWidth(int newColumnWidth)
    {
        if (newColumnWidth > 0 && newColumnWidth != mColumnWidth)
        {
            mColumnWidth = newColumnWidth;
            mColumnWidthChanged = true;
        }
    }

    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state)
    {
        int width = getWidth();
        int height = getHeight();
        if (mColumnWidthChanged && mColumnWidth > 0 && width > 0 && height > 0)
        {
            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;
        }
        super.onLayoutChildren(recycler, state);
    }
}

অবশেষে:

mDevicePhotosView.setLayoutManager(new GridAutofitLayoutManager(getContext(), getResources().getDimensionPixelSize(R.dimen.item_size)));
mDevicePhotosView.addItemDecoration(new GridSpacesItemDecoration(Util.dpToPx(getContext(), 2),true));

ওহে. এটি আশ্চর্যজনকভাবে কাজ করে তবে আমি আপনার সমাধান সহ একটি শিরোনাম ব্যবহার করছি। আপনি কীভাবে পুরো-প্রস্থের শিরোলেখ অর্জন করতে পারেন তা প্রস্তাব করতে পারেন?
অজিৎ

দয়া করে আপনি নীচের হিসাবে লেআউট ম্যানেজারের সাথে পজিশনটি যাচাই করতে layoutManager.getPosition(view)পারেন যে পজিশনটি শূন্য যা আপনার শিরোলেখ হবে কিনা .. এছাড়াও, এই ভাবে আপনি যে কোনও পজিশনে অন্য শিরোনাম যুক্ত করতে সক্ষম হবেন :)
মিনা সামির

9

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

item_layout.xml

<CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:margin="10dp">

activity_layout.xml

<RecyclerView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="10dp"/>

হালনাগাদ: এখানে চিত্র বর্ণনা লিখুন


এটা ঠিক কাজ করে! আপনি কি এই বিষয়ে বিস্তারিত বলতে পারেন, দয়া করে?
elyar abad

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

7

আপনি যদি সমস্ত ডিভাইসে আপনার আইটেমের আকারটি স্থির করতে চান RecyclerView। আপনি এই মত করতে পারেন

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int mSpanCount;
    private float mItemSize;

    public GridSpacingItemDecoration(int spanCount, int itemSize) {
        this.mSpanCount = spanCount;
        mItemSize = itemSize;
    }

    @Override
    public void getItemOffsets(final Rect outRect, final View view, RecyclerView parent,
            RecyclerView.State state) {
        final int position = parent.getChildLayoutPosition(view);
        final int column = position % mSpanCount;
        final int parentWidth = parent.getWidth();
        int spacing = (int) (parentWidth - (mItemSize * mSpanCount)) / (mSpanCount + 1);
        outRect.left = spacing - column * spacing / mSpanCount;
        outRect.right = (column + 1) * spacing / mSpanCount;

        if (position < mSpanCount) {
            outRect.top = spacing;
        }
        outRect.bottom = spacing;
    }
}

recyclerview_item.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="@dimen/recycler_view_item_width" 
    ...
    >
    ...
</LinearLayout>

dimens.xml

 <dimen name="recycler_view_item_width">60dp</dimen>

কার্যকলাপ

int numberOfColumns = 3;
mRecyclerView.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
mRecyclerView.setAdapter(...);
mRecyclerView.addItemDecoration(new GridSpacingItemDecoration(3,
        getResources().getDimensionPixelSize(R.dimen.recycler_view_item_width)));

এখানে চিত্র বর্ণনা লিখুন এখানে চিত্র বর্ণনা লিখুন


এটি কি স্ক্রিনের আকার অনুসারে কাজ করবে মানে 5 ইঞ্চি স্ক্রিনে যেভাবে প্রদর্শিত হচ্ছে, তারা অন্যান্য পর্দার আকারগুলিতেও একই দেখাচ্ছে?
সুনীল

আইটেমের আকার ঠিক করা হবে তবে আইটেমের মধ্যে স্থান পৃথক হতে পারে, আপনি বুঝতে আরও 2 টি চিত্র দেখতে পারেন
ফান ভ্যান লিনহ

তারা বিভিন্ন স্ক্রিনের আকারে ভিন্নভাবে দেখায় any কোনওভাবেই কিন্তু কাজ করার জন্য আপনাকে ধন্যবাদ
সুনীল

6

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

   class GridSpacingItemDecoration(private val columnCount: Int, @Px preferredSpace: Int, private val includeEdge: Boolean): RecyclerView.ItemDecoration() {

    /**
     * In this algorithm space should divide by 3 without remnant or width of items can have a difference
     * and we want them to be exactly the same
     */
    private val space = if (preferredSpace % 3 == 0) preferredSpace else (preferredSpace + (3 - preferredSpace % 3))

    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
        val position = parent.getChildAdapterPosition(view)

        if (includeEdge) {

            when {
                position % columnCount == 0 -> {
                    outRect.left = space
                    outRect.right = space / 3
                }
                position % columnCount == columnCount - 1 -> {
                    outRect.right = space
                    outRect.left = space / 3
                }
                else -> {
                    outRect.left = space * 2 / 3
                    outRect.right = space * 2 / 3
                }
            }

            if (position < columnCount) {
                outRect.top = space
            }

            outRect.bottom = space

        } else {

            when {
                position % columnCount == 0 -> outRect.right = space * 2 / 3
                position % columnCount == columnCount - 1 -> outRect.left = space * 2 / 3
                else -> {
                    outRect.left = space / 3
                    outRect.right = space / 3
                }
            }

            if (position >= columnCount) {
                outRect.top = space
            }
        }
    }

}

আমি নীচের লাইনগুলি যুক্ত করব, যদি আমার মতো কেউ স্প্যানকাউন্ট = 1columnCount == 1 -> { outRect.left = space outRect.right = space }
গ্র্যাডম্যাডনেসটি

5

@Edwardaa প্রদত্ত কোডটি অনুলিপি করেছেন এবং আরটিএল সমর্থন করার জন্য আমি এটি নিখুঁত করে তুলেছি:

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
    private int spanCount;
    private int spacing;
    private boolean includeEdge;
    private int headerNum;
    private boolean isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL;

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge, int headerNum) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
        this.headerNum = headerNum;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view) - headerNum; // item position
        if (position >= 0) {
            int column = position % spanCount; // item column
            if(isRtl) {
                column = spanCount - 1 - column;
            }
            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        } else {
            outRect.left = 0;
            outRect.right = 0;
            outRect.top = 0;
            outRect.bottom = 0;
        }
    }
}

প্রতি এক থেকে কোড কপি পারে gist.github.com/xingstarx/f2525ef32b04a5e67fecc5c0b5c4b939
Xingxing

4

উপরের উত্তরগুলি গ্রিডলাউটম্যানেজার এবং লিনিয়ারলআউটআউট ম্যানেজার মার্জিন হ্যান্ডলিং সেট করার উপায়গুলি স্পষ্ট করে দিয়েছে।

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

আপনি এটি এইভাবে পেতে পারেন:

private static class MyItemDecoration extends RecyclerView.ItemDecoration {
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        int index = ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
    }
}

4
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int spacing;
    private boolean includeEdge;

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams();
        int column = params.getSpanIndex();

        if (includeEdge) {
            outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
            outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

            if (position < spanCount) { // top edge
                outRect.top = spacing;
            }
            outRect.bottom = spacing; // item bottom
        } else {
            outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
            outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
            if (position >= spanCount) {
                outRect.top = spacing; // item top
            }
        }
    }
}

এডওয়ার্ডার উত্তর থেকে কিছুটা আলাদা, কলামটি কীভাবে নির্ধারণ করা হয় তা পার্থক্য, কারণ বিভিন্ন উচ্চতার আইটেমের ক্ষেত্রে কলামটি কেবল%% দ্বারা নির্ধারণ করা যায় না spanCount


4
class VerticalGridSpacingDecoration(private val spacing: Int) : RecyclerView.ItemDecoration() {

  override fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: State
  ) {
    val layoutManager = parent.layoutManager as? GridLayoutManager
    if (layoutManager == null || layoutManager.orientation != VERTICAL) {
      return super.getItemOffsets(outRect, view, parent, state)
    }

    val spanCount = layoutManager.spanCount
    val position = parent.getChildAdapterPosition(view)
    val column = position % spanCount
    with(outRect) {
      left = if (column == 0) 0 else spacing / 2
      right = if (column == spanCount.dec()) 0 else spacing / 2
      top = if (position < spanCount) 0 else spacing
    }
  }
}

3

এখানে আমার সংশোধনীটি দেওয়া হচ্ছে SpacesItemDecorationযার উপরের, নীচে, বাম এবং ডানদিকে সমানভাবে নাম্বার কলকোম এবং স্থান নিতে পারে ।

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {
    private int space;
    private int mNumCol;

    public SpacesItemDecoration(int space, int numCol) {
        this.space = space;
        this.mNumCol=numCol;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view,
                               RecyclerView parent, RecyclerView.State state) {

        //outRect.right = space;
        outRect.bottom = space;
        //outRect.left = space;

        //Log.d("ttt", "item position" + parent.getChildLayoutPosition(view));
        int position=parent.getChildLayoutPosition(view);

        if(mNumCol<=2) {
            if (position == 0) {
                outRect.left = space;
                outRect.right = space / 2;
            } else {
                if ((position % mNumCol) != 0) {
                    outRect.left = space / 2;
                    outRect.right = space;
                } else {
                    outRect.left = space;
                    outRect.right = space / 2;
                }
            }
        }else{
            if (position == 0) {
                outRect.left = space;
                outRect.right = space / 2;
            } else {
                if ((position % mNumCol) == 0) {
                    outRect.left = space;
                    outRect.right = space/2;
                } else if((position % mNumCol) == (mNumCol-1)){
                    outRect.left = space/2;
                    outRect.right = space;
                }else{
                    outRect.left=space/2;
                    outRect.right=space/2;
                }
            }

        }

        if(position<mNumCol){
            outRect.top=space;
        }else{
            outRect.top=0;
        }
        // Add top margin only for the first item to avoid double space between items
        /*
        if (parent.getChildLayoutPosition(view) == 0 ) {

        } else {
            outRect.top = 0;
        }*/
    }
}

এবং আপনার যুক্তিতে নীচের কোডটি ব্যবহার করুন।

recyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels, numCol));

2

কেবলমাত্র XML ব্যবহার করে এই সমস্যার জন্য খুব সহজ এবং এখনও নমনীয় সমাধান রয়েছে যা প্রতিটি লেআউটম্যানেজারে কাজ করে।

ধরে নিন আপনি X এর সমান ব্যবধান চান (উদাহরণস্বরূপ 8 ডিপি)।

  1. আপনার কার্ডভিউ আইটেমটিকে অন্য লেআউটে মুড়িয়ে দিন

  2. বাইরের লেআউটটিকে এক্স / 2 (4 ডিপি) এর এক প্যাডিং দিন

  3. বাইরের লেআউটের পটভূমিকে স্বচ্ছ করুন

...

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:background="@android:color/transparent"
    android:padding="4dip">

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.CardView>

</LinearLayout>
  1. আপনার পুনর্ব্যবহারকারীকে X / 2 (4 ডিপি) এর এক প্যাডিং দিন

...

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="4dp" />

এবং এটাই. আপনার এক্স (8 ডিপি) এর নিখুঁত ব্যবধান রয়েছে।


2

যাঁরা স্তব্ধ হয়ে পড়ে আছেন তাদের জন্য (যেমন https://imgur.com/XVutH5u )

রিসাইক্লারভিউয়ের পদ্ধতিগুলি:

getChildAdapterPosition(view)
getChildLayoutPosition(view)

কখনও কখনও সূচি হিসাবে -1 ফিরে আসে যাতে আইটেমডেকার সেট করতে আমরা সমস্যায় পড়তে পারি। আমার সমাধান হ'ল অবহেলিত আইটেমডেকোরেশনের পদ্ধতিটি ওভাররাইড করা:

public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent)

নবাগত পরিবর্তে:

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, State state)

এটার মত:

recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
                TheAdapter.VH vh = (TheAdapter.VH) recyclerView.findViewHolderForAdapterPosition(itemPosition);
                View itemView = vh.itemView;    //itemView is the base view of viewHolder
                //or instead of the 2 lines above maybe it's possible to use  View itemView = layoutManager.findViewByPosition(itemPosition)  ... NOT TESTED

                StaggeredGridLayoutManager.LayoutParams itemLayoutParams = (StaggeredGridLayoutManager.LayoutParams) itemView.getLayoutParams();

                int spanIndex = itemLayoutParams.getSpanIndex();

                if (spanIndex == 0)
                    ...
                else
                    ...
            }
        });

এখনও পর্যন্ত আমার জন্য কাজ করছে বলে মনে হচ্ছে :)


দুর্দান্ত উত্তর! আপনার আইটেমগুলির মধ্যে শিরোনাম আইটেম রয়েছে সেখানে নিয়মিত "নিয়মিত" গ্রিডলআউট ম্যানেজার না করে সব ক্ষেত্রে কাজ করে। ধন্যবাদ!
শিরেন 85

2

এই প্রশ্নের উত্তরগুলি হওয়া উচিত তাদের চেয়ে জটিল বলে মনে হচ্ছে। এই আমার গ্রহণ এখানে।

ধরা যাক আপনি গ্রিড আইটেমগুলির মধ্যে 1dp ব্যবধান চান। নিম্নলিখিতগুলি করুন:

  1. একটি প্যাডিং যোগ 0.5dp করতে প্রতিটি আইটেমের
  2. একটি প্যাডিং যোগ -0.5dp করার RecycleView
  3. এটাই! :)

1

এটি RecyclerViewহেডার সহ পাশাপাশি কাজ করবে ।

public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {

    private int spanCount;
    private int spacing;
    private boolean includeEdge;
    private int headerNum;

    public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge, int headerNum) {
        this.spanCount = spanCount;
        this.spacing = spacing;
        this.includeEdge = includeEdge;
        this.headerNum = headerNum;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        int position = parent.getChildAdapterPosition(view) - headerNum; // item position

        if (position >= 0) {
            int column = position % spanCount; // item column

            if (includeEdge) {
                outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
                outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)

                if (position < spanCount) { // top edge
                    outRect.top = spacing;
                }
                outRect.bottom = spacing; // item bottom
            } else {
                outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
                outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f /    spanCount) * spacing)
                if (position >= spanCount) {
                    outRect.top = spacing; // item top
                }
            }
        } else {
            outRect.left = 0;
            outRect.right = 0;
            outRect.top = 0;
            outRect.bottom = 0;
        }
    }
    }
}

শিরোনাম কী?
টিম ক্রেনেন

1

yqritc এর উত্তর আমার পক্ষে নিখুঁতভাবে কাজ করেছে। আমি কোটলিন ব্যবহার করছিলাম তবে এখানে এটির সমতুল্য।

class ItemOffsetDecoration : RecyclerView.ItemDecoration  {

    // amount to add to padding
    private val _itemOffset: Int

    constructor(itemOffset: Int) {
        _itemOffset = itemOffset
    }

    constructor(@NonNull context: Context, @DimenRes itemOffsetId: Int){
       _itemOffset = context.resources.getDimensionPixelSize(itemOffsetId)
    }

    /**
     * Applies padding to all sides of the [Rect], which is the container for the view
     */
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView,state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)
        outRect.set(_itemOffset, _itemOffset, _itemOffset, _itemOffset)
    }
}

অন্য সব কিছুই এক।


1

জন্য StaggeredGridLayoutManager ব্যবহারকারী, সতর্কতা অবলম্বন করা আবশ্যক, এখানে সহ সবচেয়ে উত্তরের প্রচুর কোড নিচে সঙ্গে এক হিসাব করে আইটেমটি কলাম ভোট:

int column = position % spanCount

যা ধরে নিয়েছে যে 1 ম / 3 য় / 5 য় / .. আইটেমগুলি সর্বদা বাম দিকে এবং ২ য় / ৪ র্থ / 6th ষ্ঠ / .. আইটেমগুলি সর্বদা ডানদিকে অবস্থিত। এই অনুমান কি সবসময় সত্য? না।

ধরা যাক আপনার প্রথম আইটেমটি 100 ডিপি উচ্চ এবং ২ য় মাত্র 50 ডিপি, অনুমান করুন যে আপনার 3 য় আইটেমটি কোথায় অবস্থিত, বাম বা ডান?


0

গ্রিডলাউটম্যানেজার এবং হেডারভিউয়ের সাথে আমার রিসাইক্লারভিউয়ের মতো এটি করা শেষ করেছি

নীচের কোডটিতে আমি প্রতিটি আইটেমের মধ্যে 4 ডিপি স্পেস সেট করেছি (প্রতিটি আইটেমের চারপাশে 2 ডিপি এবং পুরো রিসাইক্লারভিউয়ের 2dp প্যাডিং)।

layout.xml

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycleview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="2dp" />

টুকরা / কার্যকলাপ

GridLayoutManager manager = new GridLayoutManager(getContext(), 3);
recyclerView.setLayoutManager(manager);
int spacingInPixels = Utils.dpToPx(2);
recyclerView.addItemDecoration(new SpacesItemDecoration(spacingInPixels));

SpaceItemDecoration.java

public class SpacesItemDecoration extends RecyclerView.ItemDecoration {

    private int mSpacing;

    public SpacesItemDecoration(int spacing) {
        mSpacing = spacing;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView recyclerView, RecyclerView.State state) {
        outRect.left = mSpacing;
        outRect.top = mSpacing;
        outRect.right = mSpacing;
        outRect.bottom = mSpacing;
    }
}

Utils.java

public static int dpToPx(final float dp) {
    return Math.round(dp * (Resources.getSystem().getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

0

তৈরি https://stackoverflow.com/a/29905000/1649371 (উপরে) সমাধান কাজ আমি নিম্নলিখিত পদ্ধতি (এবং পরবর্তী সব কল) সংশোধন করতে ছিল

@SuppressWarnings("all")
protected int getItemSpanSize(RecyclerView parent, View view, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
        return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanSize(childIndex);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
        return ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).isFullSpan() ? spanCount : 1;
    } else if (mgr instanceof LinearLayoutManager) {
        return 1;
    }

    return -1;
}

@SuppressWarnings("all")
protected int getItemSpanIndex(RecyclerView parent, View view, int childIndex) {

    RecyclerView.LayoutManager mgr = parent.getLayoutManager();
    if (mgr instanceof GridLayoutManager) {
        return ((GridLayoutManager) mgr).getSpanSizeLookup().getSpanIndex(childIndex, spanCount);
    } else if (mgr instanceof StaggeredGridLayoutManager) {
        return ((StaggeredGridLayoutManager.LayoutParams) view.getLayoutParams()).getSpanIndex();
    } else if (mgr instanceof LinearLayoutManager) {
        return 0;
    }

    return -1;
}


0

আপনার যদি একটি টগল স্যুইচ থাকে যা গ্রিডে তালিকার মধ্যে টগল করে, recyclerView.removeItemDecoration()কোনও নতুন আইটেম সজ্জা সেট করার আগে কল করতে ভুলবেন না । যদি না হয় তবে ব্যবধানের জন্য নতুন গণনাগুলি ভুল হবে।


এটার মতো কিছু.

        recyclerView.removeItemDecoration(gridItemDecorator)
        recyclerView.removeItemDecoration(listItemDecorator)
        if (showAsList){
            recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
            recyclerView.addItemDecoration(listItemDecorator)
        }
        else{
            recyclerView.layoutManager = GridLayoutManager(this, spanCount)
            recyclerView.addItemDecoration(gridItemDecorator)
        }

0

আপনি যদি গ্রিডলাউটম্যানেজার সহ শিরোনাম ব্যবহার করছেন তবে গ্রিডগুলির মধ্যে ব্যবধানের জন্য কোটলিনে লিখিত এই কোডটি ব্যবহার করুন :

inner class SpacesItemDecoration(itemSpace: Int) : RecyclerView.ItemDecoration() {
    var space: Int = itemSpace

    override fun getItemOffsets(outRect: Rect?, view: View?, parent: RecyclerView?, state: RecyclerView.State?) {
        super.getItemOffsets(outRect, view, parent, state)
        val position = parent!!.getChildAdapterPosition(view)
        val viewType = parent.adapter.getItemViewType(position)
       //check to not to set any margin to header item 
        if (viewType == GridViewAdapter.TYPE_HEADER) {
            outRect!!.top = 0
            outRect.left = 0
            outRect.right = 0
            outRect.bottom = 0
        } else {
            outRect!!.left = space
            outRect.right = space
            outRect.bottom = space

            if (parent.getChildLayoutPosition(view) == 0) {
                outRect.top = space
            } else {
                outRect.top = 0
            }
        }
    }
    }

আর পাস ItemDecorationকরতে recyclerviewযেমন

mIssueGridView.addItemDecoration(SpacesItemDecoration(10))

0

বাচ্চাদের জন্য আইটেমগুলির মধ্যে ফাঁক দিয়ে সমস্যাগুলির জন্য কার্ডভিউ ব্যবহার করার সময় অ্যাপ্লিকেশনটি সেট করে সমাধান করা যেতে পারে: কার্ড ইউজকম্প্যাটপ্যাডিং সত্য।

বড় মার্জিনের জন্য আইটেমের উচ্চতা বাড়ান। কার্ডএলভিশন alচ্ছিক (ডিফল্ট মান ব্যবহার করুন)।

<androidx.cardview.widget.CardView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardUseCompatPadding="true"
    app:cardElevation="2dp">

-1

ধন্যবাদ এডওয়ার্ডার উত্তর https://stackoverflow.com/a/30701422/2227031

আরেকটি বিষয় লক্ষণীয়:

যদি মোট ব্যবধান এবং মোট আইটেমের প্রস্থ পর্দার প্রস্থের সমান না হয় তবে আপনাকে আইটেমউইথ সামঞ্জস্য করতে হবে, উদাহরণস্বরূপ, বিনডভিউহোল্ডার পদ্ধতিতে অ্যাডাপ্টারে

Utils.init(_mActivity);
int width = 0;
if (includeEdge) {
    width = ScreenUtils.getScreenWidth() - spacing * (spanCount + 1);
} else {
    width = ScreenUtils.getScreenWidth() - spacing * (spanCount - 1);
}
int itemWidth = width / spanCount;

ConstraintLayout.LayoutParams layoutParams = (ConstraintLayout.LayoutParams) holder.imageViewAvatar.getLayoutParams();
// suppose the width and height are the same
layoutParams.width = itemWidth;
layoutParams.height = itemWidth;
holder.imageViewAvatar.setLayoutParams(layoutParams);

-1

এডওয়ার্ডার দুর্দান্ত উত্তরের ভিত্তিতে আমি তৈরি একটি কোটলিন সংস্করণ

class RecyclerItemDecoration(private val spanCount: Int, private val spacing: Int) : RecyclerView.ItemDecoration() {

  override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {

    val spacing = Math.round(spacing * parent.context.resources.displayMetrics.density)
    val position = parent.getChildAdapterPosition(view)
    val column = position % spanCount

    outRect.left = spacing - column * spacing / spanCount
    outRect.right = (column + 1) * spacing / spanCount

    outRect.top = if (position < spanCount) spacing else 0
    outRect.bottom = spacing
  }

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