smoothScrollToPosition does not work in nested RecyclerView - android

I have a recyclerView and each of it's item is a recyclerView. I want scroll to custom position of inner recyclerView at specific condition.
I used this code at innerRecyclerView but it didn't work:
innerRecyclerView.smoothScrollToPosition(position);
and this:
innerRecyclerView.scrollToPosition(position);
and this one:
layoutManager.scrollToPositionWithOffset(position, offset);
Now I have two question:
1) Is it possible scroll to custom position of inner recyclerView?
2) If that is possible, how?
Here is initialize main recyclerView:
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false);
adapter = new FreightsListRVAdapter(new FreightListCallBack(), new FreightListVHFactory());
rvFreightsList.setLayoutManager(layoutManager);
rvFreightsList.setItemViewCacheSize(30);
rvFreightsList.setNestedScrollingEnabled(true);
rvFreightsList.setAdapter(adapter);
Here is initialize innerRecyclerview:
LinearLayoutManager layoutManager = new LinearLayoutManager(itemView.getContext(), RecyclerView.VERTICAL, false);
layoutManager.setItemPrefetchEnabled(true);
layoutManager.setInitialPrefetchItemCount(7);
rvFreights.setNestedScrollingEnabled(false);
rvFreights.setLayoutManager(layoutManager);
rvFreights.setItemViewCacheSize(20);
adapter = new FreightsRVAdapter(new FreightCallBack(), new FreightSingleVHFactory());
rvFreights.setAdapter(adapter);
Here is my main recyclerView adapter:
public class FreightsListRVAdapter extends ListAdapter<FreightListModel, FreightListVH> {
private final FreightListVHFactory mFactory;
private final PublishSubject<FreightListVHAction> mClickUserPS = PublishSubject.create();
#Inject
public FreightsListRVAdapter(#NonNull FreightListCallBack diffCallback, FreightListVHFactory factory) {
super(diffCallback);
mFactory = factory;
}
#NonNull
#Override
public FreightListVH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return mFactory.create(parent);
}
#Override
public void onBindViewHolder(#NonNull FreightListVH holder, int position) {
holder.getVM().setObject(getItem(position));
holder.bind();
holder.itemOnClick(mClickUserPS);
}
public PublishSubject<FreightListVHAction> getmClickUserPS() {
return mClickUserPS;
}
}
Here is layout of each row of mainRecyclerView:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView 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/txtDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:textColor="#992C2C2C"
android:textSize="11sp"
app:fontFamily="#font/iransans"
tools:ignore="HardcodedText,SmallSp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/txtDate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="15dp"
android:gravity="right"
android:textColor="#2C2C2C"
android:textSize="20sp"
app:fontFamily="#font/iransans_medium"
tools:ignore="RtlHardcoded"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rvFreights"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbars="none" />
</androidx.appcompat.widget.LinearLayoutCompat>

In Kotlin-androidX recyclerview solution
val parentViewHolder = parentRecyclerView?.findViewHolderForAdapterPosition(parentPosition) as? ParentViewHolder?
var childY = 0F
if (parentViewHolder != null)
childY = parentViewHolder.childRecyclerView?.getChildAt(lastPosition)?.y ?: 0F
parentRecyclerView.scrollBy(0, childY.toInt())
PrentViewHolder.kt
class PrentViewHolder(
view: InflateBinding
): RecyclerView.ViewHolder(view.root) {
var recyclerView: RecyclerView? = null
fun populateData(data: Data) {
viewDataBinding.recyclerview.adapter = adapter
recyclerView = viewDataBinding.recyclerview
}
}

Can you please try this:
float y = recyclerView.getY() + recyclerView.getChildAt(selectedPosition).getY();
mainRecyclerview.smoothScrollTo(0, (int) y);

Related

Horizontal RecyclerView with dynamic item height

