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.
Related
I have a problem which is driving me nuts. Basically it is a simple RecyclerView which displays a cardview. There are a lot of posts out there already, which I checked. I have assigned a LayoutManager as indicated here (RecyclerView Not Displaying Any CardView Items) , I have implemented the getItemCount method as explained here (card view not showing up), and I changed to the following versions (changing version was suggested here RecyclerView of cards not showing anything):
compile 'com.android.support:support-v4:24.0.0'
compile 'com.android.support:cardview-v7:24.0.0'
compile 'com.android.support:recyclerview-v7:24.0.0'
I also did the notifyDataSetChanged() as indicated here (RecyclerView Not Displaying Any CardView Items). However, nothing fixed it for me.
I have an Activity which has the following code (only relevant sections, getDummyData returns a List with 1 dummy data):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DatabaseHelper databaseHelper = new DatabaseHelper(getApplicationContext());
setContentView(R.layout.activity_overview);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
rv.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rv.setLayoutManager(linearLayoutManager);
RVAdapter adapter = new RVAdapter(getDummyData());
rv.setAdapter(adapter);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
adapter.notifyDataSetChanged();
}
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.DocumentViewHolder> {
List<Document> DocumentList;
public RVAdapter(List<Document> Documents) {
this.DocumentList = Documents;
}
#Override
public DocumentViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.document_item, parent, false);
DocumentViewHolder pvh = new DocumentViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(DocumentViewHolder DocumentViewHolder, int i) {
DocumentViewHolder.Date.setText(DocumentList.get(i).getCreatedFormatted());
DocumentViewHolder.participants.setText(DocumentList.get(i).getParticipants(getApplicationContext()));
DocumentViewHolder.counterOfItems.setText(DocumentList.get(i).getcounterOfItems(getApplicationContext()) + StringUtils.EMPTY);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public int getItemCount() {
//return DocumentList.size();
return 1;
}
public class DocumentViewHolder extends RecyclerView.ViewHolder {
TextView Date;
TextView participants;
TextView ideasPreview;
TextView counterOfItems;
ImageView Photo;
public DocumentViewHolder(View itemView) {
super(itemView);
Date = (TextView) itemView.findViewById(R.id._date);
participants = (TextView) itemView.findViewById(R.id.participants);
ideasPreview = (TextView) itemView.findViewById(R.id.ideas_preview);
counterOfItems = (TextView) itemView.findViewById(R.id.counter_of_items);
Photo = (ImageView) itemView.findViewById(R.id._photo);
}
}
}
And I have a Document_item - 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="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardCornerRadius="#dimen/_card_corner">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.25" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingEnd="#dimen/activity_horizontal_margin"
android:paddingStart="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin">
<TextView
android:id="#+id/_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="21st June 2016" />
<TextView
android:id="#+id/participants"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Thomas, Christian and Johann" />
<TextView
android:id="#+id/counter_of_items"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Thomas, Christian and Johann" />
<TextView
android:id="#+id/ideas_preview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello, Test, Test, Test" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
The activity's xml looks like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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:fitsSystemWindows="true"
tools:context="com.chmaurer.idea.OverviewActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#drawable/ic_playlist_add_white_24dp" />
</android.support.design.widget.CoordinatorLayout>
The code is compiling and executing normally, but no cards are shown. I have tried a few hour for myself now, but it is definitely the point where I'd be glad to have a hint...
Your code is fine, The problem is with layout file: document_item.xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/_photo"
android:layout_width="wrap_content" -->mistake
android:layout_height="wrap_content"
android:layout_weight="0.25" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent" -->mistake
android:gravity="center_horizontal"
android:orientation="vertical"
...
The second LinearLayout gets its height from parent (first LinearLayout), and the first one gets its height from its only child: ImageView (so without no drawable set, the second layout's height will be zero! ), if you set a drawable for ImageView (in onBindViewHolder method or in layout xml file) it probably crops some of TextView items, Also when you set android:layout_width to "wrap_content", actually you're ignoring layout_weight.
So edit layout file like this:
...
<ImageView
android:id="#+id/_photo"
android:layout_width="0dp"
android:layout_gravity="center_vertical"
android:layout_height="wrap_content"
android:layout_weight="0.25" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
...
You are using RecyclerView with vertical orientation (in Java code)
In the Activity XML you are setting the layout height to Wrap_Content
The card layout also has an height of match_parent
They will not work like that, I lost three days on this
Try to give fix height to your card layout, test also other alteration of other layout, it will work for you
Good luck
Just try after adding this line inside your recyclerview:
app:layout_behavior="#string/appbar_scrolling_view_behavior"
like this:
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</android.support.v7.widget.RecyclerView>
Hope it will help you.
I'm using RecyclerView inside NestedScrollView. Also i set setNestedScrollingEnabled to false for recyclerview
to support lower API
ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);
Now! When user scrolled the view every thing seems okay, but!!! views in recyclerview does not recycled!!! and Heap size grows swiftly!!
Update:
RecyclerView layout manager is StaggeredLayoutManager
fragment_profile.xml:
<android.support.design.widget.CoordinatorLayout
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:id="#+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" >
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/profileSwipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- RecyclerView and NestedScrollView -->
<include layout="#layout/fragment_profile_details" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>
fragment_profile_details.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:id="#+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:orientation="vertical" >
<android.support.v4.widget.NestedScrollView
android:id="#+id/nested_scrollbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="fill_vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:fillViewport="true"
android:scrollbars="none" >
<LinearLayout
android:id="#+id/nested_scrollbar_linear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical" >
<android.support.v7.widget.CardView
android:id="#+id/profileCardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="#color/card_backgroind"
app:cardCornerRadius="0dp"
app:cardElevation="0dp" >
<!-- Profile related stuff like avatar and etc. --->
</android.support.v7.widget.CardView>
<android.support.v7.widget.RecyclerView
android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/four"
android:layout_marginEnd="#dimen/four"
android:layout_marginLeft="#dimen/four"
android:layout_marginRight="#dimen/four"
android:layout_marginStart="#dimen/four"
android:layout_marginTop="#dimen/four"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:clipToPadding="false" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
ProfileFragment.java:
mAdapter = new MainAdapter(getActivity(), glide, Data);
listView = (RecyclerView) view.findViewById(R.id.list_view);
ViewCompat.setNestedScrollingEnabled(listView, false);
listView.setAdapter(mAdapter);
mStaggeredLM = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
mStaggeredLM.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS);
listView.setLayoutManager(mStaggeredLM);
mScroll.setOnScrollChangeListener(new OnScrollChangeListener() {
#Override
public void onScrollChange(NestedScrollView arg0, int arg1, int arg2, int arg3, int arg4) {
View view = (View) mScroll.getChildAt(mScroll.getChildCount() - 1);
int diff = (view.getBottom() - ( mScroll.getHeight() + mScroll.getScrollY()));
if(diff == 0){
int visibleItemCount = mStaggeredLM.getChildCount();
int totalItemCount = mStaggeredLM.getItemCount();
int[] lastVisibleItemPositions = mStaggeredLM.findLastVisibleItemPositions(null);
int lastVisibleItemPos = getLastVisibleItem(lastVisibleItemPositions);
Log.e("getChildCount", String.valueOf(visibleItemCount));
Log.e("getItemCount", String.valueOf(totalItemCount));
Log.e("lastVisibleItemPos", String.valueOf(lastVisibleItemPos));
if ((visibleItemCount + 5) >= totalItemCount) {
mLoadMore.setVisibility(View.VISIBLE);
Log.e("LOG", "Last Item Reached!");
}
mMore = true;
mFresh = false;
mRefresh = false;
getPosts();
}
}
});
P.s : I've set load more to scroll view, because recyclerview do it continuously and none stoppable!
Any help is appreciated
This is because we have a recycler view which has scroll behaviour inside a scroll view. (scroll inside a scroll)
I think the best way to resolve this issue is to your profileCardview as a header in your recycler view and then remove the nested scroll view.
If it were a listview then it was as simple as listView.addHeaderView(profileCardView) but for the Recycler view there is no addheadview equivalent. Hence you could refer the below link to change your implementation.
Is there an addHeaderView equivalent for RecyclerView?
For a RecyclerView or ListView the height should be constant, because if it will not a constant size then how it will manage the maximum number of visible rows in memory. Try by changing RecyclerView attribute android:layout_height="match_parent" or a fixed height(e.g. "300dp" - as needed), instead of "wrap_content". It should improve your memory management.
I am having Recyclerview inside Scrollview
<Scrollview
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="#+id/layoutStaticContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
//Static content.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp">
.
.
<LinearLayout>
//Dynamic content(newsfeed)
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</ScrollView>
Now while scrolling, layoutStaticContent stays fix on the top & recyclerview content scrolls independently in the bottom part.
How to scroll the whole content i.e (layoutStaticContent + recyclerview content) such that there is only 1 scrollview?
I also tried replacing scrollview with Nestedscrollview but no success.
Use the android.support.v4.widget.NestedScrollView then inside both layout
NestedScrollView
Put the LinearLayout which contains both the static and dynamic data inside of a NestedScrollView and it'll work like a charm.
Here is the code you need:
<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:id="#+id/layoutStaticContent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
//Static content.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp">
.
.
<LinearLayout>
//Dynamic content(newsfeed)
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
I hope it helps!
One possible way around this is only use RecyclerView with the static content as header to your Recyclerview.
Then the layout would simply be:
//Dynamic content(newsfeed)
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
There will be a list_item_header.xml layout for your static content:
//Static content.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp">
.
.
<LinearLayout>
And you'll have to change your recyclerview adapter to contain:
private static final int TYPE_HEADER = 0;
private static final int TYPE_ITEM = 1;
#Override
public int getItemCount()
{
int itemCount = super.getItemCount();
if (mIsHeaderPresent)
{
itemCount += 1;
}
return itemCount;
}
#Override
public int getItemViewType(int position)
{
if (mIsHeaderPresent && position == 0)
{
return TYPE_HEADER;
}
return TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
if (viewType == TYPE_HEADER)
{
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_header, parent, false);
ViewHolderHeader viewHolder = new ViewHolderHeader(itemView);
return viewHolder;
} else if (viewType == TYPE_ITEM)
{
return getItemViewHolder(parent);
}
throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly");
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder passedViewHolder)
{
if (mIsHeaderPresent && passedViewHolder instanceof ViewHolderHeader)
{
onBindHeaderViewHolder((ViewHolderHeader) passedViewHolder);
} else
{
onBindItemViewHolder(passedViewHolder);
}
}
if you want to scroll all data i think you have to use CoordinatorLayout. in CoordinatorLayout you use appbar layout and CollapsingToolbarLayout where you can put your static content. because its a wrong approach in android to use a scroll able container in to another scroll able container. you can use coordinater layout like this.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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:fitsSystemWindows="true"
>
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="?attr/colorPrimary"
android:fitsSystemWindows="true"
app:expandedTitleMarginStart="48dp"
app:expandedTitleMarginEnd="64dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
//Static content.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp">
.
.
<LinearLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
After a lot of searching and trying, I found the solution:
1. Set the height for the RecyclerView inside the ScrollView:
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
...
<android.support.v7.widget.RecyclerView
android:id="#+id/myPostsRecyclerView"
android:layout_width="match_parent"
**android:layout_height="550dp"**
android:layout_below="#+id/textView7"
android:background="#drawable/background"
android:padding="5dp"
**android:visibility="gone"**
tools:listitem="#layout/item_send" />
</RelativeLayout>
</ScrollView>
2. In the adapter , where you set the data list :
public void setData(List<Post> posts) {
this.posts.clear();
this.posts.addAll(posts);
notifyDataSetChanged();
if (posts.size() < 1)
activity.recyclerView.setVisibility(View.GONE);
else {
activity.recyclerView.setVisibility(View.VISIBLE);
ViewGroup.LayoutParams params=activity.recyclerView.getLayoutParams();
params.height=ViewGroup.LayoutParams.WRAP_CONTENT;
activity.recyclerView.setLayoutParams(params);
}
}
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
I have RecyclerView inside ScrollView which is inside SwipeRefresh layout. I have few layouts on top of RecyclerView, but my RecyclerView is not visible, even if i remove other layouts from ScrollView. What do you suggest? I need to put list below some layouts in ScrollView somehow.
<?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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<include layout="#layout/toolbar"></include>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
....
<android.support.v7.widget.RecyclerView
android:id="#+id/simpleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
Tried to give specific height but still not visible o.O
If i replace RecyclerView with ListView, then list is visible.
If you want to have all the items of the list always visible then replace RecyclerView with LinearLayout and add your items to it.
An example:
your_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"
xmlns:app="http://schemas.android.com/apk/res-auto">
<include layout="#layout/toolbar"></include>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
....
<LinearLayout
android:id="#+id/simpleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/item_text"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/abc_ic_ab_back_mtrl_am_alpha"/>
</LinearLayout>
And in your Java code:
first declare the list
mSimpleList = (LinearLayout) findViewById(R.id.simpleList);
then method for adding the items
public void addListItems(ArrayList<String> strings) {
LayoutInflater inflater = LayoutInflater.from(this);
for(String s : strings) {
View item = inflater.inflate(R.layout.item_layout, mSimpleList, false);
TextView text = (TextView) item.findViewById(R.id.item_text);
text.setText(s);
mSimpleList.addView(item);//you can add layout params if you want
}
}
I just had to put android:fillViewport="true" to SwipeRefreshLayout. And now RecyclerView is visible.
My earlier answer is blocking the down scroll. So, a good work around will be add your Stuff as the first element of the RecyclerView. That can be easily implemented using the adapter. That way you can still scroll your stuff as well as your actual list elements.
<?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="match_parent"
android:orientation="vertical">
<include layout="#layout/toolbar"></include>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/simpleList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="#+id/your_stuff" />
</android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>
And using something like the following for your adapter implimentation,
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
class YourStuffViewHolder extends RecyclerView.ViewHolder {
//
}
class ViewHolderListItem extends RecyclerView.ViewHolder {
//
}
#Override
public int getItemViewType(int position) {
if(position>0){
return 1;
}
return 0;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case 0: return new YourStuffViewHolder();
case 1: return new ViewHolderListItem ();
}
}
}