diff --git a/vector/src/main/java/de/spiritcroc/recyclerview/widget/BetterLinearLayoutManager.java b/vector/src/main/java/de/spiritcroc/recyclerview/widget/BetterLinearLayoutManager.java index 71a0ba2c2f..6e97a2b5a3 100644 --- a/vector/src/main/java/de/spiritcroc/recyclerview/widget/BetterLinearLayoutManager.java +++ b/vector/src/main/java/de/spiritcroc/recyclerview/widget/BetterLinearLayoutManager.java @@ -47,7 +47,7 @@ import java.util.List; * A {@link RecyclerView.LayoutManager} implementation which provides * similar functionality to {@link android.widget.ListView}. */ -public class BetterLinearLayoutManager extends LayoutManager implements +public class BetterLinearLayoutManager extends LinearLayoutManager implements ItemTouchHelper.ViewDropHandler, RecyclerView.SmoothScroller.ScrollVectorProvider { private static final String TAG = "LinearLayoutManager"; @@ -179,6 +179,7 @@ public class BetterLinearLayoutManager extends LayoutManager implements */ public BetterLinearLayoutManager(Context context, @RecyclerView.Orientation int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); setOrientation(orientation); setReverseLayout(reverseLayout); } @@ -193,6 +194,7 @@ public class BetterLinearLayoutManager extends LayoutManager implements */ public BetterLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); Properties properties = getProperties(context, attrs, defStyleAttr, defStyleRes); setOrientation(properties.orientation); setReverseLayout(properties.reverseLayout); @@ -322,6 +324,11 @@ public class BetterLinearLayoutManager extends LayoutManager implements * Compatibility support for {@link android.widget.AbsListView#setStackFromBottom(boolean)} */ public void setStackFromEnd(boolean stackFromEnd) { + // mAnchorInfo can be uninitialized during super construction execution. Avoid duplicate execution + if (mAnchorInfo == null) { + return; + } + assertNotInLayoutOrScroll(null); if (mStackFromEnd == stackFromEnd) { return; @@ -352,6 +359,11 @@ public class BetterLinearLayoutManager extends LayoutManager implements * @param orientation {@link #HORIZONTAL} or {@link #VERTICAL} */ public void setOrientation(@RecyclerView.Orientation int orientation) { + // mAnchorInfo can be uninitialized during super construction execution. Avoid duplicate execution + if (mAnchorInfo == null) { + return; + } + if (orientation != HORIZONTAL && orientation != VERTICAL) { throw new IllegalArgumentException("invalid orientation:" + orientation); } @@ -406,6 +418,10 @@ public class BetterLinearLayoutManager extends LayoutManager implements * {@link #setStackFromEnd(boolean)} */ public void setReverseLayout(boolean reverseLayout) { + // mAnchorInfo can be uninitialized during super construction execution. Avoid duplicate execution + if (mAnchorInfo == null) { + return; + } assertNotInLayoutOrScroll(null); if (reverseLayout == mReverseLayout) { return; @@ -2604,4 +2620,4 @@ public class BetterLinearLayoutManager extends LayoutManager implements mFocusable = false; } } -} \ No newline at end of file +} diff --git a/vector/src/main/java/de/spiritcroc/recyclerview/widget/LayoutManager.java b/vector/src/main/java/de/spiritcroc/recyclerview/widget/LinearLayoutManager.java similarity index 64% rename from vector/src/main/java/de/spiritcroc/recyclerview/widget/LayoutManager.java rename to vector/src/main/java/de/spiritcroc/recyclerview/widget/LinearLayoutManager.java index 1ac7e9ab16..6cb5d81777 100644 --- a/vector/src/main/java/de/spiritcroc/recyclerview/widget/LayoutManager.java +++ b/vector/src/main/java/de/spiritcroc/recyclerview/widget/LinearLayoutManager.java @@ -1,14 +1,27 @@ package de.spiritcroc.recyclerview.widget; +import android.content.Context; +import android.util.AttributeSet; import android.view.View; import androidx.recyclerview.widget.RecyclerView; /** - * Exposing/replicating some internal functions from RecylerView.LayoutManager + * Exposing/replicating some internal functions/attributes from RecylerView.LayoutManager */ -public abstract class LayoutManager extends RecyclerView.LayoutManager { +public abstract class LinearLayoutManager extends androidx.recyclerview.widget.LinearLayoutManager { + public LinearLayoutManager(Context context) { + super(context); + } + + public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) { + super(context, orientation, reverseLayout); + } + + public LinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } /* * Exposed things from RecyclerView.java @@ -22,31 +35,31 @@ public abstract class LayoutManager extends RecyclerView.LayoutManager { new ViewBoundsCheck.Callback() { @Override public View getChildAt(int index) { - return LayoutManager.this.getChildAt(index); + return LinearLayoutManager.this.getChildAt(index); } @Override public int getParentStart() { - return LayoutManager.this.getPaddingLeft(); + return LinearLayoutManager.this.getPaddingLeft(); } @Override public int getParentEnd() { - return LayoutManager.this.getWidth() - LayoutManager.this.getPaddingRight(); + return LinearLayoutManager.this.getWidth() - LinearLayoutManager.this.getPaddingRight(); } @Override public int getChildStart(View view) { final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); - return LayoutManager.this.getDecoratedLeft(view) - params.leftMargin; + return LinearLayoutManager.this.getDecoratedLeft(view) - params.leftMargin; } @Override public int getChildEnd(View view) { final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); - return LayoutManager.this.getDecoratedRight(view) + params.rightMargin; + return LinearLayoutManager.this.getDecoratedRight(view) + params.rightMargin; } }; @@ -58,32 +71,32 @@ public abstract class LayoutManager extends RecyclerView.LayoutManager { new ViewBoundsCheck.Callback() { @Override public View getChildAt(int index) { - return LayoutManager.this.getChildAt(index); + return LinearLayoutManager.this.getChildAt(index); } @Override public int getParentStart() { - return LayoutManager.this.getPaddingTop(); + return LinearLayoutManager.this.getPaddingTop(); } @Override public int getParentEnd() { - return LayoutManager.this.getHeight() - - LayoutManager.this.getPaddingBottom(); + return LinearLayoutManager.this.getHeight() + - LinearLayoutManager.this.getPaddingBottom(); } @Override public int getChildStart(View view) { final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); - return LayoutManager.this.getDecoratedTop(view) - params.topMargin; + return LinearLayoutManager.this.getDecoratedTop(view) - params.topMargin; } @Override public int getChildEnd(View view) { final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); - return LayoutManager.this.getDecoratedBottom(view) + params.bottomMargin; + return LinearLayoutManager.this.getDecoratedBottom(view) + params.bottomMargin; } }; diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index a73c7b1b05..0f984e2ad6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -56,7 +56,6 @@ import androidx.core.view.isVisible import androidx.fragment.app.setFragmentResultListener import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.transition.TransitionManager import com.airbnb.epoxy.EpoxyModel @@ -71,6 +70,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.jakewharton.rxbinding3.view.focusChanges import com.jakewharton.rxbinding3.widget.textChanges import com.vanniktech.emoji.EmojiPopup +import de.spiritcroc.recyclerview.widget.BetterLinearLayoutManager import im.vector.app.R import im.vector.app.core.dialogs.ConfirmationDialogBuilder import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper @@ -311,7 +311,7 @@ class RoomDetailFragment @Inject constructor( private lateinit var sharedActionViewModel: MessageSharedActionViewModel private lateinit var knownCallsViewModel: SharedKnownCallsViewModel - private lateinit var layoutManager: LinearLayoutManager + private lateinit var layoutManager: BetterLinearLayoutManager private lateinit var jumpToBottomViewVisibilityManager: JumpToBottomViewVisibilityManager private var modelBuildListener: OnModelBuildFinishedListener? = null @@ -1219,7 +1219,7 @@ class RoomDetailFragment @Inject constructor( timelineEventController.timeline = roomDetailViewModel.timeline views.timelineRecyclerView.trackItemsVisibilityChange() - layoutManager = object : LinearLayoutManager(context, RecyclerView.VERTICAL, true) { + layoutManager = object : BetterLinearLayoutManager(context, RecyclerView.VERTICAL, true) { override fun onLayoutCompleted(state: RecyclerView.State?) { super.onLayoutCompleted(state) updateJumpToReadMarkerViewVisibility()