I am trying to create a horizontal recycler view with dynamic height by following this stack overflow post. The solution seems working. But the recycler view items disappear when I try to remove an item from recycler view.
recyclerview layout:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:clipToPadding="false"
android:orientation="horizontal"
android:paddingStart="13dp"
android:paddingEnd="13dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Recycler view item layout:
<androidx.cardview.widget.CardView
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="wrap_content"
android:layout_marginEnd="4dp"
android:layout_marginStart="4dp"
app:cardBackgroundColor="#BCAAAA"
app:cardElevation="2dp">
<TextView
android:padding="36dp"
android:id="#+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="22sp"
tools:text="Test String"/>
</androidx.cardview.widget.CardView>
Activity:
val flexBoxLayoutManager = FlexboxLayoutManager(this, FlexDirection.ROW, FlexWrap.NOWRAP)
with(recyclerView) {
layoutManager = flexBoxLayoutManager
adapter = RecyclerViewAdapter()
setHasFixedSize(false)
}
Adapter:
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textViewName: TextView = itemView.findViewById(R.id.textViewName)
init {
updateLayoutParamsToAllowHorizontalScrolling()
}
private fun updateLayoutParamsToAllowHorizontalScrolling() {
(itemView.layoutParams as? FlexboxLayoutManager.LayoutParams)?.let {
it.flexShrink = 0.0f
it.alignSelf = AlignItems.FLEX_START
}
}
}
override fun onBindViewHolder(holder: RecyclerViewAdapter.ViewHolder, position: Int) {
val item = listItems[position]
var msg = "Sample item no:$position "
for(i in 0..position){
msg += "dynamic content \n"
}
holder.textViewName.text = msg
holder.itemView.setOnClickListener {
val pos = listItems.indexOf(item)
listItems.removeAt(pos)
notifyItemRemoved(pos)
}
}
A screen recording of the output:
Is there any way to fix this issue? Or Are there any other approach to implement horizontal recyclerveiw with dynamic height?
I have fixed the issue without using FlexBoxLayoutManger.
Used LinearLayoutManager with horizontal orientation and the following code in onBindViewHolder in RecyclerViewAdapter.
holder.itemView.post {
val wMeasureSpec =
View.MeasureSpec.makeMeasureSpec(holder.itemView.width, View.MeasureSpec.EXACTLY)
val hMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
holder.itemView.measure(wMeasureSpec, hMeasureSpec)
if (holder.itemView.measuredHeight > holder.itemView.height) {
holder.itemView.layoutParams =
(holder.itemView.layoutParams as ViewGroup.LayoutParams)
.apply {
height = holder.itemView.measuredHeight
}
}
}

How can I get access to outside views from an Adapter

I have a recyclerview in my app showing a list of content. If a user is subscribed, they can proceed to read the full content and if not the recyclerview is hidden and a subscribe layout is shown.
Layout file
<?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:background="#color/light_grey"
android:orientation="vertical"
android:weightSum="10"
tools:layout_editor_absoluteY="25dp">
<!--RECYCLER VIEW-->
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginEnd="10dp"
android:layout_marginStart="10dp"
android:layout_marginTop="5dp"
android:layout_weight="8.3"
android:padding="2dp"
android:visibility="gone" />
<!--SUBSCRIBE TO VIEW CONTENT LAYOUT-->
<RelativeLayout
android:id="#+id/rlSubscribeToView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:visibility="gone"
android:layout_margin="10dp"
android:elevation="48dp"
android:layout_gravity="center"
android:layout_weight="8.3">
<TextView
android:id="#+id/tvSubscribe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_centerInParent="true"
android:textColor="#color/maroon"
android:text="#string/subscribe_to_view"/>
<Button
android:id="#+id/btnSubscribe"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_marginTop="15dp"
android:layout_marginStart="20dp"
android:layout_below="#id/tvSubscribe"
android:layout_marginEnd="20dp"
android:text="#string/subscribe"
android:textColor="#color/white" />
</RelativeLayout>
and the
RecyclerView Adapter
public void onBindViewHolder(#NonNull final ReadViewholder, final int position) {
holder.readMoreButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (userIsSubscribed) {
//Launch the next Activity
} else {
//Show the subscribe layout
holder.rlSubscribeToView .setVisibility(View.VISIBLE);
//Then hide the entire recyvlerView
}
}
});
}
class ReadViewholder extends RecyclerView.ViewHolder {
RelativeLayout rlSubscribeToView;
Button readMoreButton;
ReadViewholder(#NonNull View itemView) {
super(itemView);
//Not able to find (rlSubscribeToView ) since its not inside the recyclerview
rlSubscribeToView = itemView.findViewById(R.id.rlSubscribeToView);
readMoreButton= itemView.findViewById(R.id.readMoreButton);
}
}
How can I get access to the subscribe layout (rlSubscribeToView), which is on the same layout file as the recycler view and also hide the entire recycler view in the Adapter?
From a little bit of research, the are 2 callbacks that get can get you a reference to the actual RecyclerView, the onAttachedToRecyclerView and the onDetachedFromRecycler methods. My guess is that you are calling the Adapter constructor and passing in a context. If so use the below code, it will produce your desired result.
RelativeLayout rlSubscribeToView;
RecyclerView recyclerView;
public RecyclerAdapter(Context context) {
this.context = context;
this.videoItems = videoItems;
rlSubscribeToView = ((Activity) context).findViewById(R.id.rlSubscribeToView);
}
#Override
public void onAttachedToRecyclerView(#NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
}
and in your onBindViewHolder you can now get access the subscribe layout
public void onBindViewHolder(#NonNull final ReadViewholder, final int position) {
...
rlSubscribeToView.setVisibility();
}
What you need is an interface passed in as a parameter when you create your Adapter.
Example:
class Adapter(private val actions: Actions) : RecyclerView.Adapter<ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
// Create ViewHolder
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
// Setup Binder
holder.readMoreButton.setOnClickListener(View.OnClickListener {
if (userIsSubscribed) {
actions.launchActivity() //Launch the next Activity
} else {
//Show the subscribe layout
holder.rlSubscribeToView.setVisibility(View.VISIBLE)
actions.hideRecylerView() //Then hide the entire recyclerView
}
})
}
}
internal interface Actions {
fun launchActivity()
fun hideRecylerView()
}

