Hi all I am very new to android and I am having a problem with recyclerview. I am trying to add space between image views in a recyclerview but I am not successful.
What I want
What is happening
Below are my implementations
ItemOffsetDecoration.java
public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {
private int itemOffset;
public ItemOffsetDecoration(int itemOffset) {
itemOffset = 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(itemOffset, itemOffset, itemOffset, itemOffset);
}
}
shopping.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/shopping_bg"
tools:context=".activities.HomepageActivity$PlaceholderFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/shoppingRV"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:padding="#dimen/grid_horizontal_spacing"/>
</RelativeLayout>
Shopping.java
public class Shopping extends Fragment implements InstaPukkeiRecyclerViewAdapter.ItemClickListener {
InstaPukkeiRecyclerViewAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tab_shopping, container, false);
processRV(rootView);
return rootView;
}
private void processRV(View layout) {
RecyclerView recyclerView = (RecyclerView) layout.findViewById(R.id.shoppingRV);
int noOfColumns = 3;
recyclerView.setLayoutManager(new GridLayoutManager(getContext(), noOfColumns));
adapter = new InstaPukkeiRecyclerViewAdapter(getContext(), LogoIds.SHOPPING_SITE_LOGOS);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);
recyclerView.addItemDecoration(new ItemOffsetDecoration(getContext(), R.dimen.grid_horizontal_spacing));
}
}
Please help me here. Thanks in advance.
EDIT
item_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/logoImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:marginLeft="18dp"
android:marginRight="18dp"
android:id="#+id/logoImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true" />
</LinearLayout>
Change your item layout with this one in your item's XML. You make the parent(LinearLayout) height match parent that's why you are getting vertical full screen space
Use wrap_content in RecyclerView and also in row layout.And also add margins
<android.support.v7.widget.RecyclerView
android:id="#+id/shoppingRV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:padding="#dimen/grid_horizontal_spacing"/>
hmmm you can add margin to your image view or use dimen to set height and width something like this
android:layout_width="#dimen/dp_130"
android:layout_height="#dimen/dp_120"
or
<ImageView
android:id="#+id/logoImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:layout_margin="#dimen/dp_15"
android:adjustViewBounds="true" />
Inside your Recycleview set layout height to wrap_content
Related
I have a recyclerview inside SwipeRefreshLayout in a fragment. I have implemented AsyncTask to fetch data for recyclerview. The problem is SwipeRefreshLayout does not show at all, and hence the data is not populated in recyclerview. I have done the same thing for Activity and it works just fine but not in fragment. Can anybody guide me what am I doing wrong?
This is the layout file for fragment:
<?xml version="1.0" encoding="utf-8"?>
<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=".FeatureFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
And here is what I've done in the fragment class.
public class FeaturedFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private RecyclerView mRecyclerView;
private SwipeRefreshLayout mSwipeLayout;
public FeaturedFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_featured_captions, container, false);
mRecyclerView = view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mSwipeLayout = view.findViewById(R.id.refresh_layout);
mSwipeLayout.setOnRefreshListener(this);
return view;
}
#Override
public void onRefresh() {
new FetchFeedTask().execute((Void) null);
}
private class FetchFeedTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onPreExecute() {
mSwipeLayout.setRefreshing(true);
}
#Override
protected Boolean doInBackground(Void... voids) {
//things to do in background
}
#Override
protected void onPostExecute(Boolean success) {
mSwipeLayout.setRefreshing(false);
mRecyclerView.setAdapter(/*adapter*/);
//things to do at the end
}
}
}
It's too late to answer here but might help someone else.
I faced the same issue and it is because the recyclerView is immediate child of swipeRefreshLayout so simply put the recyclerView in a layout (for example ConstraintLayout) and then put this layout in your swipeRefreshLayout and everything will work as you expected.
May your code not working because of ReacyclerView scroll Listener
Try below snipped.
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int topRowVerticalPosition =
(recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop();
mSwipeLayout.setEnabled(topRowVerticalPosition >= 0);
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
});
Also, add your initialization stuff inside onViewCreated() like below
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_featured_captions, container, false);
return view;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mRecyclerView = view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mSwipeLayout = view.findViewById(R.id.refresh_layout);
mSwipeLayout.setOnRefreshListener(this);
}
Change the height of swipelayout to wrap_content
Solution 1 :)
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/refresh_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
Solution 2:) Use swipe layout and recycler view using design library
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.v4.widget.SwipeRefreshLayout>
Use NestedScrollView . put your recycleview or listview inside it. with
android:nestedScrollingEnabled="true"
Complete example -
<androidx.core.widget.NestedScrollView
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:isScrollContainer="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
android:clipToPadding="false"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.customfont.MyTextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" Title"
android:textSize="22dp"
android:textColor="#color/black"/>
<com.customfont.MyTextView
android:id="#+id/title2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text=" Title"
android:textSize="22dp"
android:textColor="#color/black"/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/mSwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MissingConstraints">
<com.pagenia.app.exoplayer.utils.ExoPlayerRecyclerView
android:id="#+id/exoPlayerRecyclerView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"
android:background="#FFFFFF"
android:dividerHeight="8dp" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
Try using the below snippet:
Always use support library widgets. instead of these:
<androidx.recyclerview.widget.RecyclerView
and
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
So:
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
So I need a horizontal RecyclerView. However, the items in them have dynamic heights based on what's returned from the backend.
The RecyclerView and its items have the height of "wrap_content"
The problem is if the first visible items in the RecyclerView are small, then when the user scrolls to the larger items, they appear cut off.
Ideally, we want the RecyclerView to be large enough to hold the largest item in the group (but only the largest existing item... not the hypothetically largest item). The RecyclerView dynamically changing its height is also acceptable.
I wrote an example app to illustrate the problem. In this app, we have a horizontal list. The first 33 items should show 1 line of text, while the next should show 3 lines of text, and the last 34 should show 2 lines. However, they all show 1 line, because the height of the RecyclerView doesn't change.
I've tried calling requestLayout() on the RecyclerView (and on the TextView) from onBindViewHolder(), but it doesn't seem to do anything.
MainActivity:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = createAdapter();
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
mRecyclerView.setAdapter(mAdapter);
}
private RecyclerView.Adapter<ViewHolder> createAdapter() {
RecyclerView.Adapter adapter = new RecyclerView.Adapter<ViewHolder>() {
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (position < 33) {
holder.mText.setText("1 line");
} else if (position > 66) {
holder.mText.setText("2 lines\n2 lines");
} else {
holder.mText.setText("3 lines\n3 lines\n3 lines");
}
}
#Override
public int getItemCount() {
return 100;
}
};
return adapter;
}
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView mText;
public ViewHolder(View itemView) {
super(itemView);
mText = (TextView) itemView.findViewById(R.id.text);
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#888888">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hi"
android:textSize="30sp" />
</LinearLayout>
Change your recyclerView height & width from wrap_content to match_parent or you can also give fixed height to your recyclerView like android:layout_height="150dp"
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#888888" />
</RelativeLayout>
or You can try
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#888888" />
</RelativeLayout>
Change your item.xml layout content with the below code.
It will solve your issue.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="160dp"
android:layout_height="match_parent"
android:background="#888888">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hi"
android:textSize="30sp" />
</LinearLayout>
You can solve this issue using the FlexboxLayoutManager Google library by defining the FlexDirection to FlexDirection.ROW and FlexWrap to FlexWrap.NOWRAP and also in your BaseViewHolder constructor set for each item the FlexShrink to 0.0f to be able to scroll horizontally. More details of how to achieve this can be found here: Horizontal RecyclerView with dynamic item’s Height
MainActivity:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAdapter = createAdapter();
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
mRecyclerView.setAdapter(mAdapter);
}
private RecyclerView.Adapter<ViewHolder> createAdapter() {
RecyclerView.Adapter adapter = new RecyclerView.Adapter<ViewHolder>() {
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (position < 33) {
holder.mText.setText("1 line");
} else if (position > 66) {
holder.mText.setText("2 lines\n2 lines");
} else {
holder.mText.setText("3 lines\n3 lines\n3 lines");
}
}
#Override
public int getItemCount() {
return 100;
}
};
return adapter;
}
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView mText;
public ViewHolder(View itemView) {
super(itemView);
mText = (TextView) itemView.findViewById(R.id.text);
}
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#888888">
<TextView
android:id="#+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hi"
android:textSize="30sp" />
</LinearLayout>
To make RecyclerView Horizontal you need to use android:layout_centerHorizontal="true". Also, everything more are the same as vertical.
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/RecyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/toolbar"/>
Try to add your textView android:singleLine="false" it changes when there are multiple lines
Just call itemAdapter.notifyDataSetChanged();
I am trying to use ItemDecorator to achieve spacing between CardViews inside a RecyclerView. For that I am using as reference this answer but the spacing isn't applied. I Also tried with this answer but no avail.
Here is the XML for the RecyclerView:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.company.name.MyFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerviewId"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
/>
</FrameLayout>
Here is the XML for the CardView:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/cardView"
card_view:cardElevation="2dp"
>
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView"
android:layout_width="100dp"
android:layout_height="98dp"
card_view:srcCompat="#mipmap/ic_launcher"
card_view:layout_constraintTop_toTopOf="parent"
card_view:layout_constraintLeft_toLeftOf="parent"/>
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
The code for the item decorators are the ones presented in the consulted answers.
What could be the reason for the spacing not to be applied?
EDIT 1:
Here's the code to assign the item decorator:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
...
myRecyclerView.setLayoutManager(new GridLayoutManager(activity, 2));
myRecyclerView.addItemDecoration(new SpacingGridView(activity, R.dimen.my_spacing), 0);
...
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState)
MyAdapter adapter = MyAdapter(getData());
myRecyclerView.setAdapter(adapter);
}
I want to place a RecylerView inside NestedScrollView as below
activity_service_menu.xml
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HELLO" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
ServiceMenuActivity.java
public class ServiceMenuTActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_menu_t);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
rv.setHasFixedSize(true);
rv.setAdapter(new RvAdapter());
}
private static class RvAdapter extends RecyclerView.Adapter<RvAdapter.RvHolder> {
#Override
public RvHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View serviceMenuItemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_service_menu, parent, false);
return new RvHolder(serviceMenuItemView);
}
#Override
public void onBindViewHolder(RvHolder holder, int position) {
}
#Override
public int getItemCount() {
return 100;
}
public static class RvHolder extends RecyclerView.ViewHolder {
public RvHolder(View itemView) {
super(itemView);
}
}
}
}
I have put the linearLayout inside scrollView and nestedScrollView.
But the RecyclerView is not visible. If I replace ScrollView with FrameLayout or any other layout, then RecyclerView is visible.
I want to use nestedScrollView and scroll the total layout when recyclerView is scrolled. Unfortunately recyclerView is not even visible.
Follow this sample will get idea where you done mistake.
Main Line is : android:fillViewport="true".
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:theme="#style/ThemeOverlay.AppCompat.Light"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="24dp">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
<com.app.view.CustomRecyclerView
android:id="#+id/recycler_movie_suggestion"
android:layout_width="match_parent"
android:layout_height="170dp"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
when you use two scrollble element inside each other you are in hot water! you have to calculate the Recycler item height and then find the whole recycler height. look at below link, I explain completely this problem.
Use RecyclerView insdie ScrollView with flexible recycler item height
I hope it help you
Please help me with the following situation.
I am developing an application where in one page I have a Linearlayout with a background image and RecyclerView with list of names.What I need is when i scroll up the RecyclerView I need the LinearLayout above also to move up so that the list in the recyclerView does not go under the LinearLayout above and when I scroll down the RecyclerView I need the LinearLayout above to scroll down so that we could see the image fully.
What i have done already is I used the setOnScrollListener of recyclerview and in the onScrolled() function I am getting the scrolling down and scrolling up event.But now i am stuck how to proceed further.
Below is the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<include layout="#layout/toolbar"
android:id="#+id/toolbar" />
<android.support.v7.widget.CardView
android:id="#+id/cardview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:layout_margin="8dp"
card_view:cardBackgroundColor="#android:color/white"
card_view:cardCornerRadius="8dp">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/scrollview"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="5"
android:orientation="vertical">
<LinearLayout
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="vertical"
android:background="#drawable/hydeparkmap"
android:layout_weight="3" ></LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:scrollbars="vertical" />
</LinearLayout>
</ScrollView>
</android.support.v7.widget.CardView>
</RelativeLayout>
Here is the code, i used in corresponding java class:
#InjectView(R.id.scrollview)
ScrollView scrollview;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shoplist);
ButterKnife.inject(this);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setTitle("ShopList");
scrollview.setVerticalScrollBarEnabled(true);
lm=new LinearLayoutManager(ShopListActivity.this);
recyclerView.setLayoutManager(lm);
firstVisibleInListview = lm.findFirstVisibleItemPosition();
adapter = new RecyclerViewAdapter(ShopListActivity.this, getData());
recyclerView.setAdapter(adapter);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(ShopListActivity.this, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Intent intent1 = new Intent(ShopListActivity.this, ShopProductListActivity.class);
intent1.putExtra("position", String.valueOf(position));
intent1.putExtra("shopname", it.get(position).getTitle());
intent1.putExtra("shopimage", String.valueOf(it.get(position).getImgIcon()));
intent1.putExtra("subcategory", subcategory);
startActivity(intent1);
}
})
);
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int currentFirstVisible = lm.findFirstVisibleItemPosition();
if(currentFirstVisible > firstVisibleInListview){
Toast.makeText(getBaseContext(),"Scrolled up ",Toast.LENGTH_SHORT).show();
scrollview.fullScroll(ScrollView.FOCUS_UP);
}
else
Toast.makeText(getBaseContext(),"Scrolled down ",Toast.LENGTH_SHORT).show();
firstVisibleInListview = currentFirstVisible;
}
});
}
so if I understand your question completely, you some View that should scroll with
RcyclerView.
if so in this situation you should delete your ScrollView cause RecyclerView have that within itself. what I write here is step by step guide to put a header( not sticky) in top of your RecyclerView so they would scroll together:
1- first you need to create a layout containing your header in my case i had an image for header so it looked like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#mipmap/winter"/>
</LinearLayout>
let's call this header_layout
2- you need to implement another method of RecyclerAdapter called getItemViewType it's output would be in as second parameter onCreateViewHolder(ViewGroup parent,int viewType) here you inflate the layout for each kind of view you need( for me these two look like this) :
#Override
public int getItemViewType(int position){
if(position == 0){
return 0;
} else {
return 1;
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView;
if(viewType==1){
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.report_row_layout, parent, false);
} else {
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.report_header_layout, parent, false);
}
return new MyViewHolder(itemView);
}
note that my first position (header) differs and other are the same you could have multiple views for multiple positions.
3- you should change your onBindViewHolder if needed in my case I needed to make it do nothing for my first position
4- remove your ScrollView and implement the layouts in positions and your main layout should look like this:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<include layout="#layout/toolbar"
android:id="#+id/toolbar" />
<android.support.v7.widget.CardView
android:id="#+id/cardview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar"
android:layout_margin="8dp"
card_view:cardBackgroundColor="#android:color/white"
card_view:cardCornerRadius="8dp">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v7.widget.CardView>
</RelativeLayout>
I don't know what your CardView is doing but delete it if you think it's not needed. if you need you can make your header a LinearLayout or anything else.
hope this helps.