Hi i use horizontal RecyclerView. But except horizontal devider i need vertical devider in each Item (different height).
I try
<View
android:layout_width="3dp"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"/>
This work then i set android:layout_height="50dp". But with android:layout_height="wrap_content" View it's gone.
I try get height from adapter
#Override
public void onBindViewHolder(final ClubListViewHolder holder, final int position) {
holder.parent.getHeight();
}
Method return -1
How solve this trouble?
You can use android:layout_height="match_parent" instead, place the view in ViewHolder layout. Then its height will be the same as item's height.
Related
I have a LinearLayout xml with a RecyclerView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/r1"
android:background="#DBDBDB">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#DBDBDB" />
</LinearLayout>
In my java class I am setting the background image of whole Linearlayout:
LinearLayout linear;
linear = findViewById(R.id.r1);
linear.setBackgroundResource(R.drawable.visitedbg);
This is working fine. But I want to set background for the Linearlayout also in Recycleradapter.
In the list the user can remove any item by clicking on it. And if the last item is removed, I want to show a background image.
In onBindViewHoldermethod I have:
movieList.remove(position);notifyDataSetChanged();
if (getItemCount()<=0){holder.linear.setBackgroundResource(R.drawable.visitedbg);}
Problem is the Nullpointerexception, as I can't define the LinearLayout view in Recycleradapter.
I tried to put it to public MyviewHolder(View itemView), also in public RecyclerAdapter.MyviewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) as
LinearLayout linear = itemView.findViewById(R.id.r1);
but this is still not working. Is there any solution for this?
First of all, I recommend migrating from findViewById() to viewBindng to prevent app from crashing in running time.
Second, You can only access views inside recyclerView's items from adapter. to implement what you want, you should listen for recyclerView's adapter change. You can use AdapterDataObserver:
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
//...
}
});
Take a look at this link in android documentation.
Another way to achieve that will be checking for adapter's item count everytime you remove an element:
movieList.remove(position);
notifyItemRemoved(position);
if(adapter.getItemCount() == 0)
linear.setBackgroundResource(R.drawable.visitedbg)
I'm trying to set the height of a ViewHolder in onBindViewHolder after changing its content but it only works at the beginning. When it gets recycled, the heights are wrong. I guess it keeps the height of the previous content. Why does it not adjust it again? What am I doing wrong?
My code (simplified):
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mMyView.setText(holder.mItem.getValue());
holder.mView.measure(
View.MeasureSpec.makeMeasureSpec(Resources.getSystem().getDisplayMetrics().widthPixels, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
);
int layoutHeight = holder.mView.getMeasuredHeight();
holder.mMyView.getLayoutParams().height = layoutHeight;
//holder.mView.requestLayout();
}
public class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mMyView;
ViewHolder(View view) {
super(view);
mView = view;
mMyView= view.findViewById(R.id.myView);
}
}
Edit: My original code is a bit more complicated than this. I need to adjust the size of a view to match the size of another view. The code above is simplified to make it easier to read.
Edit 2: As requested, here is a simplified version of my XML to understand why I want to adjust the height. My goal is to adjust the ImageView height to match the height of the TextViews.
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/imageView"
app:layout_constraintStart_toStartOf="parent"
/>
<ImageView
android:id="#+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#imageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
Edit 3: I just set the height to a fixed value now. Calculating the height had a big impact on the performance anyway. Ridiculous how difficult it is to make layouts responsive in Android.
Thanks in advance.
Simply set height of the TextView to wrap_content in its XML file. Then change the onBindViewHolder as following:
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mItem = mValues.get(position);
holder.mMyView.setText(holder.mItem.getValue());
}
Height of the TextView will be change accordingly to its content.
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
//this is called when you scroll items
//this will reset to origin xml default items
//here heightChanged is the status , set true if changed
if(heightChanged){
//height according to logic
}else{
//do nothing
}
}
It seems like the height of items are different from each other, try adding status for height that has been changed (write logs to find out the height of each view you will get an idea how to solve this)
you have to set the height of Viewholder dynamically.just use,
public class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mMyView;
ViewHolder(View view) {
super(view);
mView = view;
mMyView= view.findViewById(R.id.myView);
view.setMinimumHeight(600); // 600 you can type you height that you want...
}
}
i am facing a problem i cannot resolve. i googled it but couldnt get the solution im looking for. i have a recycle view as follow:
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:paddingBottom="70dp"
android:layout_marginTop="#dimen/activity_vertical_margin"
this recycle view is showing in the screen as follow
if you notice, there is no spacing above the text and bottom of the text for each item. most likely due to wrap_content. i want to add space within the item cell on top and bottom. something like this image
if you noticed, i draw red arrows to indicate the extra space and the text in the center of each item list. how can i add space within the cell(space on top of text and space on bottom of text? left and right space will be cool too.
when i googled this, i only found code to add spacing between items. but what i am looking for is to add spacing within the cell item itself like the second picture attach. i would appreciate your help. thanks in advance
Definitely you are using an adapter for your recycler view and that adapter is responsible to create children. As #cocored said you have to create your own layout. you have to do it in your adapter (usually in onCreateViewHolder).
you can use inflater service to inflate an xml layout for each child.
recyclerview_child.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"/>
...
</LinearLayout>
and in your adapter do something like this
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.ViewHolder> {
private List<Whatever> mData;
private LayoutInflater mInflater;
MyRecyclerViewAdapter(Context context, List<Whatever> data) {
this.mInflater = LayoutInflater.from(context);
this.mData = data;
}
// inflates the child layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.recyclerview_child, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each child
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Whatever obj = mData.get(position);
holder.myTextView.setText(obj.getName());
...
}
// total number of children
#Override
public int getItemCount() {
return mData.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder{
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
myTextView = itemView.findViewById(R.id.tv);
}
}
}
hope it helps
You would have to add a padding to your recycler item. If you're using a default item layout from android I would suggest creating your own layout.
I'm dealing with legacy code that uses a viewpager to display an horizontal list of images(instead of say a listview or recyclerview) in a fragment. The viewpager uses a custom PagerAdapter which overrides the appropriate methods(instantiateItem, getItemPositiion etc). My issue right now is that I want to add some space at the end of the final element of the viewpager, I've attempted to do this by adding a margin to this final elment.
public Object instantiateItem(ViewGroup collection, int position) {
FrameLayout itemView = ViewManager.createView(position, height, type);
int viewWidth = itemView.getLayoutParams().width;
RelativeLayout itemViewWrap = new RelativeLayout(mContext);
if(postion == items.size()-1){
RelativeLayout.LayoutParams itemViewparams = RelaiveLayout.LayoutParams)itemView.getLayoutParams();
itemViewparams.setMargins(0, 0, viewWidth, 0);
}
itemViewWrap.addView(itemView);
collection.addView(itemViewWrap);
return itemView;
}
Unfortunately this does not work and the final element is just not shown. How do I properly achieve this? Here is the xml for the fragment in which this viewpager resides.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.playground.test.views.ItemViewPager
android:id="#+id/viewpager"
android:layout_gravity="center_vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
</RelativeLayout>
You could override the last page's width using ViewPagerAdapter# getPageWidth. To be more than the rest of the page's with the margin you want.
https://developer.android.com/reference/android/support/v4/view/PagerAdapter.html#getPageWidth(int)
I have a recyclerview inside SwipeRefreshLayout. and at the end of recyclerview, I'd like to add a button, but I'm unable to do so. Here the code :
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refresh"
android:layout_width="wrap_content"
android:layout_below="#+id/toolbar"
android:paddingBottom="50dp"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"/>
<Button
android:layout_width="match_parent"
android:layout_height="50dp"
android:id="#+id/load_more"
android:layout_alignParentBottom="true"
android:textColor="#color/md_black_1000"
android:text="TEST"/>
</android.support.v4.widget.SwipeRefreshLayout>
The button does not appear at the end of the recyclerview.
SwipeRefreshLayout could have only one child.
Add RecyclerView and Button to vertical LinearLayout and put it into SwipeRefreshLayout.
<android.support.v4.widget.SwipeRefreshLayout>
<LinearLayout>
<android.support.v7.widget.RecyclerView>
<Button>
</LinearLayout>
</android.support.v4.widget.SwipeRefreshLayout>
To add Button as last item in RecyclerView you need edit adapter:
1) increase number of rows
#Override
public int getItemCount() {
return pictureArrayList.size() + 1;
}
2) show Button when list ends
#Override
public void onBindViewHolder(final ExampleHolder holder, final int position) {
final Picture picture = pictureArrayList.get(position);
if (position <= pictureArrayList.size()) {
holder.title.setVisibility(View.VISIBLE);
holder.button.setVisibility(View.GONE);
holder.title.setText(picture.getName());
holder.imageView.setImageResource(picture.getImage());
} else {
holder.title.setVisibility(View.GONE);
holder.button.setVisibility(View.VISIBLE);
}
}
You need to create a RecyclerView with different view items depending on what you want to do may be an option to use a view button at the bottom of the list, I have a blog post where I wrote a blog about the RecyclerView(Spanish).
http://erikcaffrey.github.io/2015/10/05/recyclerview/
You can see the code!
https://github.com/erikcaffrey/RecyclerView-Examples