recyclerview is not fit for all screen sizes - android

I am using recylerview and gridlayout manager with cardviews for each row, my row view(childview) is not responsive at all.
I want to show 15 cardviews in such a way that in portrait mode all my 15 childview should be visible and my recyclerview should not be scrollable whereas in landscape mode it should act vise versa( should be scrollable)
I have tried many soultions suggested on SO but nothing seems to be working.
current behaviour on different screen sizes are as follows
In the above attached screen shot ,the 3rd column, 4th and 5th row are not visible
In the above given screen my ui fits perfectly in portrait mode but in landscape i can't see all the cardviews.
in the screenshot attached above ,5th row is not visible and in the landscape mode there are some responsivness errors.
cardview.xml
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
android:layout_width="127dp"
android:layout_height="118dp"
android:layout_margin="5dp"
cardview:cardCornerRadius="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="#+id/mReminder_Image_Id"
android:layout_width="match_parent"
android:layout_height="90dp"
android:scaleType="fitXY"
android:background="#ffffff"/>
<TextView
android:id="#+id/mReminder_Text_Id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="#2d2d2d"
android:textSize="13sp"
android:text="Reminder texts"/>
</LinearLayout>
</android.support.v7.widget.CardView>
fragment_reminders.xml
<LinearLayout 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:orientation="vertical"
tools:context=".Fragments.Reminders">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Reminders"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="#color/tab_background"
android:layout_gravity="center" />
</android.support.v7.widget.Toolbar>
<android.support.v7.widget.RecyclerView
android:id="#+id/mRecyclerView_id"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
Can anyone guide me to solve this .
Thanks .

you can use this:
recyclerView.setLayoutManager(new RecyclerView.GridLayoutManager(this, span_count)
You could have a
res/values/ints.xml file with <integer> elements, giving the integer a name (name attribute) and value (text of the <integer> node). You could also have res/values-w600dp/ints.xml or res/values-land or other variations of the resource, where you provide
different values to use for different screen sizes. Then, at runtime, call
getResources().getInteger() to retrieve the correct value of the resource to use
for the current device, and use that in your GridLayoutManager constructor. Now,
you are in control over how many columns there are, by controlling how many spans
are supplied to the constructor.
https://developer.android.com/training/multiscreen/screensizes
Another approach, suggested by Chiu-Ki Chan, is to create a subclass of
RecyclerView, on which you provide a custom attribute for a desired approximate
column width. Then, in your subclass’ onMeasure() method, you can calculate the
number of spans to use to give you the desired column width.
https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager.html#GridLayoutManager(android.content.Context,%20int)
https://developer.android.com/reference/android/support/v7/widget/RecyclerView#setlayoutmanager

create a class as follows:
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class EqualSpacingItemDecoration extends RecyclerView.ItemDecoration {
private final int spacing;
private int displayMode;
public static final int HORIZONTAL = 0;
public static final int VERTICAL = 1;
public static final int GRID = 2;
public EqualSpacingItemDecoration(int spacing) {
this(spacing, -1);
}
public EqualSpacingItemDecoration(int spacing, int displayMode) {
this.spacing = spacing;
this.displayMode = displayMode;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildViewHolder(view).getAdapterPosition();
int itemCount = state.getItemCount();
RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
setSpacingForDirection(outRect, layoutManager, position, itemCount);
}
private void setSpacingForDirection(Rect outRect,
RecyclerView.LayoutManager layoutManager,
int position,
int itemCount) {
// Resolve display mode automatically
if (displayMode == -1) {
displayMode = resolveDisplayMode(layoutManager);
}
switch (displayMode) {
case HORIZONTAL:
outRect.left = spacing;
outRect.right = position == itemCount - 1 ? spacing : 0;
outRect.top = spacing;
outRect.bottom = spacing;
break;
case VERTICAL:
outRect.left = spacing;
outRect.right = spacing;
outRect.top = spacing;
outRect.bottom = position == itemCount - 1 ? spacing : 0;
break;
case GRID:
if (layoutManager instanceof GridLayoutManager) {
GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
int cols = gridLayoutManager.getSpanCount();
int rows = itemCount / cols;
outRect.left = spacing;
outRect.right = position % cols == cols - 1 ? spacing : 0;
outRect.top = spacing;
outRect.bottom = position / cols == rows - 1 ? spacing : 0;
}
break;
}
}
private int resolveDisplayMode(RecyclerView.LayoutManager layoutManager) {
if (layoutManager instanceof GridLayoutManager) return GRID;
if (layoutManager.canScrollHorizontally()) return HORIZONTAL;
return VERTICAL;
}
}
and for using it with your recycler view:
1)for grid view:
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(<sizeofpixels>, EqualSpacingItemDecoration.GRID));
2)for vertical view:
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(<sizeofpixels>, EqualSpacingItemDecoration.VERTICAL));
3)for horizontal view:
recyclerView.addItemDecoration(new EqualSpacingItemDecoration(<sizeofpixels>, EqualSpacingItemDecoration.HORIZONTAL));
hope this helps you.