How can I use FirestorePagingAdapter for a RecyclerView in NestedScrollView

I am using FirestorePagingAdapter to fetch my documents from Firestore. Everything is perfect but The "Load more" is happening automatically without getting to the bottom of the list. This is causing a janky behaviour.
I have placed my RecyclerView(Height: wrap content) in a NestedScrollView(Height: match-parent) which is the content of my main scrolling activity layout.
Is there a way to load more items only when I scroll to the last item.
<android.support.v4.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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".NewLookCode.activities.MainScrollingActivity"
tools:showIn="#layout/activity_main_scrolling">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_transporters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
android:padding="10dp"
android:visibility="visible" />
</LinearLayout>
val baseQuery = FirebaseFirestore.getInstance().collection("partners")
val config = PagedList.Config.Builder()
.setEnablePlaceholders(true)
.setPrefetchDistance(2)
.setPageSize(6)
.build()
val options = FirestorePagingOptions.Builder<PartnerInfoPojo>()
.setLifecycleOwner(this)
.setQuery(baseQuery, config, PartnerInfoPojo::class.java)
.build()
adapter = object:FirestorePagingAdapter<PartnerInfoPojo, PartnersViewHolder>(options) {
#NonNull
override fun onCreateViewHolder(#NonNull parent: ViewGroup, viewType:Int):PartnersViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_new_transporter, parent, false)
return PartnersViewHolder(view)
}
override fun onBindViewHolder(#NonNull holder:PartnersViewHolder,
position:Int,
#NonNull model:PartnerInfoPojo) {
holder.mCompany.text = model.getmCompanyName()
if(model!=null){
if(model.getmCompanyAdderss()!=null)
holder.mAddress.text = model.getmCompanyAdderss().city
}
}
}
rv_transporters.layoutManager = LinearLayoutManager(this)
rv_transporters.adapter = adapter

RelativeLayout in CoordinatorLayout doesn't scroll

I have a RelativeLayout within my CoordinatorLayout (as shown below). Also notice that within the RelativeLayout I have a RecyclerView.
However, when I scroll, I can only scroll on the RecyclerView and only the RecyclerView portion of the screen will actually scroll. If I try scrolling on the layout above the RecyclerView, it won't scroll the screen at all. Here's an illustration I made of what's going on:
So my question is, why can't I scroll on the inner RelativeLayout? Should I be organizing my layouts in a different way?
Here is my layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
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:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="250dp">
// some imageviews and textviews
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/header" />
</RelativeLayout>
<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.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_drawer"
app:menu="#menu/menu_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
How can I fix this?
RelativeLayout is not scrollable if it's not within any Scrollable View. Try putting your RelativeLayout as a Header of your RecyclerView.
In this example you will be able to scroll its content
<ScrollView
...
...>
<!-- Scrollable Contents -->
</ScrollView>
In your case I think the best way is to let your RecyclerView take up the whole screen and then assign its header. Follow this link or this. There's many out there so just google it up
Alright, this can be done using single recyclerview and putting your header relativelayout as an item of recyclerview.
May you are familiar with getItemViewType method, that is used to decide item type of recyclerview item.
Add data to your dataset using which you'll be going to decide type of an item. Consider below example...
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int ITEM_ROW = 1;
private final int ITEM_HEADER = 2;
// Will be your dataset which will be containing first item as relativeLayout payload.
private ArrayList<Object> mData;
public MyRecyclerViewAdapter(ArrayList<Object> mData) {
this.mData = mData;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh = null;
if (viewType == ITEM_ROW) {
// Inflate your row item of recyclerview here...
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_checkout_review_cart_item, parent, false);
vh = new ItemHolder(view);
} else if (viewType == ITEM_HEADER) {
// Inflate your relativeLayout here...
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_order_detail_grand_total_item, parent, false);
vh = new RelativeLayoutHolder(view);
}
return vh;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof ItemHolder) {
// Bind item of recyclerview here...
} else if (holder instanceof RelativeLayoutHolder) {
// Bind data of your relativeLayout
}
}
#Override
public int getItemCount() {
return mData.size();
}
#Override
public int getItemViewType(int position) {
// Decide type of an item using payload instances..
Object obj = mData.get(position);
if (obj instanceof ItemInfo) {
return ITEM_ROW;
} else if (obj instanceof RelativeLayoutInfo) {
return ITEM_HEADER;
} else {
return -1;
}
}
class ItemHolder extends RecyclerView.ViewHolder {
ItemHolder(View itemView) {
super(itemView);
}
}
class RelativeLayoutHolder extends RecyclerView.ViewHolder {
RelativeLayoutHolder(View itemView) {
super(itemView);
}
}
}
Your Payload of dataset will decide itemType. Two type of Pojo will going to be inserted into your dataset - RelativeLayoutInfo and ItemInfo. For an example
public class ItemInfo implements Serializable {
// Consider adding object and getter setter here
}
and
public class RelativeLayoutInfo implements Serializable {
// Consider adding object and getter setter here
}
There you go. your relativeLayout is added as an item of recyclerview.
Happy coding!!

