While playing around with RecyclerView I found that there was no easy method to determine proportional height (with the height of the screen) of the list items. After trying various approaches I found that the best way to achieve this and the way that worked the best for the application that I was doing at the moment, was determining height of the item of the RecyclerView in the adapter.
I’ve written simple utility function that determines the height of the screen and then I have predefined ratio (that can be subject to change from cached value that is inputted by the user at some point).
Here is the method:
public static int containerHeight(MainActivity ba) { DisplayMetrics dm = new DisplayMetrics(); ba.getWindowManager().getDefaultDisplay().getMetrics(dm); LogUtil.dLog(Static.HEIGHT_TAG, "Screen Height of " + Build.MANUFACTURER + " " + Build.DEVICE + " " + Build.MODEL + " is " + Integer.toString(dm.heightPixels)); //get predefined value double ratio = Static.PIC_RATIO_VALUE; //check if there is cached value; using SnappyDB try { if (ba.getDB() != null && ba.getDB().isOpen() && ba.getDB().exists(Static.PIC_RATIO)) ratio = ba.getDB().getDouble(Static.PIC_RATIO); } catch (SnappydbException e) { e.printStackTrace(); LogUtil.dLog(Static.DB_TAG, "SnappydbException | couldn't get Static.PIC_RATIO"); } return (int) (dm.heightPixels / ratio); }
The method is applied in the adapter (in the onBindViewHolder method):
public class ItemsRecyclerAdapter extends RecyclerView.Adapter<ItemsRecyclerAdapter.SimpleItemViewHolder> { private ArrayList<SubRedditItem> mSubredditItems; private Context mCntx; OnItemClickListener mItemClickListener; //in order to enable onItemClickListener public class SimpleItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { @Override public void onClick(View v) { if (mItemClickListener != null) { mItemClickListener.onItemClick(v, getAdapterPosition()); //getPosition()); } } TextView labelAndText; ImageView pic; RelativeLayout container; public SimpleItemViewHolder(View itemView) { super(itemView); labelAndText = (TextView) itemView.findViewById(R.id.txtItemTitle); pic = (ImageView) itemView.findViewById(R.id.imgItem); container = (RelativeLayout) itemView.findViewById(R.id.rlContainer); } } public ItemsRecyclerAdapter(Context c, ArrayList<SubRedditItem> si) { this.mSubredditItems = si; this.mCntx = c; } @Override public SimpleItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View itemView = LayoutInflater.from(mCntx).inflate(R.layout.recycler_item, parent, false); return new SimpleItemViewHolder(itemView); } @Override public void onBindViewHolder(SimpleItemViewHolder holder, int position) { if (holder.labelAndText != null && holder.pic != null && mSubredditItems.get(position) != null) { //set the title if (mSubredditItems.get(position).getTitle() != null) holder.labelAndText.setText(mSubredditItems.get(position).getTitle()); //load image with picasso if (mSubredditItems.get(position).getUrl() != null) Picasso.with(mCntx).load(mSubredditItems.get(position).getUrl()).into(holder.pic); //holder._pic.setImage(ImageSource.uri(mSubredditItems.get(position).getUrl())); //set height in proportion to screen size int proportionalHeight = UIUtil.containerHeight((MainActivity) mCntx); TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, proportionalHeight); // (width, height) holder.container.setLayoutParams(params); } } @Override public int getItemCount() { //if (recentPost != null && recentPost.getPosts() != null) return mSubredditItems.size(); } public interface OnItemClickListener { public void onItemClick(View view, int position); } //to be added if more suitable public void SetOnItemClickListener(final OnItemClickListener mItemClickListener) { this.mItemClickListener = mItemClickListener; } }
The item layout is defined in the following manner:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:id="@+id/rlContainer" android:layout_height="wrap_content"> <ImageView android:id="@+id/imgItem" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/ChocolateTransparent" android:layout_alignParentBottom="true"> <TextView android:id="@+id/txtItemTitle" android:text="@string/testText" android:textSize="16sp" android:textStyle="bold" android:paddingTop="20dp" android:paddingBottom="20dp" android:paddingRight="10dp" android:paddingLeft="10dp" android:textColor="@color/White" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout> </RelativeLayout>
The ratio can also be determined in correlation to the downloaded image dimensions (landscape/portrait), something that will yield additional changes
The example application is actually a reddit client (feed fetching interaction is managed with rest2mobile) that displays graphic submittions (images) and respective submittion title. When the user clicks on settings it can change the ratio of the items in the RecyclerView and change the subreddit.
Screenshots:
The code of the application can be found on GitHub.
i will be test right now. okey thank the first time~