Related

How to reduce space between columns in recycler view(GridLayoutManager) in android

I am using GridLayoutManager of recyclerview to display custom gallery in my app. I have implementated all the features like gallery. But there is a small thing Im stuck with. In one row I have 3 images. But I need to reduce the space between the images. While doing so , I dont want to show more than 3 images in a row, but the image size (if needed) can increase.
You can use custom RecyclerViewItemDecorator:
public class RecyclerViewItemDecorator extends RecyclerView.ItemDecoration {
private int spaceInPixels;
public RecyclerViewItemDecorator(int spaceInPixels) {
this.spaceInPixels = spaceInPixels;
}
#Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
outRect.left = spaceInPixels;
outRect.right = spaceInPixels;
outRect.bottom = spaceInPixels;
if (parent.getChildLayoutPosition(view) == 0) {
outRect.top = spaceInPixels;
} else {
outRect.top = 0;
}
}
}
Then add it to your RecyclerView:
// For example 10 pixels
int spaceInPixels = 10;
mRecyclerView.addItemDecoration(new RecyclerViewItemDecorator(spaceInPixels));
Hope it helps!
Use this for the recycler view,
this.mRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));
this.mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext())
.color(Color.DKGRAY)
.build());
this.mRecyclerView.addItemDecoration(new VerticalDividerItemDecoration.Builder(getContext())
.color(Color.DKGRAY)
.build());
and in your layout file for each item, set the Image in such a way to meet the edges of the container.
eg:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RlayoutGrid"
android:layout_width="220dp"
android:layout_height="170dp"
android:background="#android:color/black">
<ImageView
android:id="#+id/prefence_imageButton"
android:layout_width="match_parent"
android:layout_height="170dp"
android:background="#android:color/black"
android:focusable="false"
android:focusableInTouchMode="false"
android:scaleType="fitXY"
/>
</RelativeLayout>
and add this to your build.gradle
compile 'com.yqritc:recyclerview-flexibledivider:1.2.4'
To remove spacing you can use outRect.setEmpty()
RecyclerView.ItemDecoration divider = new RecyclerView.ItemDecoration(){
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.setEmpty();
}
};
grid.addItemDecoration(divider);

Center Columns in RecyclerView

I'm trying to create a dynamic RecyclerView layout. I am using a GridLayoutManager with three columns.
I need to wrap each grid item and center the columns (like attached).
I have tried a StaggeredGridLayout, I have tried a WrapGridLayoutManager but neither of these worked.
Here is my RecyclerView:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/categories_grid"
android:layout_marginTop="#dimen/feed_item_margin"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
and my RecyclerView item:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:background="#drawable/first_time_category_unselected"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<TextView
android:id="#+id/category_name"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_gravity="center_vertical"
android:textColor="#color/black_colour"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/category_status_icon"
android:layout_gravity="center_vertical"
android:background="#drawable/icon_follow"
android:layout_marginLeft="#dimen/feed_item_margin"
android:layout_marginRight="#dimen/feed_item_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
This is the decoration I'm using to implement grid spacing:
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;
}
}
This is what I'm trying to achieve:
This is what I am getting:
If anyone can help on this I'd greatly appreciate it
You can use Staggered Grid Layout Manager
as
StagaggeredGridLayoutManager = new StaggeredGridLayoutManager(3, LinearLayoutManager.HORIZONTAL );
recyclerView.setLayoutManager(gaggeredGridLayoutManager);
Here is Link for reference
Use this in recyclerView you could not arrange as you shown
<cuneyt.example.com.tagview.Tag.TagView
android:id="#+id/tag_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp" />
Download repo from GIT https://github.com/Cutta/TagView
TagView tagGroup = (TagView)findviewById(R.id.tag_view);
//You can add one tag
tagGroup.addTag(Tag tag);
//You can add multiple tag via ArrayList
tagGroup.addTags(ArrayList tags);
//Via string array
addTags(String[] tags);
//set click listener
tagGroup.setOnTagClickListener(new OnTagClickListener() {
#Override
public void onTagClick(Tag tag, int position) {
}
});
//set delete listener
tagGroup.setOnTagDeleteListener(new OnTagDeleteListener() {
#Override
public void onTagDeleted(final TagView view, final Tag tag, final int position) {
}
});
How do I make WRAP_CONTENT work on a RecyclerView