"LayoutManager is already attached to a RecyclerView" error

I am trying to have multiple RecyclerViews in a layout but I get the following error: "LayoutManager is already attached to a RecyclerView"
The Java code is:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_squad, container, false);
Activity parentActivity = getActivity();
final ObservableScrollView scrollView = (ObservableScrollView) view.findViewById(R.id.squad_scrollview);
final RecyclerView gkRecyclerView = (RecyclerView) view.findViewById(R.id.gk_recycler);
final RecyclerView coachRecyclerView = (RecyclerView) view.findViewById(R.id.coach_recycler);
coachRecyclerView.setAdapter(new SquadRecyclerAdapter(parentActivity, getSquadDummyData(0)));
coachRecyclerView.setLayoutManager(new MyLinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false));
coachRecyclerView.setHasFixedSize(false);
gkRecyclerView.setAdapter(new SquadRecyclerAdapter(parentActivity, getSquadDummyData(1)));
gkRecyclerView.setLayoutManager(new MyLinearLayoutManager(parentActivity, LinearLayoutManager.VERTICAL, false));
gkRecyclerView.setHasFixedSize(false);
scrollView.setTouchInterceptionViewGroup((ViewGroup) parentActivity.findViewById(R.id.container));
if (parentActivity instanceof ObservableScrollViewCallbacks) {
scrollView.setScrollViewCallbacks((ObservableScrollViewCallbacks) parentActivity);
}
return view;
}
The XML layout code is:
<com.github.ksoichiro.android.observablescrollview.ObservableScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/squad_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/margin_medium"
>
<LinearLayout
android:id="#+id/squad_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/seasons_scrollview"
android:divider="#drawable/nav_bar_divider"
android:elevation="#dimen/card_elevation"
android:orientation="vertical"
android:showDividers="middle">
<LinearLayout
android:id="#+id/coach_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_coach_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Coach"
android:textSize="#dimen/text_size_standard" />
<android.support.v7.widget.RecyclerView
android:id="#+id/coach_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin_small"
android:paddingBottom="#dimen/margin_small"
android:scrollbars="none">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
<LinearLayout
android:id="#+id/gk_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_gk_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Goalkeepers"
android:textSize="#dimen/text_size_standard" />
<android.support.v7.widget.RecyclerView
android:id="#+id/gk_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/margin_small"
android:paddingBottom="#dimen/margin_small"
android:scrollbars="none">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
<LinearLayout
android:id="#+id/def_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_def_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Defense"
android:textSize="#dimen/text_size_standard" />
</LinearLayout>
<LinearLayout
android:id="#+id/mid_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_mid_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Midfielders"
android:textSize="#dimen/text_size_standard" />
</LinearLayout>
<LinearLayout
android:id="#+id/for_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="#dimen/margin_small"
android:paddingLeft="#dimen/margin_standard"
android:paddingRight="#dimen/margin_standard"
android:paddingTop="#dimen/margin_small">
<TextView
android:id="#+id/squad_for_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Forwards"
android:textSize="#dimen/text_size_standard" />
</LinearLayout>
</LinearLayout>
</com.github.ksoichiro.android.observablescrollview.ObservableScrollView>
The MyLinearLayoutManager is a custom LinearLayoutManager I found online in order to solve the wrap-content issue of the SDK LinearLayoutManager.
Is there any way I can have multiple RecyclerViews in a single layout? It seems that I cannot attach more than one LayoutManagers per layout.
Any assistance would be very welcome :)
I had this problem too. My Activity uses Tabs, with three fragments, when I go to third tab, and back to first (or second), this error is thrown.
After searching a lot, I found out that may be the garbage collector, because I was using a strong reference.
Since the constructor LinearLayoutManager uses the activity as the parameter (not the fragment), a Tabs Activity stays active during tabs changes.
Removing the local field in mLinearLayoutManager from the class, and using a weak reference, I could get rid of this problem:
before:
public class MyFragment1 extends Fragment
private LinearLayoutManager linearLayoutManager;
#Override
public void onCreate(Bundle savedInstanceState) {
linearLayoutManager = new LinearLayoutManager(getActivity());
(...)
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
(...)
mRecyclerView.setLayoutManager(linearLayoutManager);
}
}
I changed to:
public class MyFragment1 extends Fragment {
// private LinearLayoutManager linearLayoutManager;
#Override
public void onCreate(Bundle savedInstanceState) {
// linearLayoutManager = new LinearLayoutManager(getActivity());
(...)
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
(...)
mRecyclerView.setLayoutManager(
new LinearLayoutManager(getActivity()));
}
}
Just need to create a new instance:
RecyclerView recyclerView = new RecyclerView(getContext());
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()))
I faced this error when providing LayoutManager via Dagger. The solution is to replace layout manager injection with layout manager javax.inject.Provider injection.
#Inject
lateinit var layoutManager: Provider<RecyclerView.LayoutManager>
...
recyclerView.setLayoutManager(layoutManager.get())
I have the same problem as well. I work around it by setting null to LinearLayoutManager instance.
public class MyFragment extends Fragment {
protected LinearLayoutManager mLinearLayoutManager;
...
#Override
public void onDestroy() {
super.onDestroy();
if(mLinearLayoutManager != null) // Workaround: android.support.v7.widget.LinearLayoutManager is already attached to a RecyclerView
mLinearLayoutManager = null;
}
I opened FragmentB from FragmentA. Then returned back to FragmentA and got this exception. I found an error. I created in onCreate:
linearLayoutManager = LinearLayoutManager(requireContext())
and used in it onCreateView:
view.recycler_view.layoutManager = linearLayoutManager
Because linearLayoutManager hadn't recreated when we returned from FragmentB, RecyclerView used an old linearLayoutManager. So, I moved linearLayoutManager = LinearLayoutManager(requireContext()) to onCreateView.
In my case, I had declared a LinearLayoutManager globally and I was trying to attach the same instance of LinearLayoutManager to multiple RecyclerView's so I was getting this error.
The Solution is to attach different LayoutManager to each RecyclerView because one LayoutManager can only be attached to one Recyclerview.
I had this problem with Dagger2 and it was solved by removing the Scope Annotation.
I had annotated the code with some scope and when i removed the scope the problem was fixed.
I hope this would be helpful to you.
#MyScope #Provides static LinearLayoutManager provideLinearLayoutManager
I deleted the #MyScope.
This error I faced with Daggar2
and simply remove by using Provider before the LinearLayoutManager like;
#Inject
Provider <LinearLayoutManager> linearLayoutManager;
mViewDataBinding.rvResult.setLayoutManager(linearLayoutManager.get());
Possible options to fix this crash:
Create an instance of LayoutManager in onViewCreated of Fragment:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = LinearLayoutManager(context)
}
If it is necessary to have an instance of LayoutManager as a variable in Fragment, then detach the instance from RecyclerView in onDestroyView:
class MyFragment : Fragment() {
private val myLayoutManager by lazy { LinearLayoutManager(context) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView.layoutManager = myLayoutManager
}
override fun onDestroyView() {
recyclerView.layoutManager = null
super.onDestroyView()
}
}
The second option will work, because the condition for throwing an exception will be false. Here is the code from the method setLayoutManager of RecyclerView:
...
if (layout != null) {
if (layout.mRecyclerView != null) { // will be false
throw new IllegalArgumentException("LayoutManager " + layout
+ " is already attached to a RecyclerView:"
+ layout.mRecyclerView.exceptionLabel());
}
mLayout.setRecyclerView(this);
if (mIsAttached) {
mLayout.dispatchAttachedToWindow(this);
}
}

Categories

Resources