Issues recreating a material design lists with leave behind in Android

I'd like to recreate the Material Design list: controls in Android inside a sliding panel.
I'm making use of:
com.android.support:appcompat-v7
com.android.support:support-v4
com.android.support:recyclerview-v7
com.android.support:design
https://github.com/umano/AndroidSlidingUpPanel
https://github.com/serso/android-linear-layout-manager
https://github.com/daimajia/AndroidSwipeLayout
https://github.com/tmiyamon/gradle-mdicons
I ended up using portions of the support libraries, but this specific app is 5.0+ only so there may be some Lollipop-only stuff in my code.
Here is the layout for a list item in my RecyclerView:
<com.daimajia.swipe.SwipeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right">
<RelativeLayout
android:layout_width="42dp"
android:layout_height="match_parent"
android:background="?android:selectableItemBackground"
android:clickable="true"
android:focusable="true">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/ic_delete_black_24dp"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/ripple_floating"
android:clickable="true"
android:focusable="true"
android:minHeight="48dp"
android:paddingEnd="16dp"
android:paddingStart="16dp"
android:elevation="2dp">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:ellipsize="end"
android:singleLine="true"
android:text="..."/>
</RelativeLayout>
</com.daimajia.swipe.SwipeLayout>
And this is the current result.
The remaining problems to solve are elevation shadows and dividers.
As you can see in the image there are somewhat reasonable shadows on the sides of the list items. However there are no elevation shadows on the bottom of the items, so when an item is revealed no shadow shows above the revealed area.
The second issue is dividers. I have a single-item list with no icons/images so the proper design is to use dividers for the items.
However I can't use the DividerItemDecoration from serso/android-linear-layout-manager because it is not integrated into the slider and this happens when 2 adjacent items are slid.
Does anyone know of any drawable, attribute, or library I should be using to style these list items as material sheets with elevation shadows and borders?
Shadows/Elevation
For the shadows/elevation to look like that you can use card view with the common trick to make them slightly wider than the screen width ("full width cards").
For example:
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_marginLeft="#dimen/card_margin_horizontal"
android:layout_marginRight="#dimen/card_margin_horizontal"
app:cardCornerRadius="0dp"
app:cardElevation="4dp">
In values/dimens.xml:
<dimen name="card_margin_horizontal">-3dp</dimen>
In values-v21/dimens.xml
<dimen name="card_margin_horizontal">0dp</dimen>
Divider
And with that you might not need to change the divider, it might look ok.
Otherwise try adding the divider to the view itself (top view or control it's visibility yourself). It can be just a View with height 1dp and width match_parent and backgroundColor set to some dark grey (or the system divider drawable (R.attr.listDivider).
For the divider part of your question I would recommend looking into ItemDecorators. You can add an ItemDecorator to your LayoutManager and get dividers. An example of one is here (and there are several out there if you google for it)
Create a class named DividerItemDecoration.java and paste the below code
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
and use addItemDecoration().
you can find full tutorial on this page :
http://www.androidhive.info/2016/01/android-working-with-recycler-view/
Add android:clipChildren = "false" to SwipeLayout and RecyclerView.
Here is the layout for a list item in my RecyclerView:
<com.daimajia.swipe.SwipeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_marginBottom="1px"
android:clipChildren="false"
app:show_mode="lay_down">
<ImageView
android:layout_width="60dp"
android:layout_height="match_parent"
android:scaleType="center"
android:src="#drawable/ic_settings_black_24dp"/>
<FrameLayout
android:id="#+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:elevation="2dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/app_name"/>
</FrameLayout>
</com.daimajia.swipe.SwipeLayout>
Here is the layout my RecyclerView:
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorBackground"
android:clipChildren="false"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical"/>
And this is the current result.

StaggeredGridLayoutManager without ItemDecoration

StaggeredGridLayoutManager without ItemDecoration needs onScroll to arrange the items in matrix/Grid format. Is there a way to avoid ItemDecoration because I don't want decorator between items.
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL))
//Without addItemDecoration - it requires a scroll to occupy all the columns
recycler.addItemDecoration(new CustomInsetsDecoration(context));
without item decoration --
A
B
C
D
E
F
with item decoration (with min 1px/dp apart)
A B C
D E F
What I want:
ABC
DEF
A,B,C,D,E,F are all are ImageViews (of different sizes)
My item layout - a very simple - relativelayout and an Imageview:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/item_browse_cover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop" />
</RelativeLayout>
Any input is appreciated.
Thanks in advance.
Use the following MarginDecorator class with a 0 margin
public class MarginDecorator extends RecyclerView.ItemDecoration {
private int margin;
public MarginDecorator(int margin) {
this.margin = margin;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.top = margin;
outRect.bottom = margin;
outRect.left = margin;
outRect.right = margin;
}
}
Also try using the setGapStrategy()

How to find cell width from StaggeredGridLayoutManager?

I have a StaggeredGrid in a RecyclerView and I am trying to dynamically set the image height in the onBindViewHolder. I thought the StaggeredGrid was supposed to handle all this automatically, so I set android:layout_width="match_parent and android:scaleType="fitStart on the ImageView, but there is lots of gaps around the image.
Since the StaggeredGrid isn't living up to it, I'm trying to help it a bit by defining the image height dynamically in the onBindViewHolder. I have the width and height of the image ahead of time, but the cell width of the grid isn't available. I tried holder.cardView.getLayoutParams().width and getMeasuredWidth(), but they both return zero or small numbers. I know there are other places the cell width would be available, but I really need it in the onBindViewHolder event so I can set and adjust the image.
Any ideas on how to achieve this by leveraging the StaggeredGrid? Any advice or experience is appreciated!
In my activity is this:
mLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
In my adapter:
#Override
public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) {
MyModel item = mData.get(position);
int imageWidth = item.getFeatured_image().getWidth();
int imageHeight = item.getFeatured_image().getHeight();
int cellWidth = 540; // <==== how to find dynamically??!!
ViewGroup.LayoutParams imageLayoutParams = holder.thumbnailImageView.getLayoutParams();
imageLayoutParams.width = cellWidth;
imageLayoutParams.height = imageHeight * cellWidth / imageWidth;
holder.thumbnailImageView.setLayoutParams(imageLayoutParams);
MediaHelper.displayImage(item, holder.thumbnailImageView);
}
In my layout:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/row_my_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp">
<ImageView
android:id="#+id/row_my_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:scaleType="fitStart" />
<TextView
android:id="#+id/row_my_title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#CCFFFFFF"
android:textStyle="bold"
android:padding="5dp" />
</android.support.v7.widget.CardView>
I also tried to add this which does give me the cell width, but the onGlobalLayout event gets triggered way after the image is set and adjusted in the onBindViewHolder event so it's too late.
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
final View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_my_post, parent, false);
final MyViewHolder viewHolder = new MyViewHolder(view);
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int viewWidth = view.getWidth();
int viewHeight = view.getHeight();
}
});
}
return viewHolder;
}
Here is the gaps which are random due to the various image sizes. What I would like is for ALL images to be the width of the cell and let the height of the image and cell adjust dynamically:
Try This:- add this in your ImageView--> android:adjustViewBounds="true"
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/row_my_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
card_view:cardCornerRadius="2dp">
<ImageView
android:id="#+id/row_my_thumbnail_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:adjustViewBounds="true"/>
<TextView
android:id="#+id/row_my_title_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#CCFFFFFF"
android:textStyle="bold"
android:padding="5dp" />
</android.support.v7.widget.CardView>
Instead of getting the view height and width from onCreateViewHolder get it from onBindViewHolder as below:
#Override
public void onBindViewHolder(final MyAdapter.MyViewHolder holder, int position)
{
holder.itemView.post(new Runnable()
{
#Override
public void run()
{
MyModel item = mData.get(position);
int imageWidth = item.getFeatured_image().getWidth();
int imageHeight = item.getFeatured_image().getHeight();
int cellWidth = 540; // <==== how to find dynamically??!!
cellWidth = holder.itemView.getWidth();// this will give you width dynamically
ViewGroup.LayoutParams imageLayoutParams = holder.thumbnailImageView.getLayoutParams();
imageLayoutParams.width = cellWidth;
imageLayoutParams.height = imageHeight * cellWidth / imageWidth;
holder.thumbnailImageView.setLayoutParams(imageLayoutParams);
MediaHelper.displayImage(item, holder.thumbnailImageView);
}
});
}
I hope this will help you!!
The cell's width can be found at activity/fragment level and passed to the adapter before rendering time. Use something like this:
this.staggeredGridLayoutManager.getWidth() / this.staggeredGridLayoutManager.getSpanCount()
With this approach, you will be able to compute the cell's height before any rendering and avoid that initial flick introduced by post run approach.
Also, the image's aspect ratio will be preserved and you can reserve the required space before image load.
Be also aware that if any margins/paddings are present you should include them into previous calculation. Something like:
(this.staggeredGridLayoutManager.getWidth() - marginsAndOrPaddings) / this.staggeredGridLayoutManager.getSpanCount()
Update:
Starting with support packages 23.2.0, and at this point of lifecycle, this.staggeredGridLayoutManager.getWidth() returns 0. The total width can be achieved with this.recyclerView.getWidth()

Categories

Resources